Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: zsh-3.1.5-pws-5: mixing "old" and "new" completions?
- X-seq: zsh-workers 5083
- From: Sven Wischnowsky <wischnow@xxxxxxxxxxxxxxxxxxxxxxx>
- To: zsh-workers@xxxxxxxxxxxxxx
- Subject: Re: zsh-3.1.5-pws-5: mixing "old" and "new" completions?
- Date: Thu, 28 Jan 1999 15:25:40 +0100 (MET)
- In-reply-to: "Bart Schaefer"'s message of Wed, 27 Jan 1999 23:06:29 -0800
- Mailing-list: contact zsh-workers-help@xxxxxxxxxxxxxx; run by ezmlm
Bart Schaefer wrote:
> Could somebody who's managed to keep track of all this stuff (Sven? Peter?)
> please post a complete summary for _both_ zle -c and zle -C of
>
> * the new commands (compadd, complist, compcall, etc.)
> * the new variables (what's in them and when they're available)
> * the parameters passed to a user's shell functions in each case
>
> Unfortunately, I haven't had time to study Sven's posts enough to do it.
>
> A whole lot of stuff has gone by recently that sounds good in the abstract
> but that feels, in Sven's words, "rather hackish." If it were all written
> down in one place it might become obvious how it could all be made to fit
> together better.
Well...
New style completion stuff:
zle -c name comp func
This defines a widget named `name' that calls the shell function
`func' to produce matches. All the other things completion does, like
displaying a list, deciding what to insert in the line, deciding if
menu-completion should be used and so on is currently only controlled
by the C-code. To allow the user to say how he would like this widget
to behave, (s)he has to give the name of one of the builtin
completion-widgets as the `comp' argument, e.g.:
zle -c my-comp expand-or-complete my-comp-func
Defines the widget `my-comp', makes it call the shell function
`my-comp-func' and makes the completion code behave as if
`expand-or-complete' were used.
Now, inside the shell function the completion code sets up some
variables and offers a few extra builtins and condition codes (the
stuff below is copied and updated from message 4850):
The parameters are:
PREFIX the prefix of the current word from the command line
IPREFIX an ignored prefix (see below)
SUFFIX the suffix of the current word
COMMAND this is something like the `direct context'; for completion
of arguments it contains the command name, but for
subscripts or when completion the right hand side of a
parameter assignment this holds the name of the parameter;
also, when completing a redirection, this holds the
redirection operator itself (the command is still in argv)
CONTEXT the context we are currently completing in, this can be
any of:
`command' we are completing in command position
`argument' we are completing in argument position
`redirect' ... after a redirection operator
`math' ... in a math environment
`subscript' ... in a subscript
`value' ... in the value of an variable assignment
`condition' ... inside `[[...]]'
argv if completing an argument this holds the argument strings
(not including the command name); when completing an
redirection it contains the command line strings (including
the command name); when completing on the right hand side
of an array assignment this holds the strings in the
parentheses
CURRENT this is the index into `argv' pointing to the current word
NMATCHES this is the number of matches produced (and accepted) so far
These variables are settable, the example file contains two convenient
aliases to save and restore them. The completion code uses a wrapper
function to reset them to their old values at the end of each function
executed from the completion widget.
The conditions work on the contents of these variables, probably
changing them, they are modeled directly after the `compctl -x'
condition code:
-prefix str
is true if PREFIX starts with str
-iprefix str
like `-prefix', but makes the matched portion be
ignored; this is done by appending the matched
portion to IPREFIX and removing it from PREFIX
-position beg [end]
is true if we are currently in position `beg' (or between `beg'
and `end' if that is given); if `end' is given COMMAND, CONTEXT,
CURRENT, and argv are changed so that they contain only the range
of words between these positions
(as always when one of these condition takes an integer argument
an expression may be given, like `-position a+1')
-word index str
is true if the `index'th argument is `str'
-mword index pat
like `-word' but with pattern matching
-current index str
-mcurrent index pat
like `-word' and `-mword' but the `index' is take relative to the
current position
-string str
-string index str
true if the current word contains `str'; anything up to the
`index'th occurrence of `str' is ignored (or anything up to the
last occurrence if no `index' is given, again this sets IPREFIX
and PREFIX)
-class str
-class index str
like `-string' but the `str' is taken as a character class
-words min [max]
true if we have at least `min' arguments (and less than or equal
to `max' arguments if that is given)
-between s1 s2
true if we are between an argument equal to `s1' and before an
argument equal to `s2' (if there is such an argument)
-mbetween p1 p2
like `-between' but with pattern matching
-after str
true if we are after an argument equal to `str'
-mafter pat
like `-after' but with pattern matching
-nmatches num
true if we have generated `num' matches
Of course, tests can also be done by using the normal condition stuff
and the above variables (probably changing them), but these condition
codes may be faster and/or easier to use.
The builtins are:
complist ...
This gets almost the same arguments as compctl, except the more
complicated ones (like xor'ed completions, `-x', `-l', ...).
When using this builtin, the completion code uses the current values
of the variables above, so that the combination of this builtin and
the condition codes makes life really simple...
compadd [options] matches...
This allows access to the structure used internally used for storing
matches. When using this builtin the variables are not used and the
completion code does not check if the strings added match what is
one the command line, so you should know what you are doing.
Supported options are:
-q, -Q, -U, -P str, -S str, -J name, -V name
these are used like the options with the same names in compctl and
complist
-f
if this option is given the strings are treated like filenames
(showing files types with LISTTYPES)
-a
this says to put the matches in the alternative set (those that
are build for fignore ignored)
-n
this keeps the strings from appearing in the list of matches
-i str
this gives an ignored previous to use when inserting the match;
such a string is not listed and inserted before a prefix given
with the `-p' option
-p str
this gives another prefix that is not listed; but it is inserted
and used for testing file types
-s str
like `-p' but giving a suffix
When I announced all this I said that this is least stable part of
the new completion stuff because I hadn't had the time to check most
of this. Now, the example file contains a function that heavily uses
this builtin and seems to work fine.
It is intended as a utility to give full control to the things stored
for each match. I would like to add some more functionality to make
it easier to use for things people can be expected to want to have.
For example:
- a flag that says that the matches are filenames and that makes the
code automatically check fignore; this could also automatically
try to list only path name components and the like (but I think we
an extra option to support this would be better, since the results
may probably be unexpected or unwanted)
- a flag that says that normal matching rules should be applied
(together with support for the `-M' option known from compctl and
complist); this is important to have since currently all words
given to compadd are taken even if they don't match what's on the
line, so you have to do all the matching yourself (which can get
complicated if you use `-M'); also, this isn't that hard to add
since most of the code is already there
- a way to specify when a added -S-suffix should be removed
(i.e. after which characters are typed should the suffix be
removed)
Of course, other things may also turn out to be interesting, we'll
see.
compcall [ -[TD] ]
This is the youngets of the builtins. It allows to call the
`compctl'-stuff from a new style completion widget. It takes no
arguments, only two options. Normally, `compctl -T' and `compctl -D'
are not used when calling `compctl's, since I expect this to be used
mainly for command-`compctl's. However, if you want them to be used
you can give the respective option to `compcall' and you'll get them
used. The completion code called is made to believe that the line
looks like the stuff described in the parameters above (PREFIX,...).
For this we needed some conversion and copying-around which may not
be fully correct yet (so here is some code that at least needs some
verifying, more likely some changes).
If this turns out to be interesting enough to stay alive (and I
almost expect it to be), there are many things we might to want add
or change, e.g.:
- make it take arguments which are to be taken as the words the
`compctl'-code should think are on the command line
- let it accept options with strings for the stuff which is
currently taken from the parameters
- for now, the status-return is always zero, it may be interesting
or even important to let it return some useful things; this can be
information about continuing (`compctl -t<c>'), some kind of
signal if a compctl has been processed, and so on.
compctl -K ' foo'
This is as hackish as can be. This special syntax (note the space
before the function name `foo') currently allows us to call `foo'
from `compctl'-code in the same way as new style completion widgets
are called, i.e. with the parameters set up and allowed to call
`complist', `compadd', and `compcall'. I didn't bother to search a
free option character for it (although, if I remember correctly,
there still was one, but not many more than one), because I'm not
too convinced, that we should support this, although I admit that it
may be interesting to have in some cases. But we may as well keep
it, especially since this (currently) adds only two lines of code.
The examples in `new-completion-examples':
This file contains all the code you need to try all this new
completion stuff, including the definition of a completion widget
and the call to `bindkey' to bind it to TAB.
It has two functions to define completion handlers, `defcomp' and
`defpatcomp', where the first defines a handler for commands or one
of the special contexts (like `subscript') and the second one
defines handlers that should be used when the command name matches a
given pattern.
The master function of the code is `main-complete'. It first calls
`compcall' to get access to the old `compctl's, then calls the
equivalent of `-T' and finally has a look at CONTEXT to find out
which handler it should call. If you are completing a command or
argument, `do-complete' is called to handle that, finding matching
patterns and normal handlers or the equivalent of `-D'. This also
emulates the `use last path-name component' and the `=' special
handling done by the `compctl'-completion code.
To really call the handler, `call-complete' is invoked. This looks
up the definition, which may be a array name or a function name. If
it is a function, it is called (and will use `complist', `coompadd',
and friends). If it is an array, `complist' is called with the
contents of the array as arguments. This allows one to keep simple
definitions simple, as in:
defcomp __command --command--
__command=( -c )
For the functions there are some helpers:
- `compsave' and `compreset' can be used to save and restore the
states of the special parameters; this is important to have when
using the conditions and if you want to make more than one test
in the same function
- `compsub' calls `do-complete' again with the current settings of
the special parameters; this is the replacement for `compctl -l'
- `compalso' can be used to add the matches for another command or
special context (intended for e.g. `subscript includes math')
- `pfiles' does partial-path completion. It gets no arguments or
one of `-f', `-/', or `-g' known from `compctl'. If you use `-g'
the patterns to search should be given after the `-g', one per
argument (*not* all in one string). As its first two arguments,
it accepts `-W <paths>' where `<paths>' looks like the things
you can give to `compctl -W'. With all this, `pfiles' is
intended as a replacement for `comp{ctl,list} -[f/g]', giving
you multicomp-like partial path completion everywhere.
- `files' just calls `pfiles' with the arguments it got and, if
that doesn't produce any matches, calls `pfiles' again with no
arguments, producing all filenames. This is a replacement for
`compctl -[f/g] ... + -f'.
Yes, this could do with some work...
One thing that is not yet correct is the continuation-stuff. The
main functions use the return values of the handler functions for
this: zero means that other handlers should be tried, non-zero means
that no more matches should be produced. I still have to check all
the example handler functions if they behave correctly with respect
to this.
Mixed comments (most of them are from the old message):
- I haven't used an associative array for the variables since I would
then like to put [LR]BUFFER and so on into it and I didn't want to
change to many parts of the shell for this first version.
Also: using separate variables makes handling them so easy...
- When using `complist' the completion code still does normal completion
after `~', `=', and `$' (unless that is in IPREFIX, of course).
- Later we may add a way to access the matches produced and to control
what is done with the collected data (inserting, listing, ...)
- With `complist' you can make functions be called with `-K' and `-y'
put they can't use `read' to get at the comamnd line data. This is
because the new style completion uses a different way to store them
(the above parameters).
- When using conditions that change the parameter values the behavior
may be irritating since following tests use the changed values. To
avoid this you have to put the test into a separate function so that
the previous state is automatically restored by the completion code
or you have to restore the state by hand. Since I expect that many
users will want to put all their tests for a command in one function
(making things better readable) restoring by hand and forgetting to
do so in the right places will become inconvenient. This is the
reason for the `compsave' and `compreset' helper aliases, I *really*
would like to find a way to take this burden from the user.
- The condition codes behave a bit different from their `compctl -x'
counterparts since they can only access the arguments (not the
command name).
- The attentive reader of the patch will notice some hunks in zsh.h
and in mem.c. This implement a way to re-use older heaps. In fact
there are functions that allow one to temporarily switch to another
heap, go back to an older heap, and to temporarily switch to another
heap. The patch for zsh.h implements some macros like HEAPALLOC that
make it easy to use this mechanism.
- The value of `COMMAND' may be a bit irritating, since it depends on
the `CONTEXT', we might want to rename it, change it, add another
one, or something like that.
Ok, I hope this helps for now.
Bye
Sven
P.S.: So long a message, and not even a patch, tststs ;-)
--
Sven Wischnowsky wischnow@xxxxxxxxxxxxxxxxxxxxxxx
Messages sorted by:
Reverse Date,
Date,
Thread,
Author