felix
rosencrantz |
Generating
Clearcase Completions |
process
|
Using perl and XML I've been
attempting to automatically (or semi-automatically) generate ZSH completion
functions. As a test case for a complex command that has sub-commands
I wanted to try generating completions for the Clearcase cleartool command.
It should be possible to automatically generate completion functions that
can complete flags. However, it will still require a person to create
functions that complete different types of arguments (e.g. a listing of
label types, or branch types).
I use to work with Clearcase. I had some rudimentary completion
functions in tcsh and zsh. The problem I had was that as new versions of
Clearcase were released the functions had to change since there would be new
subcommands, new flags, or changed flags. Also, depending on the
licenses, some machines might have some subcommands that other hosts don't.
Being able to generate completion functions from Clearcase documentation
would make a significant difference.
Here is the process I used to create these functions. Ideally it would be
possible for do this for |
step 1
|
Create an output file of Clearcase help
commands.
cleartool help >
ct_help.out
The help command without any arguments will list help
for all subcommands. The help output contains basic command line usage
descriptions without flag descriptions. I made this file when I had
access to Clearcase. |
step 2 |
Parse the help output to create an xml file.
To do this I wrote a perl script. This script is fairly specific to
this help output. Though, hopefully, it should be possible to make
this more general, to be useful for other tools. (I needed to install
the Text::Balanced package.)
perl parse_ct.pl
ct_help.out >
ct_helpA.xml
The generated xml file is a format that should be easy
to create from the above perl script, and then via various XSLT
transformations generate an XML file that can be used with
args.xsl.
So from the chview command usage:
cleartool chview {[-cachesize
size] [-shareable_dos | -nshareable_dos] [-readonly | -readwrite]} {-cview
| view-tag}
The perl script generates output that looks like:
<subcommand
cmd='chview'>
<!-- chview {[-cachesize size] [-shareable_dos | -nshareable_dos]
[-readonly | -readwrite]} {-cview | view-tag} -->
<brace>
<brace>
<flag name='-cachesize'/>
<word name='size'/>
</brace>
<brace>
<flag name='-shareable_dos'/>
<or/>
<flag name='-nshareable_dos'/>
</brace>
<brace>
<flag name='-readonly'/>
<or/>
<flag name='-readwrite'/>
</brace>
</brace>
<brace>
<flag name='-cview'/>
<or/>
<word name='view-tag'/>
</brace>
<!-- mapping ((fw)(f|f)(f|f))(f|w) -->
</subcommand> |
|
step 3 |
This step transforms the XML generated in step2 to something that is a
little easier to generate the completion XML format. The basic
transforms are:
- Add a <flagset> node to each <subcommand>. <flagset> holds a list of
all the flags that this command has. This is useful for performing
iterations when generating the _arguments call.
- Wrap the contents in a <content> node. This is useful since we
added the <flagset> node to <subcommand>.
- Convert the <or> tags into a hierarchy. With a root of <group>,
that only has <or> children.
saxon
ct_helpA.xml s1.xsl >
ct_helpB.xml
So the XML output from the previous step on the chview subcommand now
looks like:
<subcommand cmd="chview">
<flagset>
<flag name="-cachesize"/>
<flag name="-cview"/>
<flag name="-nshareable_dos"/>
<flag name="-readonly"/>
<flag name="-readwrite"/>
<flag name="-shareable_dos"/>
</flagset>
<contents>
<brace>
<brace>
<flag name="-cachesize"/>
<word name="size"/>
</brace>
<brace>
<group>
<or end="2">
<flag name="-shareable_dos"/>
</or>
<or start="2" end="4">
<flag name="-nshareable_dos"/>
</or>
</group>
</brace>
<brace>
<group>
<or end="2">
<flag name="-readonly"/>
</or>
<or start="2" end="4">
<flag name="-readwrite"/>
</or>
</group>
</brace>
</brace>
<brace>
<group>
<or end="2">
<flag name="-cview"/>
</or>
<or start="2" end="4">
<word name="view-tag"/>
</or>
</group>
</brace>
</contents>
</subcommand> |
|
step 4 |
Another transformation to get closer to the
completion format. The basic transformations are:
- Make <flagset> have a unique set of flags. Some commands had the
same flag listed multiple times.
- Group flags with their arguments. In ct_helpB.xml, <flag> nodes were
leave nodes. Now they have children for their arguments.
(There are some problems with this transform, that causes some flags to
get extra arguments.)
- Look for the pattern -flag {const1|const2|const3}, and convert this to
constant word set. (This is not shown in the example. To see an
example look at the "find -type" flag.)
saxon
ct_helpB.xml s2.xsl >
ct_helpC.xml
So the chview command now looks like:
<subcommand cmd="chview">
<flagset>
<flag name="-cachesize"/>
<flag name="-cview"/>
<flag name="-nshareable_dos"/>
<flag name="-readonly"/>
<flag name="-readwrite"/>
<flag name="-shareable_dos"/>
</flagset>
<contents>
<brace>
<brace>
<flag name="-cachesize">
<flag_word name="size"/>
</flag>
</brace>
<brace>
<group>
<or end="2">
<flag name="-shareable_dos"/>
</or>
<or start="2" end="4">
<flag name="-nshareable_dos"/>
</or>
</group>
</brace>
<brace>
<group>
<or end="2">
<flag name="-readonly"/>
</or>
<or start="2" end="4">
<flag name="-readwrite"/>
</or>
</group>
</brace>
</brace>
<brace>
<group>
<or end="2">
<flag name="-cview"/>
</or>
<or start="2" end="4">
<word name="view-tag"/>
</or>
</group>
</brace>
</contents>
</subcommand> |
|
step 5 |
We now have a format that is easier to generate
thecompletion XML format. This file contains header information that
is copied directly to the ct_args.xml file. The rest is generated from
the input of ct_helpC.xml.
saxon
ct_helpC.xml s3.xsl >
ct_args.xml
Here is the start of chview:
<subcommand name="chview">
<service>
<arguments/>
<argspecs>
<argspec>
<optspec>
<flagarg name="-cachesize">
<explanation/>
</flagarg>
</optspec>
<description>
<message/>
<action tag="size"/>
</description>
</argspec>
<argspec>
<optspec>
<exclusionlist/>
<flagarg name="-cview">
<explanation/>
</flagarg>
</optspec>
<description>
<message/>
</description>
</argspec>
<argspec>
<optspec>
<exclusionlist>
<flag>-shareable_dos</flag>
</exclusionlist>
<flagarg name="-nshareable_dos">
<explanation/>
</flagarg>
</optspec>
<description>
<message/> |
|
step 6 |
The final step to generate the completion
function. However, before we can do that we need to generate an
include file that says how to map action tags to actual actions. For
example, the chview command's flag -cachesize has an action with the tag
'size'. The include file can map that to an action. The next
few steps are an attempt to generate this include file based on data
on the ct_args.xml file. The first xsl script does the following:
- Extract all the action elements, and converts them to actiontemplates,
which is close to the final format.
saxon
ct_args.xml gen_comdefs.xsl >
defsA.xml
Some of the output looks like:
<actiontemplate tag="command-name">
<action> </action>
</actiontemplate>
<actiontemplate tag="command-name">
<action> </action>
</actiontemplate>
<actiontemplate tag="topic">
<action> </action>
</actiontemplate> |
|
step 7 |
This step removes duplicates. This should have
been done in the previous step.
saxon defsA.xml
unique_actions.xsl >
defsB.xml
|
step 8 |
The purpose of this step is to insert actions
into the generated include file. The action.xup script has
hand-coded mappings of tags to action. This step uses a transform language
other than XSLT, called xupdate,. XSLT could be used, though I found
xupdate did more of what I wanted for this situation. The perl
script cleans up some of the resulting XML, removing a bogus doctype
instruction.
xupdate actions.xup defsB.xml >
defsC.xml
perl -p -e 's/<!DOCTYPE root>//;'
defsC.xml >
clearcase_defines.xml
Xupdate information can be found
here. I had to
make changes to the
XUpdateQueryImpl.java to be
able to use xupdate on the command line. |
step 9 |
The final step. We've generated the
ct_args.xml file, and the includes file. Now we can generate the
actual completion function.
saxon
ct_args.xml arg.xsl >
_cleartool
Now the completion for chview:
(( $+functions[_cc_chview] )) ||
_cc_chview () {
_arguments \
'-cachesize:Handling Tag size' \
'()-cview' \
'(-shareable_dos)-nshareable_dos' \
'(-readwrite)-readonly' \
'(-readonly)-readwrite' \
'(-nshareable_dos)-shareable_dos' \
'1:Handling Tag view-tag:_cc_views'
}
|
|
problems |
This does a reasonable first draft.
Though it still has a lot of problems.
- No way to attach help messages/explanations
- Problem with dealing with commands that have multiple formats for
example mkview. Currently generate multiple functions. So the last
function is the one that is used.
- Problem determining command args vs. flag args. (Look at "get" command.
flag is followed by 2 words...)
- Generating sets that are a list, -types A,B,C (is there an example?)
- Find command has a problem with multiple anypositions.
- Find command has problem in that flags will only be allowed once.
- The clearcase command has some flags, these are exclusive of clearcase
commands. But currently that is not how it works.
- This does not handle flag abbreviations. Clearcase allow users
to abbreviate flag names.
- Problem generating exclusion list for flags version anypostion.
See chview command with -cview flag.
- Sure there are dozens of other problems...
|
files |
|
|
Web site
Copyright © 2001 Felix Rosencrantz,
f_rosencrantz@yahoo.com |