* Per command _redirect completion @ 2002-02-25 5:59 Felix Rosencrantz 2002-02-25 8:18 ` Sven Wischnowsky 2002-02-25 9:47 ` Oliver Kiddle 0 siblings, 2 replies; 15+ messages in thread From: Felix Rosencrantz @ 2002-02-25 5:59 UTC (permalink / raw) To: zsh-workers Below is a proposed change for the _redirect completion function. If there is a function with the name _redirect:COMMAND, that function is called to perform completion. Otherwise, the default behavior of completing files is performed. This is the way we do variable specific dispatch for _value. If there are no objections, I'll create a real diff and checkin. -FR. --------------------------------------------------------------------------- #compdef -redirect- if (( $+functions[_redirect:$words[1]] )); then "_redirect:$words[1]" "$@" else _files fi __________________________________________________ Do You Yahoo!? Yahoo! Sports - Coverage of the 2002 Olympic Games http://sports.yahoo.com ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Per command _redirect completion 2002-02-25 5:59 Per command _redirect completion Felix Rosencrantz @ 2002-02-25 8:18 ` Sven Wischnowsky 2002-02-25 9:47 ` Oliver Kiddle 1 sibling, 0 replies; 15+ messages in thread From: Sven Wischnowsky @ 2002-02-25 8:18 UTC (permalink / raw) To: zsh-workers Felix Rosencrantz wrote: > Below is a proposed change for the _redirect completion function. If there > is a function with the name _redirect:COMMAND, that function is called > to perform completion. Otherwise, the default behavior of completing files > is performed. This is the way we do variable specific dispatch for _value. Makes sense, I think. Bye Sven -- Sven Wischnowsky wischnow@berkom.de ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Per command _redirect completion 2002-02-25 5:59 Per command _redirect completion Felix Rosencrantz 2002-02-25 8:18 ` Sven Wischnowsky @ 2002-02-25 9:47 ` Oliver Kiddle 2002-02-26 6:56 ` Felix Rosencrantz 1 sibling, 1 reply; 15+ messages in thread From: Oliver Kiddle @ 2002-02-25 9:47 UTC (permalink / raw) To: Felix Rosencrantz; +Cc: zsh-workers --- Felix Rosencrantz <f_rosencrantz@yahoo.com> wrote: > Below is a proposed change for the _redirect completion function. If > there > is a function with the name _redirect:COMMAND, that function is > called > to perform completion. Otherwise, the default behavior of completing > files > is performed. This is the way we do variable specific dispatch for > _value. > > If there are no objections, I'll create a real diff and checkin. I would prefer if - both for redirection and for values - we had separate associative arrays like _comps. And then, perhaps a compdef option for adding to these new associations. This is for a number of reasons, one being consistency with the way we handle commands. Many of the _value: functions just call one other function. It'd be better if instead, for example we could specify in the #compdef on _x_display to handle the $DISPLAY variable. Also, in many cases what should be completed is already being done in another function. For example, $GZIP should complete gzip options. It'd be more useful to direct this into _gzip where gzip options are already completed and _gzip would just need a compstate test. This redirection suggestion is even more linked to the command being run and again it would be more useful to use the existing command's completion function and have it work out what sort of files to complete. Oliver __________________________________________________ Do You Yahoo!? Everything you'll ever need on one web page from News and Sport to Email and Music Charts http://uk.my.yahoo.com ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Per command _redirect completion 2002-02-25 9:47 ` Oliver Kiddle @ 2002-02-26 6:56 ` Felix Rosencrantz 2002-02-26 8:44 ` Sven Wischnowsky 0 siblings, 1 reply; 15+ messages in thread From: Felix Rosencrantz @ 2002-02-26 6:56 UTC (permalink / raw) To: Oliver Kiddle; +Cc: zsh-workers --- Oliver Kiddle <okiddle@yahoo.co.uk> wrote: > I would prefer if - both for redirection and for values - we had > separate associative arrays like _comps. And then, perhaps a compdef > option for adding to these new associations. > > This is for a number of reasons, one being consistency with the way we > handle commands. ... > This redirection suggestion is even more linked to the command being > run and again it would be more useful to use the existing command's > completion function and have it work out what sort of files to > complete. Yep, that's exactly why I asked, there is an inconsistency. Though, I'm not volunteering to graft redirection and value/parameter onto the _comps or a similar array. Would have to be a job for someone else. Though I would like to see better completion for redirection. Redirection is one of those situations where the file may not already exist, so better guessing tricks would be useful. -FR __________________________________________________ Do You Yahoo!? Yahoo! Sports - Coverage of the 2002 Olympic Games http://sports.yahoo.com ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Per command _redirect completion 2002-02-26 6:56 ` Felix Rosencrantz @ 2002-02-26 8:44 ` Sven Wischnowsky 2002-02-27 9:35 ` Sven Wischnowsky 0 siblings, 1 reply; 15+ messages in thread From: Sven Wischnowsky @ 2002-02-26 8:44 UTC (permalink / raw) To: zsh-workers Felix Rosencrantz wrote: > --- Oliver Kiddle <okiddle@yahoo.co.uk> wrote: > > I would prefer if - both for redirection and for values - we had > > separate associative arrays like _comps. And then, perhaps a compdef > > option for adding to these new associations. > > > > This is for a number of reasons, one being consistency with the way we > > handle commands. ... > > This redirection suggestion is even more linked to the command being > > run and again it would be more useful to use the existing command's > > completion function and have it work out what sort of files to > > complete. > > Yep, that's exactly why I asked, there is an inconsistency. Though, I'm not > volunteering to graft redirection and value/parameter onto the _comps or a > similar array. Would have to be a job for someone else. I would try to make compdef and parts of _normal (and probably _complete) generic enough to use an assoc given as argument, so that we get the pattern and services stuff. I think I'll give it a try. Bye Sven -- Sven Wischnowsky wischnow@berkom.de ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Per command _redirect completion 2002-02-26 8:44 ` Sven Wischnowsky @ 2002-02-27 9:35 ` Sven Wischnowsky 2002-02-27 13:10 ` Oliver Kiddle 2002-02-28 6:35 ` Felix Rosencrantz 0 siblings, 2 replies; 15+ messages in thread From: Sven Wischnowsky @ 2002-02-27 9:35 UTC (permalink / raw) To: zsh-workers I wrote: > ... > > I would try to make compdef and parts of _normal (and probably > _complete) generic enough to use an assoc given as argument, so that > we get the pattern and services stuff. Here is a first implementation, not in its final shape, so I'm not going to commit it right now. But maybe some of you want to play with it and give me some input. Remarks (in no particular order): - To try this, you should remove your dump-file. - Most of the changes are currently in _normal. I'm planning to change that, putting parts of it in a separate function that will be called from _normal, _value and _redirect. That function will also handle a -defult- context so that calling functions don't have to implement defaults themselves (see _redirect for an example). I'm searching a good name for this function and the whole concept, actually. If you look at the docs, you'll see that I was struggling and called it `type of completion function'. It's basically a new intermediate level, something like multiple sets of definitions. Any suggestions? (Besides trying to make this clearer in the docs?) That `type of ...' led to the naming of the compdef-option (-T). - That new helper function will then get the name of the completion function type and the strings to use to look up definitions. For normal completion this will be the command name(s), for redirection I'd prefer a combination of command name and redirection operator. Then we could use a pattern-definition to write a function called for all output redirections and so on[*]. For values we currently use only the parameter name. For things like `make FOO=<TAB>' we might want to include the command name, too. And probably the parameter type, if it is known. Any other suggestions? - The other important part to look at are the new _value_* functions, showing how this is used. - Currently there is a _comp_assocs array defined in compinit that contains the known names of types (comps, redirs, values). It would be nice if we could make this obsolete, probably making compdef() collect the type names and creating the associative arrays when needed. compdump would then have to be changed to output calls to `typeset -gA ...'. - I wished there were an easier way than to use `${(e):-...}' in so many places. Sigh. - Does anyone know about other places than redirections and values where this might be interesting to use? Even now it is already easy to define more sets. - _compdef isn't changed yet. And one (mostly) unrelated remark: in a private mail Oliver asked if it were possible to supply the completion widgets with a list of redirections on the line. Collecting this information shouldn't be too complicated. Any suggestions for how we should pas this information to the completion function? An array containing values of the form `<redir-op>:<word>'? Bye Sven [*] Leading to a function that is to be called to complete non-existing files, that can also be used for mv and others. diff -ur -r ../oz/Completion/Base/Completer/_complete ./Completion/Base/Completer/_complete --- ../oz/Completion/Base/Completer/_complete Tue Feb 26 20:56:19 2002 +++ ./Completion/Base/Completer/_complete Tue Feb 26 21:31:26 2002 @@ -95,7 +95,7 @@ comp="$_comps[-first-]" if [[ -n "$comp" ]]; then - service="${_services[-first-]:--first-}" + service="${_servicecomps[-first-]:--first-}" ccarray[3]=-first- eval "$comp" && ret=0 if [[ "$_compskip" = all ]]; then @@ -124,7 +124,7 @@ ccarray[3]="$cname" comp="$_comps[$cname]" - service="${_services[$cname]:-$cname}" + service="${_servicecomps[$cname]:-$cname}" # If not, we use default completion, if any. @@ -136,7 +136,7 @@ comp="$_comps[-default-]" fi [[ -n "$comp" ]] && - service="${_services[-default-]:--default-}" && eval "$comp" && ret=0 + service="${_servicecomps[-default-]:--default-}" && eval "$comp" && ret=0 fi _compskip= diff -ur -r ../oz/Completion/Base/Core/_normal ./Completion/Base/Core/_normal --- ../oz/Completion/Base/Core/_normal Tue Feb 26 20:56:19 2002 +++ ./Completion/Base/Core/_normal Wed Feb 27 00:13:48 2002 @@ -1,55 +1,78 @@ #compdef -command-line- -local comp command cmd1 cmd2 pat val name i ret=1 _compskip="$_compskip" +local comp command pat val name i ret=1 _compskip="$_compskip" local curcontext="$curcontext" service +local _comp_command1 _comp_command2 +local __comps __patcomps __postpatcomps __services # If we get the option `-s', we don't reset `_compskip'. This ensures # that a value set in the function for the `-first-' context is kept, # but that we still use pattern functions when we were called form # another completion function. -[[ "$1" = -s ]] || _compskip='' +if [[ "$1" = -s ]]; then + shift +else + _compskip='' +fi -# Completing in command position? If not we set up `cmd1' and `cmd2' as -# two strings we have to search in the completion definition arrays (e.g. -# a path and the last path name component). +if (( ! $# )); then -command="$words[1]" -if [[ CURRENT -eq 1 ]]; then - curcontext="${curcontext%:*:*}:-command-:" + # Completing in command position? - comp="$_comps[-command-]" - [[ -n "$comp" ]] && eval "$comp" && ret=0 + if [[ CURRENT -eq 1 ]]; then + curcontext="${curcontext%:*:*}:-command-:" - return ret -else - if (( $+builtins[$command] + $+functions[$command] )); then - cmd1="$command" - curcontext="${curcontext%:*:*}:${cmd1}:" + comp="$_comps[-command-]" + [[ -n "$comp" ]] && eval "$comp" && ret=0 + + return ret + fi + + 1=comps +fi + +__comps=_$1 +__patcomps=_pat$1 +__postpatcomps=_postpat$1 +__services=_service$1 + +# Not completing in command position. We set up `_comp_command1' and +# `_comp_command2' as two strings we have to search in the completion +# definition arrays (e.g. a path and the last path name component). + +if [[ -n $+_comp_command1 ]]; then + command="$words[1]" + if [[ "$compstate[context]" = *value ]]; then + _comp_command1="$compstate[parameter]" + curcontext="${curcontext%:*:*}:${_comp_command1}:" + elif (( $+builtins[$command] + $+functions[$command] )); then + _comp_command1="$command" + curcontext="${curcontext%:*:*}:${_comp_command1}:" elif [[ "$command[1]" = '=' ]]; then - eval cmd1\=$command - cmd2="$command[2,-1]" - curcontext="${curcontext%:*:*}:${cmd2}:" + eval _comp_command1\=$command + _comp_command2="$command[2,-1]" + curcontext="${curcontext%:*:*}:${_comp_command2}:" elif [[ "$command" = ..#/* ]]; then - cmd1="${PWD}/$command" - cmd2="${command:t}" - curcontext="${curcontext%:*:*}:${cmd2}:" + _comp_command1="${PWD}/$command" + _comp_command2="${command:t}" + curcontext="${curcontext%:*:*}:${_comp_command2}:" elif [[ "$command" = */* ]]; then - cmd1="$command" - cmd2="${command:t}" - curcontext="${curcontext%:*:*}:${cmd2}:" + _comp_command1="$command" + _comp_command2="${command:t}" + curcontext="${curcontext%:*:*}:${_comp_command2}:" else - cmd1="$command" - cmd2="$commands[$command]" - curcontext="${curcontext%:*:*}:${cmd1}:" + _comp_command1="$command" + _comp_command2="$commands[$command]" + curcontext="${curcontext%:*:*}:${_comp_command1}:" fi fi # See if there are any matching pattern completions. if [[ "$_compskip" != (all|*patterns*) ]]; then - service="${_services[$cmd1]:-$cmd1}" - for i in "${(@)_patcomps[(K)$cmd1]}"; do + service="${${(e):-\$${__services}[$_comp_command1]}:-$_comp_command1}" + for i in "${(@e):-\$${__patcomps}[(K)$_comp_command1]}"; do "$i" && ret=0 if [[ "$_compskip" = *patterns* ]]; then break @@ -58,9 +81,9 @@ return ret fi done - if [[ -n "$cmd2" ]]; then - service="${_services[$cmd2]:-$cmd2}" - for i in "${(@)_patcomps[(K)$cmd2]}"; do + if [[ -n "$_comp_command2" ]]; then + service="${${(e):-\$${__services}[$_comp_command2]}:-$_comp_command2}" + for i in "${(@e):-\$${__patcomps}[(K)$_comp_command2]}"; do "$i" && ret=0 if [[ "$_compskip" = *patterns* ]]; then break @@ -75,12 +98,13 @@ # Now look up the two names in the normal completion array. ret=1 -name="$cmd1" -comp="$_comps[$cmd1]" -service="${_services[$cmd1]:-$cmd1}" - -[[ -z "$comp" ]] && - name="$cmd2" comp="$_comps[$cmd2]" service="${_services[$cmd2]:-$cmd2}" +name="$_comp_command1" +comp="${(e):-\$${__comps}[$_comp_command1]}" +service="${${(e):-\$${__services}[$_comp_command1]}:-$_comp_command1}" + +[[ -z "$comp" && -n "$_comp_command2" ]] && + name="$_comp_command2" comp="${(e):-\$${__comps}[$_comp_command2]}" \ + service="${${(e):-\$${__services}[$_comp_command2]}:-$_comp_command2}" # And generate the matches, probably using default completion. @@ -88,14 +112,14 @@ _compskip=patterns eval "$comp" && ret=0 [[ "$_compskip" = (all|*patterns*) ]] && return ret -elif [[ "$_compskip" != *default* ]]; then +elif [[ "$1" = comps && "$_compskip" != *default* ]]; then name=-default- comp="$_comps[-default-]" fi if [[ "$_compskip" != (all|*patterns*) ]]; then - service="${_services[$cmd1]:-$cmd1}" - for i in "${(@)_postpatcomps[(K)$cmd1]}"; do + service="${${(e):-\$${__services}[$_comp_command1]}:-$_comp_command1}" + for i in "${(@e):-\$${__postpatcomps}[(K)$_comp_command1]}"; do _compskip=default "$i" && ret=0 if [[ "$_compskip" = *patterns* ]]; then @@ -105,9 +129,9 @@ return ret fi done - if [[ -n "$cmd2" ]]; then - service="${_services[$cmd2]:-$cmd2}" - for i in "${(@)_postpatcomps[(K)$cmd2]}"; do + if [[ -n "$_comp_command2" ]]; then + service="${${(e):-\$${__services}[$_comp_command2]}:-$_comp_command2}" + for i in "${(@e):-\$${__postpatcomps}[(K)$_comp_command2]}"; do _compskip=default "$i" && ret=0 if [[ "$_compskip" = *patterns* ]]; then @@ -120,8 +144,10 @@ fi fi -[[ "$name" = -default- && -n "$comp" && "$_compskip" != (all|*default*) ]] && - service="${_services[-default-]:--default-}" && eval "$comp" && ret=0 +[[ "$1" = comps && "$name" = -default- && -n "$comp" && + "$_compskip" != (all|*default*) ]] && + service="${${(e):-${__services}[-default-]}:--default-}" && + eval "$comp" && ret=0 _compskip='' diff -ur -r ../oz/Completion/Base/Utility/_contexts ./Completion/Base/Utility/_contexts --- ../oz/Completion/Base/Utility/_contexts Tue Feb 26 20:56:19 2002 +++ ./Completion/Base/Utility/_contexts Tue Feb 26 23:44:51 2002 @@ -6,8 +6,19 @@ # For example the function for `-subscript-' could call this as in # `_contexts -math-' to get the completions that would be generated for a # mathematical context. +# You may also select the assocs to use with the `-T assoc' option. -local i tmp ret=1 service or +local i tmp ret=1 service or type + +type=(-T comps) +zparseopts -D o=or T:=type + +type="$type[2]" +if (( $#or )); then + or=yes +else + or= +fi if [[ $1 = -o ]]; then or=yes @@ -15,8 +26,9 @@ fi for i; do - tmp="$_comps[$i]" - [[ -n "$tmp" ]] && service="${_services[$i]:-$i}" && eval "$tmp" && ret=0 + tmp="${(e):-\$_${type}[$i]}" + [[ -n "$tmp" ]] && service="${${(e):-\$_service${type}[$i]}:-$i}" && + eval "$tmp" && ret=0 [[ -n "$or" && ret -eq 0 ]] && return 0 done diff -ur -r ../oz/Completion/Zsh/Context/_redirect ./Completion/Zsh/Context/_redirect --- ../oz/Completion/Zsh/Context/_redirect Tue Feb 26 20:56:19 2002 +++ ./Completion/Zsh/Context/_redirect Tue Feb 26 22:56:48 2002 @@ -1,3 +1,3 @@ #compdef -redirect- -_files +_normal redirs || _files diff -ur -r ../oz/Completion/Zsh/Context/_value ./Completion/Zsh/Context/_value --- ../oz/Completion/Zsh/Context/_value Wed Feb 27 00:14:27 2002 +++ ./Completion/Zsh/Context/_value Wed Feb 27 00:09:28 2002 @@ -1,70 +1,29 @@ #compdef -value- -array-value- -_value () { - # You can customize completion for different parameters by writing a - # function `_value:<name>', where <name> is the name of the parameter. - # When completing values of elements of associative arrays, we first - # search for a function `_value:<assoc>-<key>' and then for - # `_value:<assoc>', so it's simple to define different functions - # for different keys or one function for a whole association. +# You can customize completion for different parameters by writing +# functions with the tag-line `#compdef -T value <name>'. - if (( $+functions[_value:$compstate[parameter]] )); then - "_value:$compstate[parameter]" "$@" - elif (( $+functions[_value:${compstate[parameter]%%-*}] )); then - "_value:${compstate[parameter]%%-*}" "$@" - elif [[ "$compstate[parameter]" != *-* && - "${(Pt)${compstate[parameter]}}" = assoc* ]]; then - if (( CURRENT & 1 )); then - _wanted association-keys expl 'association key' \ - compadd -k "$compstate[parameter]" - else - compstate[parameter]="${compstate[parameter]}-${words[CURRENT-1]}" - _value "$@" - fi - else - local pats - - if { zstyle -a ":completion:${curcontext}:" assign-list pats && - [[ "$compstate[parameter]" = (${(j:|:)~pats}) ]] } || - [[ "$PREFIX$SUFFIX" = *:* ]]; then - compset -P '*:' - compset -S ':*' - _default -r '\-\n\t /:' "$@" - else - _default "$@" - fi - fi -} +_normal value && return 0 -_value:CPPFLAGS () { - compset -q - if compset -P '-I'; then - _files -/ "$@" +if [[ "$compstate[parameter]" != *-* && + "${(Pt)${compstate[parameter]}}" = assoc* ]]; then + if (( CURRENT & 1 )); then + _wanted association-keys expl 'association key' \ + compadd -k "$compstate[parameter]" else - _default "$@" + compstate[parameter]="${compstate[parameter]}-${words[CURRENT-1]}" + _value "$@" fi -} +else + local pats -_value:LDFLAGS () { - compset -q - if compset -P '-L'; then - _files -/ "$@" - elif compset -P '-R'; then + if { zstyle -a ":completion:${curcontext}:" assign-list pats && + [[ "$compstate[parameter]" = (${(j:|:)~pats}) ]] } || + [[ "$PREFIX$SUFFIX" = *:* ]]; then compset -P '*:' compset -S ':*' - _files -/ -S/ -r '\n\t\- /:' "$@" + _default -r '\-\n\t /:' "$@" else _default "$@" fi -} - -_value:DISPLAY() { _x_display "$@" } - -_value:PRINTER() { _printers "$@" } -_value:LPDEST() { _printers "$@" } - -_value:TERM() { _terminals "$@" } - -_value:TZ() { _time_zone "$@" } - -_value "$@" +fi diff -ur -r ../oz/Completion/Zsh/Context/_value_CPPFLAGS ./Completion/Zsh/Context/_value_CPPFLAGS --- ../oz/Completion/Zsh/Context/_value_CPPFLAGS Wed Feb 27 00:14:27 2002 +++ ./Completion/Zsh/Context/_value_CPPFLAGS Wed Feb 27 00:25:03 2002 @@ -0,0 +1,8 @@ +#compdef -T values CPPFLAGS + +compset -q +if compset -P '-I'; then + _files -/ "$@" +else + _default "$@" +fi diff -ur -r ../oz/Completion/Zsh/Context/_value_DISPLAY ./Completion/Zsh/Context/_value_DISPLAY --- ../oz/Completion/Zsh/Context/_value_DISPLAY Wed Feb 27 00:14:27 2002 +++ ./Completion/Zsh/Context/_value_DISPLAY Wed Feb 27 00:25:31 2002 @@ -0,0 +1,3 @@ +#compdef -T values DISPLAY + +_x_display diff -ur -r ../oz/Completion/Zsh/Context/_value_LDFLAGS ./Completion/Zsh/Context/_value_LDFLAGS --- ../oz/Completion/Zsh/Context/_value_LDFLAGS Wed Feb 27 00:14:27 2002 +++ ./Completion/Zsh/Context/_value_LDFLAGS Wed Feb 27 00:25:24 2002 @@ -0,0 +1,12 @@ +#compdef -T values LDFLAGS + +compset -q +if compset -P '-L'; then + _files -/ "$@" +elif compset -P '-R'; then + compset -P '*:' + compset -S ':*' + _files -/ -S/ -r '\n\t\- /:' "$@" +else + _default "$@" +fi diff -ur -r ../oz/Completion/Zsh/Context/_value_PRINTER ./Completion/Zsh/Context/_value_PRINTER --- ../oz/Completion/Zsh/Context/_value_PRINTER Wed Feb 27 00:14:27 2002 +++ ./Completion/Zsh/Context/_value_PRINTER Wed Feb 27 00:25:12 2002 @@ -0,0 +1,3 @@ +#compdef -T values PRINTER LPDEST + +_printers diff -ur -r ../oz/Completion/Zsh/Context/_value_TERM ./Completion/Zsh/Context/_value_TERM --- ../oz/Completion/Zsh/Context/_value_TERM Wed Feb 27 00:14:27 2002 +++ ./Completion/Zsh/Context/_value_TERM Wed Feb 27 00:25:42 2002 @@ -0,0 +1,3 @@ +#compdef -T values TERM + +_terminals diff -ur -r ../oz/Completion/Zsh/Context/_value_TZ ./Completion/Zsh/Context/_value_TZ --- ../oz/Completion/Zsh/Context/_value_TZ Wed Feb 27 00:14:27 2002 +++ ./Completion/Zsh/Context/_value_TZ Wed Feb 27 00:25:49 2002 @@ -0,0 +1,3 @@ +#compdef -T values TZ + +_time_zone diff -ur -r ../oz/Completion/Zsh/Context/_value~ ./Completion/Zsh/Context/_value~ --- ../oz/Completion/Zsh/Context/_value~ Wed Feb 27 00:14:27 2002 +++ ./Completion/Zsh/Context/_value~ Fri Feb 22 14:25:41 2002 @@ -0,0 +1,70 @@ +#compdef -value- -array-value- + +_value () { + # You can customize completion for different parameters by writing a + # function `_value:<name>', where <name> is the name of the parameter. + # When completing values of elements of associative arrays, we first + # search for a function `_value:<assoc>-<key>' and then for + # `_value:<assoc>', so it's simple to define different functions + # for different keys or one function for a whole association. + + if (( $+functions[_value:$compstate[parameter]] )); then + "_value:$compstate[parameter]" "$@" + elif (( $+functions[_value:${compstate[parameter]%%-*}] )); then + "_value:${compstate[parameter]%%-*}" "$@" + elif [[ "$compstate[parameter]" != *-* && + "${(Pt)${compstate[parameter]}}" = assoc* ]]; then + if (( CURRENT & 1 )); then + _wanted association-keys expl 'association key' \ + compadd -k "$compstate[parameter]" + else + compstate[parameter]="${compstate[parameter]}-${words[CURRENT-1]}" + _value "$@" + fi + else + local pats + + if { zstyle -a ":completion:${curcontext}:" assign-list pats && + [[ "$compstate[parameter]" = (${(j:|:)~pats}) ]] } || + [[ "$PREFIX$SUFFIX" = *:* ]]; then + compset -P '*:' + compset -S ':*' + _default -r '\-\n\t /:' "$@" + else + _default "$@" + fi + fi +} + +_value:CPPFLAGS () { + compset -q + if compset -P '-I'; then + _files -/ "$@" + else + _default "$@" + fi +} + +_value:LDFLAGS () { + compset -q + if compset -P '-L'; then + _files -/ "$@" + elif compset -P '-R'; then + compset -P '*:' + compset -S ':*' + _files -/ -S/ -r '\n\t\- /:' "$@" + else + _default "$@" + fi +} + +_value:DISPLAY() { _x_display "$@" } + +_value:PRINTER() { _printers "$@" } +_value:LPDEST() { _printers "$@" } + +_value:TERM() { _terminals "$@" } + +_value:TZ() { _time_zone "$@" } + +_value "$@" diff -ur -r ../oz/Completion/compdump ./Completion/compdump --- ../oz/Completion/compdump Tue Feb 26 20:56:19 2002 +++ ./Completion/compdump Tue Feb 26 23:34:51 2002 @@ -16,7 +16,7 @@ emulate -L zsh setopt extendedglob noshglob -typeset _d_file _d_f _d_bks _d_line _d_als _d_files +typeset _d_file _d_f _d_bks _d_line _d_als _d_files _d_name _d_tmp _d_file=${_comp_dumpfile-${0:h}/compinit.dump}.$HOST.$$ [[ $_d_file = //* ]] && _d_file=${_d_file[2,-1]} @@ -35,33 +35,41 @@ print "#files: $#_d_files" > $_d_file -# First dump the arrays _comps, _services and _patcomps. The quoting +# First dump the arrays _comps, _servicecomps and _patcomps. The quoting # hieroglyphics ensure that a single quote inside a variable is itself # correctly quoted. -print "_comps=(" >> $_d_file -for _d_f in ${(ok)_comps}; do - print -r - "${(q)_d_f}" "${(q)_comps[$_d_f]}" -done >> $_d_file -print ")" >> $_d_file - -print "_services=(" >> $_d_file -for _d_f in ${(ok)_services}; do - print -r - "${(q)_d_f}" "${(q)_services[$_d_f]}" -done >> $_d_file -print ")" >> $_d_file - -print "\n_patcomps=(" >> $_d_file -for _d_f in "${(ok@)_patcomps}"; do - print -r - "${(q)_d_f}" "${(q)_patcomps[$_d_f]}" -done >> $_d_file -print ")" >> $_d_file +for _d_name in $_comp_assocs; do + + _d_tmp="_${_d_name}" + print "_${_d_name}=(" + for _d_f in ${(Pok)_d_tmp}; do + print -r - "${(q)_d_f}" "${(q)${(e):-\$${_d_tmp}[$_d_f]}}" + done + print ")" + + _d_tmp="_service${_d_name}" + print "\n_service${_d_name}=(" + for _d_f in ${(Pok)_d_tmp}; do + print -r - "${(q)_d_f}" "${(q)${(e):-\$${_d_tmp}[$_d_f]}}" + done + print ")" + + _d_tmp="_pat${_d_name}" + print "\n_pat${_d_name}=(" + for _d_f in ${(Pok)_d_tmp}; do + print -r - "${(q)_d_f}" "${(q)${(e):-\$${_d_tmp}[$_d_f]}}" + done + print ")" + + _d_tmp="_postpat${_d_name}" + print "\n_postpat${_d_name}=(" + for _d_f in ${(Pok)_d_tmp}; do + print -r - "${(q)_d_f}" "${(q)${(e):-\$${_d_tmp}[$_d_f]}}" + done + print ")" -print "\n_postpatcomps=(" >> $_d_file -for _d_f in "${(ok@)_postpatcomps}"; do - print -r - "${(q)_d_f}" "${(q)_postpatcomps[$_d_f]}" done >> $_d_file -print ")" >> $_d_file print "\n_compautos=(" >> $_d_file for _d_f in "${(ok@)_compautos}"; do diff -ur -r ../oz/Completion/compinit ./Completion/compinit --- ../oz/Completion/compinit Tue Feb 26 20:56:19 2002 +++ ./Completion/compinit Wed Feb 27 00:20:53 2002 @@ -11,8 +11,10 @@ # If the first line looks like this, the file is autoloaded as a # function and that function will be called to generate the matches # when completing for one of the commands whose <names> are given. +# The names may also be interspersed with `-T <assoc>' options +# specifying for which set of functions this should be added. # -# `#compdef -p <pattern>' +# `#compdef -[pP] <patterns ...>' # This defines a function that should be called to generate matches # for commands whose name matches <pattern>. Note that only one pattern # may be given. @@ -100,13 +102,27 @@ esac done -# The associative array containing the definitions for the commands and +# The name suffixes for the associative arrays containing the functions +# to call. +# +# NOTE: you have to update this array when defining new types of +# completion function sets. + +_comp_assocs=(comps redirs values) + +# The associative arrays containing the definitions for the commands and # services. -# Definitions for patterns will be stored in the associations `_patcomps' -# and `_postpatcomps'. `_compautos' contains the names and options -# for autoloaded functions that get options. +# Definitions for patterns will be stored in the associations `_pat*' +# and `_postpat*'. + +for _i_name in "${(@)_comp_assocs}"; do + typeset -gA _$_i_name _service$_i_name _pat$_i_name _postpat$_i_name +done + +# `_compautos' contains the names and options for autoloaded functions +# that get options. -typeset -gA _comps _services _patcomps _postpatcomps _compautos +typeset -gA _compautos # The associative array use to report information about the last # completion to the outside. @@ -176,6 +192,9 @@ # The option `-P' is like `-p', but the function will be called after # trying to find a function defined for the command on the line if no # such function could be found. +# In each of these cases the argument list may also contain `-T assoc' +# options to specify the associactive arrays to which the following +# definitions should be added. # With the `-k' option a function for a special completion keys is # defined and immediately bound to those keys. Here, the extra arguments # are the name of one of the builtin completion widgets and any number @@ -191,7 +210,8 @@ # whose names are given as arguments. If combined with the `-p' option # it deletes the definitions for the patterns given as argument. # The `-d' option may not be combined with the `-k' option, i.e. -# definitions for key function can not be removed. +# definitions for key function can not be removed. But one `-T assoc' +# option may follow the `-d' to say which definitions should be removed. # # Examples: # @@ -213,12 +233,12 @@ # delete the definitions for the command names `bar' and `baz' compdef() { - local opt autol type func delete new i ret=0 cmd svc + local opt autol type func delete new i ret=0 cmd svc assoc=comps # Get the options. - if [[ $#* -eq 0 ]]; then - echo "$0: I needs arguments" + if (( ! $# )); then + echo "$0: I need arguments" return 1 fi @@ -247,8 +267,8 @@ done shift OPTIND-1 - if [[ $#* -eq 0 ]]; then - echo "$0: I needs arguments" + if (( ! $# )); then + echo "$0: I need arguments" return 1 fi @@ -257,25 +277,41 @@ # and we define which services to use for the commands. if [[ "$1" = *\=* ]]; then - for i; do - if [[ "$i" = *\=* ]]; then - cmd="${i%%\=*}" - svc="${i#*\=}" - func="$_comps[${(k)_services[(R)$svc]:-$svc}]" - (( $+_services[$svc] )) && svc=$_services[$svc] - [[ -z "$func" ]] && - func="${_patcomps[(K)$svc][1]:-${_postpatcomps[(K)$svc][1]}}" - if [[ -n "$func" ]]; then - _comps[$cmd]="$func" - _services[$cmd]="$svc" + while (( $# )); do + if [[ $1 = -T ]]; then + shift + if (( ! $# )); then + echo "$0: missing type" + return 1 + fi + if (( ! ${_comp_assocs[(I)$1]} )); then + echo "$0: unknown type" + return 1 + fi + assoc="$1" + shift + else + if [[ "$1" = *\=* ]]; then + cmd="${1%%\=*}" + svc="${1#*\=}" + func="$_comps[${(e):-\${(k)_service${assoc}[(R)$svc]:-$svc}}]" + [[ -n ${(e):-\$_service${assoc}[$svc]} ]] && + svc=${(e):-\$_service${assoc}[$svc]} + [[ -z "$func" ]] && + func="${${(e):-\$_pat${assoc}[(K)$svc][1]}:-${(e):-\$_postpat${assoc}[(K)$svc][1]}}" + if [[ -n "$func" ]]; then + eval "_${assoc}"'[$cmd]="$func"' + eval "_service${assoc}"'[$cmd]="$svc"' + else + echo "$0: unknown command or service: $svc" + ret=1 + fi else - echo "$0: unknown command or service: $svc" + echo "$0: invalid argument: $1" ret=1 fi - else - echo "$0: invalid argument: $i" - ret=1 - fi + shift + fi done return ret @@ -290,18 +326,44 @@ case "$type" in pattern) - if [[ $# -gt 1 ]]; then - echo "$0: only one pattern allowed" - return 1 - fi - _patcomps[$1]="$func" + while (( $# )); do + if [[ $1 = -T ]]; then + shift + if (( ! $# )); then + echo "$0: missing type" + return 1 + fi + if (( ! ${_comp_assocs[(I)$1]} )); then + echo "$0: unknown type" + return 1 + fi + assoc="$1" + shift + else + eval "_pat${assoc}"'[$1]="$func"' + shift + fi + done ;; postpattern) - if [[ $# -gt 1 ]]; then - echo "$0: only one pattern allowed" - return 1 - fi - _postpatcomps[$1]="$func" + while (( $# )); do + if [[ $1 = -T ]]; then + shift + if (( ! $# )); then + echo "$0: missing type" + return 1 + fi + if (( ! ${_comp_assocs[(I)$1]} )); then + echo "$0: unknown type" + return 1 + fi + assoc="$1" + shift + else + eval "_postpat${assoc}"'[$1]="$func"' + shift + fi + done ;; widgetkey) while [[ -n $1 ]]; do @@ -321,7 +383,7 @@ fi shift 3 done - ;; + ;; key) if [[ $# -lt 2 ]]; then echo "$0: missing keys" @@ -348,40 +410,70 @@ done ;; *) - # For commands store the function name in the `_comps' + # For commands store the function name in the # associative array, command names as keys. - for i; do - if [[ "$i" = *\=* ]]; then - cmd="${i%%\=*}" - svc=yes + while (( $# )); do + if [[ $1 = -T ]]; then + shift + if (( ! $# )); then + echo "$0: missing type" + return 1 + fi + if (( ! ${_comp_assocs[(I)$1]} )); then + echo "$0: unknown type" + return 1 + fi + assoc="$1" + shift else - cmd="$i" - svc= + if [[ "$1" = *\=* ]]; then + cmd="${1%%\=*}" + svc=yes + else + cmd="$1" + svc= + fi + if [[ -z "$new" || -z "${(e):-\$_${assoc}[$1]}" ]]; then + eval "_${assoc}"'[$cmd]="$func"' + [[ -n "$svc" ]] && eval "_service${assoc}"'[$cmd]="${1#*\=}"' + fi + shift fi - if [[ -z "$new" || "${+_comps[$i]}" -eq 0 ]]; then - _comps[$cmd]="$func" - if [[ -n "$svc" ]]; then _services[$cmd]="${i#*\=}"; fi - fi done ;; esac else # Handle the `-d' option, deleting. + + if [[ $1 = -T ]]; then + shift + if (( ! $# )); then + echo "$0: missing type" + return 1 + fi + if (( ! ${_comp_assocs[(I)$1]} )); then + echo "$0: unknown type" + return 1 + fi + assoc="$1" + shift + fi + case "$type" in pattern) - unset "_patcomps[$^@]" + unset "_pat${assoc}[$^@]" ;; postpattern) - unset "_postpatcomps[$^@]" + unset "_postpat${assoc}[$^@]" ;; key) # Oops, cannot do that yet. echo "$0: cannot restore key bindings" - return 1v + return 1 ;; *) - unset "_comps[$^@]" + unset "_${assoc}[$^@]" esac fi } diff -ur -r ../oz/Doc/Zsh/compsys.yo ./Doc/Zsh/compsys.yo --- ../oz/Doc/Zsh/compsys.yo Tue Feb 26 20:56:17 2002 +++ ./Doc/Zsh/compsys.yo Wed Feb 27 00:37:21 2002 @@ -173,14 +173,27 @@ arguments for the command `tt(cmd)', setting the parameter tt($service) to the string `tt(service)'. The function can then use that parameter to decide what to complete. + +Finally, the list of var(names) may contain tt(-T) options, each +followed by a type name. These type names describe in what kind of +overall context the function is to be used. The default without a +tt(-T) option is `tt(comps)', saying that the function is a normal +completion function. Other type names currently understood by the +completion system are tt(redirs) and tt(values). The first is used to +define specialised completion functions for certain commands and the +latter is used to define functions used when completing values of +parameters. For example, to define the function that should be used +when completing after `tt(foo=<TAB>)' one would use the tag line: + +example(#compdef -T values foo) ) -item(tt(#compdef -p) var(pattern))( +item(tt(#compdef -p) var(patterns...))( The file will be made autoloadable and the function defined in it will be called when completing for a command whose name matches the given -var(pattern) (a standard globbing pattern). Note that only one -var(pattern) may be given. +var(pattern) (a standard globbing pattern). As in the first case, the +list of var(patterns) may contain tt(-T) options. ) -item(tt(#compdef -P) var(pattern))( +item(tt(#compdef -P) var(patterns...))( Like the previous one, but the function will be called only if no completion function for the command on the line could be found. ) @@ -254,10 +267,10 @@ findex(compdef) cindex(completion system, adding definitions) startitem() -xitem(tt(compdef) [ tt(-an) ] var(function names...)) -xitem(tt(compdef -d) var(names...)) -xitem(tt(compdef -p) [ tt(-a) ] var(function pattern)) -xitem(tt(compdef -P) [ tt(-a) ] var(function pattern)) +xitem(tt(compdef) [ tt(-an) ] var(function names) [ tt(-T) var(type) ] ...)) +xitem(tt(compdef -d) [ tt(-T) var(type) ] var(names...)) +xitem(tt(compdef -p) [ tt(-a) ] var(function patterns) [ tt(-T) var(type) ] ...) +xitem(tt(compdef -P) [ tt(-a) ] var(function patterns) [ tt(-T) var(type) ] ...) xitem(tt(compdef -k) [ tt(-an) ] var(function style key-sequences...)) item(tt(compdef -K) [ tt(-an) ] var(function name style key-sequences ...))( The first form tells the completion system to call the given @@ -3553,7 +3566,7 @@ the functions for the fields if they are called. ) findex(_contexts) -item(tt(_contexts) [ tt(-o) ] var(names) ...)( +item(tt(_contexts) [ tt(-o) ] [ tt(-T) var(type) ] var(names) ...)( This function looks up the definitions for the context and command names given as arguments and calls the handler functions for them if there is a definition (given with the tt(compdef) function). For @@ -3564,6 +3577,10 @@ If the tt(-o) option is given, tt(_contexts) returns after the first context for which completions could be generated, without trying the other contexts. + +This function basically calls the tt(_normal) function repeatedly and +if the tt(-T) option is given the var(type) is given to tt(_normal) as +an argument to tell it which type of completion function to use. ) findex(_describe) item(tt(_describe) [ tt(-o) ] var(descr) var(name1) [ var(name2) ] var(opts) ... tt(-)tt(-) ...)( @@ -3789,7 +3806,7 @@ ) ) findex(_normal) -item(tt(_normal))( +item(tt(_normal) [ var(type) ])( This function is used for normal command completion. It has two tasks: completing the first word on the command line as the name of a command, and completing the arguments to this command. In the second case, the name of @@ -3808,6 +3825,13 @@ checked after the call to the corresponding completion function. This has the same effect here as in the tt(-first-) context: if it is set, no more completion functions are called even if there are no matches so far. + +If the optional var(type) argument is given, tt(_normal) does not use +the normal associative arrays for its lookup but instead uses the ones +defined for the given var(type), which may currently be one of +tt(comps) for normal completion, tt(redirs) for completion of +command-specific redirections or tt(values) to complete on the right +hand side of parameter assignments. ) findex(_options) item(tt(_options))( -- Sven Wischnowsky wischnow@berkom.de ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Per command _redirect completion 2002-02-27 9:35 ` Sven Wischnowsky @ 2002-02-27 13:10 ` Oliver Kiddle 2002-02-27 14:30 ` Sven Wischnowsky 2002-02-28 6:35 ` Felix Rosencrantz 1 sibling, 1 reply; 15+ messages in thread From: Oliver Kiddle @ 2002-02-27 13:10 UTC (permalink / raw) To: zsh-workers --- Sven Wischnowsky <wischnow@berkom.de> wrote: > > And one (mostly) unrelated remark: in a private mail Oliver asked if > it were possible to supply the completion widgets with a list of > redirections on the line. Collecting this information shouldn't be > too > complicated. Any suggestions for how we should pas this information > to > the completion function? An array containing values of the form > `<redir-op>:<word>'? The array sounds reasonable. What happens with something like 2>&1? What can the redir op be - just < and > or a variety of things. What about another command being piped to the one it is completing. > diff -ur -r ../oz/Completion/Base/Utility/_contexts > +# You may also select the assocs to use with the `-T assoc' option. I know we only renamed it a year ago but _contexts perhaps could be better named. > diff -ur -r ../oz/Completion/Zsh/Context/_value_PRINTER > ./Completion/Zsh/Context/_value_PRINTER > @@ -0,0 +1,3 @@ > +#compdef -T values PRINTER LPDEST > + > +_printers Do we really want lots of tiny little functions like this one? Can't we just stick the compdef line in _printers itself. We have a compdef for commands like rmdir in _directories which is a similar situation. Have I also understood correctly, that the compdef changes allow multiple uses of -T so that _gzip might start with: #compdef gzip gunzip gzcat=gunzip -T values GZIP Sorry, but I've only had time to glance over this. I'll try it out and reply more fully later. Oliver __________________________________________________ Do You Yahoo!? Everything you'll ever need on one web page from News and Sport to Email and Music Charts http://uk.my.yahoo.com ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Per command _redirect completion 2002-02-27 13:10 ` Oliver Kiddle @ 2002-02-27 14:30 ` Sven Wischnowsky 0 siblings, 0 replies; 15+ messages in thread From: Sven Wischnowsky @ 2002-02-27 14:30 UTC (permalink / raw) To: zsh-workers Oliver Kiddle wrote: > > --- Sven Wischnowsky <wischnow@berkom.de> wrote: > > > > And one (mostly) unrelated remark: in a private mail Oliver asked if > > it were possible to supply the completion widgets with a list of > > redirections on the line. Collecting this information shouldn't be > > too > > complicated. Any suggestions for how we should pas this information > > to > > the completion function? An array containing values of the form > > `<redir-op>:<word>'? > > The array sounds reasonable. What happens with something like 2>&1? > What can the redir op be - just < and > or a variety of things. What > about another command being piped to the one it is completing. You can have a look at it by trying completion after various redirection operators and then using `echo $_lastcomp[redirect]'. They are the ones you can see in the table at lex.c:128. There are almost certainly some interesting things missing (e.g. the descriptor number used in `2>...'). Just some more things that would have to be put into that array (and the lookup string in _redirect). Pipes are generally not supported currently -- separates different commands and that part of the code is pretty old. > > diff -ur -r ../oz/Completion/Base/Utility/_contexts > > +# You may also select the assocs to use with the `-T assoc' option. > > I know we only renamed it a year ago but _contexts perhaps could be > better named. Hm. I don't think it's too bad, but then I'm not a native English speaker. > > diff -ur -r ../oz/Completion/Zsh/Context/_value_PRINTER > > ./Completion/Zsh/Context/_value_PRINTER > > @@ -0,0 +1,3 @@ > > +#compdef -T values PRINTER LPDEST > > + > > +_printers > > Do we really want lots of tiny little functions like this one? Can't we > just stick the compdef line in _printers itself. We have a compdef for > commands like rmdir in _directories which is a similar situation. Seems that I didn't make it clear enough that I only consider the core of this patch to be near its final form (basically the code in compinit and _normal, where the latter will be slightly modified and moved to a separate function). I just didn't want to change too many functions that won't have to be changed anyway. The way it's implemented we have many different possibilities for how to handle this. For some of the functions we have already we can, as you correctly saw, modify already existing function-files like _printer, for others we could group them together in a single file and use $service to decide what exactly to complete (grouping together parameters or redirections that belong together in the same way we already do it for commands). And for others we can use new files as in this example patch. > Have I also understood correctly, that the compdef changes allow > multiple uses of -T so that _gzip might start with: > #compdef gzip gunzip gzcat=gunzip -T values GZIP Right. Good? ;-) > Sorry, but I've only had time to glance over this. I'll try it out and > reply more fully later. Thanks! Bye Sven -- Sven Wischnowsky wischnow@berkom.de ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Per command _redirect completion @ 2002-02-28 6:35 ` Felix Rosencrantz 2002-02-28 8:42 ` Sven Wischnowsky 0 siblings, 1 reply; 15+ messages in thread From: Felix Rosencrantz @ 2002-02-28 6:35 UTC (permalink / raw) To: zsh-workers Looks good to me. Though am seeing an error with the value completions. While the redirs and normal completion don't seem to have a problem. host@ TZ=<TAB> _normal:74: division by zero host@ DISPLAY=<TAB> _normal:74: ':' without '?' _normal:74:service="${${(e):-\$${__services}[$_comp_command1]}:-$_comp_command1}" -FR. __________________________________________________ Do You Yahoo!? Yahoo! Greetings - Send FREE e-cards for every occasion! http://greetings.yahoo.com ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Per command _redirect completion 2002-02-28 6:35 ` Felix Rosencrantz @ 2002-02-28 8:42 ` Sven Wischnowsky 2002-03-01 5:47 ` Bart Schaefer 2002-03-01 9:24 ` Oliver Kiddle 0 siblings, 2 replies; 15+ messages in thread From: Sven Wischnowsky @ 2002-02-28 8:42 UTC (permalink / raw) To: zsh-workers Felix Rosencrantz wrote: > Looks good to me. Though am seeing an error with the value completions. While > the redirs and normal completion don't seem to have a problem. > > host@ TZ=<TAB> > _normal:74: division by zero > host@ DISPLAY=<TAB> > _normal:74: ':' without '?' > > _normal:74:service="${${(e):-\$${__services}[$_comp_command1]}:-$_comp_command1}" Yup, had this too, somtimes. Try the new and improved patch below... It's still not in its final form, but definitely getting better. No more need to define new types in the _comp_assoc array by hand, compdef() will do it automatically. Only two small value-functions left. The stuff in _normal has been put into separate function `_do_type', which needs a better name (for which I need help). Between the things to do: - Decide on a name for the concept so that we can give _do_type its final name and update the docs. - Cleanup _value. Especially the call to _do_type should probably be moved further down so that completion for values of assocs is tried first. As with redirection we can use `-T values -default-' fro default completion. This could even be integrated into _value which would then decide what to do based on $service. - Probably change the order of the strings given to _do_type (these are the strings used for lookup, e.g. command names for normal completion). These should be from most to least specific, I think. - Improve _redirect to use more information about the redirection operator once we have it. - Update _compdef. Every help is appreciated, especially for the first point. Bye Sven diff -ur -r ../oz/Completion/Base/Completer/_complete ./Completion/Base/Completer/_complete --- ../oz/Completion/Base/Completer/_complete Tue Feb 26 20:56:19 2002 +++ ./Completion/Base/Completer/_complete Wed Feb 27 22:32:22 2002 @@ -95,7 +95,7 @@ comp="$_comps[-first-]" if [[ -n "$comp" ]]; then - service="${_services[-first-]:--first-}" + service="${_servicecomps[-first-]:--first-}" ccarray[3]=-first- eval "$comp" && ret=0 if [[ "$_compskip" = all ]]; then @@ -124,7 +124,7 @@ ccarray[3]="$cname" comp="$_comps[$cname]" - service="${_services[$cname]:-$cname}" + service="${_servicecomps[$cname]:-$cname}" # If not, we use default completion, if any. @@ -134,9 +134,9 @@ return 1 fi comp="$_comps[-default-]" + service="${_servicecomps[-default-]:--default-}" fi - [[ -n "$comp" ]] && - service="${_services[-default-]:--default-}" && eval "$comp" && ret=0 + [[ -n "$comp" ]] && eval "$comp" && ret=0 fi _compskip= diff -ur -r ../oz/Completion/Base/Core/_do_type ./Completion/Base/Core/_do_type --- ../oz/Completion/Base/Core/_do_type Wed Feb 27 22:28:45 2002 +++ ./Completion/Base/Core/_do_type Wed Feb 27 23:12:31 2002 @@ -0,0 +1,91 @@ +#autoload + +local comp pat val name i ret=1 _compskip="$_compskip" +local curcontext="$curcontext" service str +local __comps __patcomps __postpatcomps __services + +# If we get the option `-s', we don't reset `_compskip'. + +if [[ "$1" = -s ]]; then + shift +else + _compskip='' +fi + +__comps=_$1 + +(( ${(P)+__comps} )) || return 1 + +__patcomps=_pat$1 +__postpatcomps=_postpat$1 +__services=_service$1 + +shift + +# See if there are any matching pattern completions. + +if [[ "$_compskip" != (all|*patterns*) ]]; then + + for str in "$@"; do + [[ -n "$str" ]] || continue + service="${${(e):-\$${__services}[\$str]}:-$str}" + for i in "${(@e):-\$${__patcomps}[(K)\$str]}"; do + "$i" && ret=0 + if [[ "$_compskip" = *patterns* ]]; then + break + elif [[ "$_compskip" = all ]]; then + _compskip='' + return ret + fi + done + done +fi + +# Now look up the names in the normal completion array. + +ret=1 +for str in "$@"; do + [[ -n "$str" ]] || continue + name="$str" + comp="${(e):-\$${__comps}[\$str]}" + service="${${(e):-\$${__services}[\$str]}:-$str}" + + [[ -z "$comp" ]] || break +done + +# And generate the matches, probably using default completion. + +if [[ -n "$comp" ]]; then + _compskip=patterns + eval "$comp" && ret=0 + [[ "$_compskip" = (all|*patterns*) ]] && return ret +elif [[ "$_compskip" != *default* ]]; then + name=-default- + comp="${(e):-\$${__comps}[-default-]}" +fi + +if [[ "$_compskip" != (all|*patterns*) ]]; then + for str; do + [[ -n "$str" ]] || continue + service="${${(e):-\$${__services}[\$str]}:-$str}" + for i in "${(@e):-\$${__postpatcomps}[(K)\$str]}"; do + _compskip=default + "$i" && ret=0 + if [[ "$_compskip" = *patterns* ]]; then + break + elif [[ "$_compskip" = all ]]; then + _compskip='' + return ret + fi + done + done +fi + +[[ "$name" = -default- && -n "$comp" && + "$_compskip" != (all|*default*) ]] && + service="${${(e):-${__services}[-default-]}:--default-}" && + eval "$comp" && ret=0 + +_compskip='' + +return ret diff -ur -r ../oz/Completion/Base/Core/_normal ./Completion/Base/Core/_normal --- ../oz/Completion/Base/Core/_normal Tue Feb 26 20:56:19 2002 +++ ./Completion/Base/Core/_normal Wed Feb 27 22:29:17 2002 @@ -1,20 +1,16 @@ #compdef -command-line- -local comp command cmd1 cmd2 pat val name i ret=1 _compskip="$_compskip" -local curcontext="$curcontext" service +local _comp_command1 _comp_command2 skip -# If we get the option `-s', we don't reset `_compskip'. This ensures -# that a value set in the function for the `-first-' context is kept, -# but that we still use pattern functions when we were called form -# another completion function. - -[[ "$1" = -s ]] || _compskip='' +if [[ "$1" = -s ]]; then + skip=(-s) +else + skip=() + _compskip='' +fi -# Completing in command position? If not we set up `cmd1' and `cmd2' as -# two strings we have to search in the completion definition arrays (e.g. -# a path and the last path name component). +# Completing in command position? -command="$words[1]" if [[ CURRENT -eq 1 ]]; then curcontext="${curcontext%:*:*}:-command-:" @@ -22,107 +18,8 @@ [[ -n "$comp" ]] && eval "$comp" && ret=0 return ret -else - if (( $+builtins[$command] + $+functions[$command] )); then - cmd1="$command" - curcontext="${curcontext%:*:*}:${cmd1}:" - elif [[ "$command[1]" = '=' ]]; then - eval cmd1\=$command - cmd2="$command[2,-1]" - curcontext="${curcontext%:*:*}:${cmd2}:" - elif [[ "$command" = ..#/* ]]; then - cmd1="${PWD}/$command" - cmd2="${command:t}" - curcontext="${curcontext%:*:*}:${cmd2}:" - elif [[ "$command" = */* ]]; then - cmd1="$command" - cmd2="${command:t}" - curcontext="${curcontext%:*:*}:${cmd2}:" - else - cmd1="$command" - cmd2="$commands[$command]" - curcontext="${curcontext%:*:*}:${cmd1}:" - fi -fi - -# See if there are any matching pattern completions. - -if [[ "$_compskip" != (all|*patterns*) ]]; then - service="${_services[$cmd1]:-$cmd1}" - for i in "${(@)_patcomps[(K)$cmd1]}"; do - "$i" && ret=0 - if [[ "$_compskip" = *patterns* ]]; then - break - elif [[ "$_compskip" = all ]]; then - _compskip='' - return ret - fi - done - if [[ -n "$cmd2" ]]; then - service="${_services[$cmd2]:-$cmd2}" - for i in "${(@)_patcomps[(K)$cmd2]}"; do - "$i" && ret=0 - if [[ "$_compskip" = *patterns* ]]; then - break - elif [[ "$_compskip" = all ]]; then - _compskip='' - return ret - fi - done - fi fi -# Now look up the two names in the normal completion array. - -ret=1 -name="$cmd1" -comp="$_comps[$cmd1]" -service="${_services[$cmd1]:-$cmd1}" - -[[ -z "$comp" ]] && - name="$cmd2" comp="$_comps[$cmd2]" service="${_services[$cmd2]:-$cmd2}" - -# And generate the matches, probably using default completion. - -if [[ -n "$comp" ]]; then - _compskip=patterns - eval "$comp" && ret=0 - [[ "$_compskip" = (all|*patterns*) ]] && return ret -elif [[ "$_compskip" != *default* ]]; then - name=-default- - comp="$_comps[-default-]" -fi - -if [[ "$_compskip" != (all|*patterns*) ]]; then - service="${_services[$cmd1]:-$cmd1}" - for i in "${(@)_postpatcomps[(K)$cmd1]}"; do - _compskip=default - "$i" && ret=0 - if [[ "$_compskip" = *patterns* ]]; then - break - elif [[ "$_compskip" = all ]]; then - _compskip='' - return ret - fi - done - if [[ -n "$cmd2" ]]; then - service="${_services[$cmd2]:-$cmd2}" - for i in "${(@)_postpatcomps[(K)$cmd2]}"; do - _compskip=default - "$i" && ret=0 - if [[ "$_compskip" = *patterns* ]]; then - break - elif [[ "$_compskip" = all ]]; then - _compskip='' - return ret - fi - done - fi -fi - -[[ "$name" = -default- && -n "$comp" && "$_compskip" != (all|*default*) ]] && - service="${_services[-default-]:--default-}" && eval "$comp" && ret=0 - -_compskip='' +_set_command -return ret +_do_type "$skip[@]" comps "_$comp_command1" "_$comp_command2" diff -ur -r ../oz/Completion/Base/Utility/_contexts ./Completion/Base/Utility/_contexts --- ../oz/Completion/Base/Utility/_contexts Tue Feb 26 20:56:19 2002 +++ ./Completion/Base/Utility/_contexts Tue Feb 26 23:44:51 2002 @@ -6,8 +6,19 @@ # For example the function for `-subscript-' could call this as in # `_contexts -math-' to get the completions that would be generated for a # mathematical context. +# You may also select the assocs to use with the `-T assoc' option. -local i tmp ret=1 service or +local i tmp ret=1 service or type + +type=(-T comps) +zparseopts -D o=or T:=type + +type="$type[2]" +if (( $#or )); then + or=yes +else + or= +fi if [[ $1 = -o ]]; then or=yes @@ -15,8 +26,9 @@ fi for i; do - tmp="$_comps[$i]" - [[ -n "$tmp" ]] && service="${_services[$i]:-$i}" && eval "$tmp" && ret=0 + tmp="${(e):-\$_${type}[$i]}" + [[ -n "$tmp" ]] && service="${${(e):-\$_service${type}[$i]}:-$i}" && + eval "$tmp" && ret=0 [[ -n "$or" && ret -eq 0 ]] && return 0 done diff -ur -r ../oz/Completion/Base/Utility/_set_command ./Completion/Base/Utility/_set_command --- ../oz/Completion/Base/Utility/_set_command Wed Feb 27 22:28:17 2002 +++ ./Completion/Base/Utility/_set_command Wed Feb 27 22:27:46 2002 @@ -0,0 +1,31 @@ +#autoload + +# This sets the parameters _comp_command1 and _comp_command2 in the +# calling function. + +local command + +command="$words[1]" + +[[ -z "$command" ]] && return + +if (( $+builtins[$command] + $+functions[$command] )); then + _comp_command1="$command" + curcontext="${curcontext%:*:*}:${_comp_command1}:" +elif [[ "$command[1]" = '=' ]]; then + eval _comp_command1\=$command + _comp_command2="$command[2,-1]" + curcontext="${curcontext%:*:*}:${_comp_command2}:" +elif [[ "$command" = ..#/* ]]; then + _comp_command1="${PWD}/$command" + _comp_command2="${command:t}" + curcontext="${curcontext%:*:*}:${_comp_command2}:" +elif [[ "$command" = */* ]]; then + _comp_command1="$command" + _comp_command2="${command:t}" + curcontext="${curcontext%:*:*}:${_comp_command2}:" +else + _comp_command1="$command" + _comp_command2="$commands[$command]" + curcontext="${curcontext%:*:*}:${_comp_command1}:" +fi diff -ur -r ../oz/Completion/Unix/Type/_files ./Completion/Unix/Type/_files --- ../oz/Completion/Unix/Type/_files Tue Feb 26 20:56:19 2002 +++ ./Completion/Unix/Type/_files Wed Feb 27 22:35:35 2002 @@ -1,4 +1,4 @@ -#autoload +#compdef -T redirs -default- local opts tmp glob pat pats expl tag i def descr end ign ret=1 match tried local type sdef diff -ur -r ../oz/Completion/Unix/Type/_printers ./Completion/Unix/Type/_printers --- ../oz/Completion/Unix/Type/_printers Tue Feb 26 20:56:19 2002 +++ ./Completion/Unix/Type/_printers Wed Feb 27 21:18:55 2002 @@ -1,4 +1,4 @@ -#autoload +#compdef -T values PRINTER LPDEST local expl ret=1 list disp sep diff -ur -r ../oz/Completion/Unix/Type/_terminals ./Completion/Unix/Type/_terminals --- ../oz/Completion/Unix/Type/_terminals Tue Feb 26 20:56:19 2002 +++ ./Completion/Unix/Type/_terminals Wed Feb 27 21:19:33 2002 @@ -1,4 +1,4 @@ -#compdef infocmp +#compdef infocmp -T values TERM local desc expl diff -ur -r ../oz/Completion/Unix/Type/_time_zone ./Completion/Unix/Type/_time_zone --- ../oz/Completion/Unix/Type/_time_zone Tue Feb 26 20:56:19 2002 +++ ./Completion/Unix/Type/_time_zone Wed Feb 27 21:20:11 2002 @@ -1,4 +1,4 @@ -#compdef +#compdef -T values TZ local expl diff -ur -r ../oz/Completion/X/Type/_x_display ./Completion/X/Type/_x_display --- ../oz/Completion/X/Type/_x_display Tue Feb 26 20:56:19 2002 +++ ./Completion/X/Type/_x_display Wed Feb 27 21:18:14 2002 @@ -1,3 +1,3 @@ -#autoload +#compdef -T values DISPLAY _tags displays && _hosts -S ':0 ' -r : diff -ur -r ../oz/Completion/Zsh/Context/_default ./Completion/Zsh/Context/_default --- ../oz/Completion/Zsh/Context/_default Tue Feb 26 20:56:19 2002 +++ ./Completion/Zsh/Context/_default Wed Feb 27 21:58:26 2002 @@ -19,7 +19,7 @@ # allow completion to handle file names after any equals sign. if [[ -o magicequalsubst && "$PREFIX" = *\=* ]]; then - compstate[parameter]="${words[1]:t}-${PREFIX%%\=*}" + compstate[parameter]="${PREFIX%%\=*}" compset -P 1 '*=' _value "$@" else diff -ur -r ../oz/Completion/Zsh/Context/_redirect ./Completion/Zsh/Context/_redirect --- ../oz/Completion/Zsh/Context/_redirect Tue Feb 26 20:56:19 2002 +++ ./Completion/Zsh/Context/_redirect Wed Feb 27 22:45:54 2002 @@ -1,3 +1,15 @@ #compdef -redirect- -_files +local strs _comp_command1 _comp_command2 + +_set_command + +strs=( "$compstate[redirect]" ) + +if [[ -n "$_comp_command1" ]]; then + strs=( "$strs[@]" + "${_comp_command1}:$strs[1]" ) + [[ -n "$_comp_command2" ]] && strs=( "$strs[@]" "${_comp_command2}:$strs[1]" ) +fi + +_do_type redirs "$strs[@]" diff -ur -r ../oz/Completion/Zsh/Context/_value ./Completion/Zsh/Context/_value --- ../oz/Completion/Zsh/Context/_value Wed Feb 27 00:14:27 2002 +++ ./Completion/Zsh/Context/_value Wed Feb 27 22:03:03 2002 @@ -1,70 +1,52 @@ #compdef -value- -array-value- -_value () { - # You can customize completion for different parameters by writing a - # function `_value:<name>', where <name> is the name of the parameter. - # When completing values of elements of associative arrays, we first - # search for a function `_value:<assoc>-<key>' and then for - # `_value:<assoc>', so it's simple to define different functions - # for different keys or one function for a whole association. - - if (( $+functions[_value:$compstate[parameter]] )); then - "_value:$compstate[parameter]" "$@" - elif (( $+functions[_value:${compstate[parameter]%%-*}] )); then - "_value:${compstate[parameter]%%-*}" "$@" - elif [[ "$compstate[parameter]" != *-* && - "${(Pt)${compstate[parameter]}}" = assoc* ]]; then - if (( CURRENT & 1 )); then - _wanted association-keys expl 'association key' \ - compadd -k "$compstate[parameter]" - else - compstate[parameter]="${compstate[parameter]}-${words[CURRENT-1]}" - _value "$@" - fi - else - local pats +# You can customize completion for different parameters by writing +# functions with the tag-line `#compdef -T value <name>'. + +local strs type + +type="${(Pt)compstate[parameter]}" - if { zstyle -a ":completion:${curcontext}:" assign-list pats && - [[ "$compstate[parameter]" = (${(j:|:)~pats}) ]] } || - [[ "$PREFIX$SUFFIX" = *:* ]]; then - compset -P '*:' - compset -S ':*' - _default -r '\-\n\t /:' "$@" - else - _default "$@" - fi +if [[ -z "$type" ]]; then + if [[ "$compstate[parameter]" = *-* ]]; then + type=association-value + elif [[ "$compstate[context]" = value ]]; then + type=scalar + else + type=array fi -} +fi + +strs=( "$compstate[parameter]" "${compstate[parameter]}:$type" ) -_value:CPPFLAGS () { - compset -q - if compset -P '-I'; then - _files -/ "$@" +if [[ "$compstate[context]" != *value && -n "$_comp_command1" ]]; then + strs=( "$strs[@]" "${_comp_command1}:$^strs[@]" ) + [[ -n "$_comp_command2" ]] && + strs=( "$strs[@]" "${_comp_command2}:${(@)^strs[1,2]}" ) +fi + +_do_type values "$strs[@]" && return 0 + +if [[ "$compstate[parameter]" != *-* && + "$compstate[context]" = *value && + "${(Pt)${compstate[parameter]}}" = assoc* ]]; then + if (( CURRENT & 1 )); then + _wanted association-keys expl 'association key' \ + compadd -k "$compstate[parameter]" else - _default "$@" + compstate[parameter]="${compstate[parameter]}-${words[CURRENT-1]}" + _value "$@" fi -} +else + local pats -_value:LDFLAGS () { - compset -q - if compset -P '-L'; then - _files -/ "$@" - elif compset -P '-R'; then + if { zstyle -a ":completion:${curcontext}:" assign-list pats && + [[ "$compstate[parameter]" = (${(j:|:)~pats}) ]] } || + [[ "$PREFIX$SUFFIX" = *:* ]]; then compset -P '*:' compset -S ':*' - _files -/ -S/ -r '\n\t\- /:' "$@" + _default -r '\-\n\t /:' "$@" else _default "$@" fi -} - -_value:DISPLAY() { _x_display "$@" } - -_value:PRINTER() { _printers "$@" } -_value:LPDEST() { _printers "$@" } - -_value:TERM() { _terminals "$@" } - -_value:TZ() { _time_zone "$@" } - -_value "$@" +fi diff -ur -r ../oz/Completion/Zsh/Context/_value_CPPFLAGS ./Completion/Zsh/Context/_value_CPPFLAGS --- ../oz/Completion/Zsh/Context/_value_CPPFLAGS Wed Feb 27 00:14:27 2002 +++ ./Completion/Zsh/Context/_value_CPPFLAGS Wed Feb 27 00:25:03 2002 @@ -0,0 +1,8 @@ +#compdef -T values CPPFLAGS + +compset -q +if compset -P '-I'; then + _files -/ "$@" +else + _default "$@" +fi diff -ur -r ../oz/Completion/Zsh/Context/_value_LDFLAGS ./Completion/Zsh/Context/_value_LDFLAGS --- ../oz/Completion/Zsh/Context/_value_LDFLAGS Wed Feb 27 00:14:27 2002 +++ ./Completion/Zsh/Context/_value_LDFLAGS Wed Feb 27 00:25:24 2002 @@ -0,0 +1,12 @@ +#compdef -T values LDFLAGS + +compset -q +if compset -P '-L'; then + _files -/ "$@" +elif compset -P '-R'; then + compset -P '*:' + compset -S ':*' + _files -/ -S/ -r '\n\t\- /:' "$@" +else + _default "$@" +fi diff -ur -r ../oz/Completion/compdump ./Completion/compdump --- ../oz/Completion/compdump Tue Feb 26 20:56:19 2002 +++ ./Completion/compdump Wed Feb 27 23:10:35 2002 @@ -16,7 +16,7 @@ emulate -L zsh setopt extendedglob noshglob -typeset _d_file _d_f _d_bks _d_line _d_als _d_files +typeset _d_file _d_f _d_bks _d_line _d_als _d_files _d_name _d_tmp _d_file=${_comp_dumpfile-${0:h}/compinit.dump}.$HOST.$$ [[ $_d_file = //* ]] && _d_file=${_d_file[2,-1]} @@ -35,33 +35,43 @@ print "#files: $#_d_files" > $_d_file -# First dump the arrays _comps, _services and _patcomps. The quoting +# First dump the arrays _comps, _servicecomps and _patcomps. The quoting # hieroglyphics ensure that a single quote inside a variable is itself # correctly quoted. -print "_comps=(" >> $_d_file -for _d_f in ${(ok)_comps}; do - print -r - "${(q)_d_f}" "${(q)_comps[$_d_f]}" -done >> $_d_file -print ")" >> $_d_file - -print "_services=(" >> $_d_file -for _d_f in ${(ok)_services}; do - print -r - "${(q)_d_f}" "${(q)_services[$_d_f]}" -done >> $_d_file -print ")" >> $_d_file - -print "\n_patcomps=(" >> $_d_file -for _d_f in "${(ok@)_patcomps}"; do - print -r - "${(q)_d_f}" "${(q)_patcomps[$_d_f]}" -done >> $_d_file -print ")" >> $_d_file +for _d_name in $_comp_assocs; do + + print "\n\ntypeset -gA _$_d_name _service$_d_name _pat$_d_name _postpat$_d_name" + + _d_tmp="_${_d_name}" + print "\n_${_d_name}=(" + for _d_f in ${(Pok)_d_tmp}; do + print -r - "${(q)_d_f}" "${(q)${(e):-\$${_d_tmp}[$_d_f]}}" + done + print ")" + + _d_tmp="_service${_d_name}" + print "\n_service${_d_name}=(" + for _d_f in ${(Pok)_d_tmp}; do + print -r - "${(q)_d_f}" "${(q)${(e):-\$${_d_tmp}[$_d_f]}}" + done + print ")" + + _d_tmp="_pat${_d_name}" + print "\n_pat${_d_name}=(" + for _d_f in ${(Pok)_d_tmp}; do + print -r - "${(q)_d_f}" "${(q)${(e):-\$${_d_tmp}[$_d_f]}}" + done + print ")" + + _d_tmp="_postpat${_d_name}" + print "\n_postpat${_d_name}=(" + for _d_f in ${(Pok)_d_tmp}; do + print -r - "${(q)_d_f}" "${(q)${(e):-\$${_d_tmp}[$_d_f]}}" + done + print ")" -print "\n_postpatcomps=(" >> $_d_file -for _d_f in "${(ok@)_postpatcomps}"; do - print -r - "${(q)_d_f}" "${(q)_postpatcomps[$_d_f]}" done >> $_d_file -print ")" >> $_d_file print "\n_compautos=(" >> $_d_file for _d_f in "${(ok@)_compautos}"; do diff -ur -r ../oz/Completion/compinit ./Completion/compinit --- ../oz/Completion/compinit Tue Feb 26 20:56:19 2002 +++ ./Completion/compinit Wed Feb 27 23:08:37 2002 @@ -11,8 +11,10 @@ # If the first line looks like this, the file is autoloaded as a # function and that function will be called to generate the matches # when completing for one of the commands whose <names> are given. +# The names may also be interspersed with `-T <assoc>' options +# specifying for which set of functions this should be added. # -# `#compdef -p <pattern>' +# `#compdef -[pP] <patterns ...>' # This defines a function that should be called to generate matches # for commands whose name matches <pattern>. Note that only one pattern # may be given. @@ -100,13 +102,26 @@ esac done -# The associative array containing the definitions for the commands and +# The name suffixes for the associative arrays containing the functions +# to call. + +typeset -Ua _comp_assocs + +_comp_assocs=(comps) + +# The associative arrays containing the definitions for the commands and # services. -# Definitions for patterns will be stored in the associations `_patcomps' -# and `_postpatcomps'. `_compautos' contains the names and options -# for autoloaded functions that get options. +# Definitions for patterns will be stored in the associations `_pat*' +# and `_postpat*'. +# The assocs for the other function types are created automatically by +# compdef. + +typeset -gA _comps _servicecomps _patcomps _postpatcomps -typeset -gA _comps _services _patcomps _postpatcomps _compautos +# `_compautos' contains the names and options for autoloaded functions +# that get options. + +typeset -gA _compautos # The associative array use to report information about the last # completion to the outside. @@ -176,6 +191,9 @@ # The option `-P' is like `-p', but the function will be called after # trying to find a function defined for the command on the line if no # such function could be found. +# In each of these cases the argument list may also contain `-T assoc' +# options to specify the associactive arrays to which the following +# definitions should be added. # With the `-k' option a function for a special completion keys is # defined and immediately bound to those keys. Here, the extra arguments # are the name of one of the builtin completion widgets and any number @@ -191,7 +209,8 @@ # whose names are given as arguments. If combined with the `-p' option # it deletes the definitions for the patterns given as argument. # The `-d' option may not be combined with the `-k' option, i.e. -# definitions for key function can not be removed. +# definitions for key function can not be removed. But one `-T assoc' +# option may follow the `-d' to say which definitions should be removed. # # Examples: # @@ -213,12 +232,12 @@ # delete the definitions for the command names `bar' and `baz' compdef() { - local opt autol type func delete new i ret=0 cmd svc + local opt autol type func delete new i ret=0 cmd svc assoc=comps # Get the options. - if [[ $#* -eq 0 ]]; then - echo "$0: I needs arguments" + if (( ! $# )); then + echo "$0: I need arguments" return 1 fi @@ -247,8 +266,8 @@ done shift OPTIND-1 - if [[ $#* -eq 0 ]]; then - echo "$0: I needs arguments" + if (( ! $# )); then + echo "$0: I need arguments" return 1 fi @@ -257,25 +276,39 @@ # and we define which services to use for the commands. if [[ "$1" = *\=* ]]; then - for i; do - if [[ "$i" = *\=* ]]; then - cmd="${i%%\=*}" - svc="${i#*\=}" - func="$_comps[${(k)_services[(R)$svc]:-$svc}]" - (( $+_services[$svc] )) && svc=$_services[$svc] - [[ -z "$func" ]] && - func="${_patcomps[(K)$svc][1]:-${_postpatcomps[(K)$svc][1]}}" - if [[ -n "$func" ]]; then - _comps[$cmd]="$func" - _services[$cmd]="$svc" + while (( $# )); do + if [[ $1 = -T ]]; then + shift + if (( ! $# )); then + echo "$0: missing type" + return 1 + fi + _comp_assocs=( "$_comp_assocs[@]" "$1" ) + typeset -gA _$1 _service_$1 _pat$1 _postpat$1 + assoc="$1" + shift + else + if [[ "$1" = *\=* ]]; then + cmd="${1%%\=*}" + svc="${1#*\=}" + func="$_comps[${(e):-\${(k)_service${assoc}[(R)$svc]:-$svc}}]" + [[ -n ${(e):-\$_service${assoc}[$svc]} ]] && + svc=${(e):-\$_service${assoc}[$svc]} + [[ -z "$func" ]] && + func="${${(e):-\$_pat${assoc}[(K)$svc][1]}:-${(e):-\$_postpat${assoc}[(K)$svc][1]}}" + if [[ -n "$func" ]]; then + eval "_${assoc}"'[$cmd]="$func"' + eval "_service${assoc}"'[$cmd]="$svc"' + else + echo "$0: unknown command or service: $svc" + ret=1 + fi else - echo "$0: unknown command or service: $svc" + echo "$0: invalid argument: $1" ret=1 fi - else - echo "$0: invalid argument: $i" - ret=1 - fi + shift + fi done return ret @@ -290,18 +323,40 @@ case "$type" in pattern) - if [[ $# -gt 1 ]]; then - echo "$0: only one pattern allowed" - return 1 - fi - _patcomps[$1]="$func" + while (( $# )); do + if [[ $1 = -T ]]; then + shift + if (( ! $# )); then + echo "$0: missing type" + return 1 + fi + _comp_assocs=( "$_comp_assocs[@]" "$1" ) + typeset -gA _$1 _service_$1 _pat$1 _postpat$1 + assoc="$1" + shift + else + eval "_pat${assoc}"'[$1]="$func"' + shift + fi + done ;; postpattern) - if [[ $# -gt 1 ]]; then - echo "$0: only one pattern allowed" - return 1 - fi - _postpatcomps[$1]="$func" + while (( $# )); do + if [[ $1 = -T ]]; then + shift + if (( ! $# )); then + echo "$0: missing type" + return 1 + fi + _comp_assocs=( "$_comp_assocs[@]" "$1" ) + typeset -gA _$1 _service_$1 _pat$1 _postpat$1 + assoc="$1" + shift + else + eval "_postpat${assoc}"'[$1]="$func"' + shift + fi + done ;; widgetkey) while [[ -n $1 ]]; do @@ -321,7 +376,7 @@ fi shift 3 done - ;; + ;; key) if [[ $# -lt 2 ]]; then echo "$0: missing keys" @@ -348,40 +403,66 @@ done ;; *) - # For commands store the function name in the `_comps' + # For commands store the function name in the # associative array, command names as keys. - for i; do - if [[ "$i" = *\=* ]]; then - cmd="${i%%\=*}" - svc=yes + while (( $# )); do + if [[ $1 = -T ]]; then + shift + if (( ! $# )); then + echo "$0: missing type" + return 1 + fi + _comp_assocs=( "$_comp_assocs[@]" "$1" ) + typeset -gA _$1 _service_$1 _pat$1 _postpat$1 + assoc="$1" + shift else - cmd="$i" - svc= + if [[ "$1" = *\=* ]]; then + cmd="${1%%\=*}" + svc=yes + else + cmd="$1" + svc= + fi + if [[ -z "$new" || -z "${(e):-\$_${assoc}[$1]}" ]]; then + eval "_${assoc}"'[$cmd]="$func"' + [[ -n "$svc" ]] && eval "_service${assoc}"'[$cmd]="${1#*\=}"' + fi + shift fi - if [[ -z "$new" || "${+_comps[$i]}" -eq 0 ]]; then - _comps[$cmd]="$func" - if [[ -n "$svc" ]]; then _services[$cmd]="${i#*\=}"; fi - fi done ;; esac else # Handle the `-d' option, deleting. + + if [[ $1 = -T ]]; then + shift + if (( ! $# )); then + echo "$0: missing type" + return 1 + fi + _comp_assocs=( "$_comp_assocs[@]" "$1" ) + typeset -gA _$1 _service_$1 _pat$1 _postpat$1 + assoc="$1" + shift + fi + case "$type" in pattern) - unset "_patcomps[$^@]" + unset "_pat${assoc}[$^@]" ;; postpattern) - unset "_postpatcomps[$^@]" + unset "_postpat${assoc}[$^@]" ;; key) # Oops, cannot do that yet. echo "$0: cannot restore key bindings" - return 1v + return 1 ;; *) - unset "_comps[$^@]" + unset "_${assoc}[$^@]" esac fi } diff -ur -r ../oz/Doc/Zsh/compsys.yo ./Doc/Zsh/compsys.yo --- ../oz/Doc/Zsh/compsys.yo Tue Feb 26 20:56:17 2002 +++ ./Doc/Zsh/compsys.yo Wed Feb 27 00:37:21 2002 @@ -173,14 +173,27 @@ arguments for the command `tt(cmd)', setting the parameter tt($service) to the string `tt(service)'. The function can then use that parameter to decide what to complete. + +Finally, the list of var(names) may contain tt(-T) options, each +followed by a type name. These type names describe in what kind of +overall context the function is to be used. The default without a +tt(-T) option is `tt(comps)', saying that the function is a normal +completion function. Other type names currently understood by the +completion system are tt(redirs) and tt(values). The first is used to +define specialised completion functions for certain commands and the +latter is used to define functions used when completing values of +parameters. For example, to define the function that should be used +when completing after `tt(foo=<TAB>)' one would use the tag line: + +example(#compdef -T values foo) ) -item(tt(#compdef -p) var(pattern))( +item(tt(#compdef -p) var(patterns...))( The file will be made autoloadable and the function defined in it will be called when completing for a command whose name matches the given -var(pattern) (a standard globbing pattern). Note that only one -var(pattern) may be given. +var(pattern) (a standard globbing pattern). As in the first case, the +list of var(patterns) may contain tt(-T) options. ) -item(tt(#compdef -P) var(pattern))( +item(tt(#compdef -P) var(patterns...))( Like the previous one, but the function will be called only if no completion function for the command on the line could be found. ) @@ -254,10 +267,10 @@ findex(compdef) cindex(completion system, adding definitions) startitem() -xitem(tt(compdef) [ tt(-an) ] var(function names...)) -xitem(tt(compdef -d) var(names...)) -xitem(tt(compdef -p) [ tt(-a) ] var(function pattern)) -xitem(tt(compdef -P) [ tt(-a) ] var(function pattern)) +xitem(tt(compdef) [ tt(-an) ] var(function names) [ tt(-T) var(type) ] ...)) +xitem(tt(compdef -d) [ tt(-T) var(type) ] var(names...)) +xitem(tt(compdef -p) [ tt(-a) ] var(function patterns) [ tt(-T) var(type) ] ...) +xitem(tt(compdef -P) [ tt(-a) ] var(function patterns) [ tt(-T) var(type) ] ...) xitem(tt(compdef -k) [ tt(-an) ] var(function style key-sequences...)) item(tt(compdef -K) [ tt(-an) ] var(function name style key-sequences ...))( The first form tells the completion system to call the given @@ -3553,7 +3566,7 @@ the functions for the fields if they are called. ) findex(_contexts) -item(tt(_contexts) [ tt(-o) ] var(names) ...)( +item(tt(_contexts) [ tt(-o) ] [ tt(-T) var(type) ] var(names) ...)( This function looks up the definitions for the context and command names given as arguments and calls the handler functions for them if there is a definition (given with the tt(compdef) function). For @@ -3564,6 +3577,10 @@ If the tt(-o) option is given, tt(_contexts) returns after the first context for which completions could be generated, without trying the other contexts. + +This function basically calls the tt(_normal) function repeatedly and +if the tt(-T) option is given the var(type) is given to tt(_normal) as +an argument to tell it which type of completion function to use. ) findex(_describe) item(tt(_describe) [ tt(-o) ] var(descr) var(name1) [ var(name2) ] var(opts) ... tt(-)tt(-) ...)( @@ -3789,7 +3806,7 @@ ) ) findex(_normal) -item(tt(_normal))( +item(tt(_normal) [ var(type) ])( This function is used for normal command completion. It has two tasks: completing the first word on the command line as the name of a command, and completing the arguments to this command. In the second case, the name of @@ -3808,6 +3825,13 @@ checked after the call to the corresponding completion function. This has the same effect here as in the tt(-first-) context: if it is set, no more completion functions are called even if there are no matches so far. + +If the optional var(type) argument is given, tt(_normal) does not use +the normal associative arrays for its lookup but instead uses the ones +defined for the given var(type), which may currently be one of +tt(comps) for normal completion, tt(redirs) for completion of +command-specific redirections or tt(values) to complete on the right +hand side of parameter assignments. ) findex(_options) item(tt(_options))( -- Sven Wischnowsky wischnow@berkom.de ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Per command _redirect completion 2002-02-28 8:42 ` Sven Wischnowsky @ 2002-03-01 5:47 ` Bart Schaefer 2002-03-04 8:50 ` Sven Wischnowsky 2002-03-01 9:24 ` Oliver Kiddle 1 sibling, 1 reply; 15+ messages in thread From: Bart Schaefer @ 2002-03-01 5:47 UTC (permalink / raw) To: zsh-workers On Feb 27, 10:35am, Sven Wischnowsky wrote: } } I wrote: } } > I would try to make compdef and parts of _normal (and probably } > _complete) generic enough to use an assoc given as argument, so that } > we get the pattern and services stuff. I like this idea a lot, now that I've had a chance to digest it fully. } - I wished there were an easier way than to use `${(e):-...}' in so } many places. Sigh. We'd need namerefs; ${(P)...} doesn't cut it for hashes. You could use `eval' in a few places, I think, but not all of them. On Feb 28, 9:42am, Sven Wischnowsky wrote: } } - Decide on a name for the concept so that we can give _do_type its } final name and update the docs. What if we called the function `_common'? It's use is both "commonplace" and "shared" ... } - Probably change the order of the strings given to _do_type (these } are the strings used for lookup, e.g. command names for normal } completion). These should be from most to least specific, I think. That sounds sensible. -- Bart Schaefer Brass Lantern Enterprises http://www.well.com/user/barts http://www.brasslantern.com Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Per command _redirect completion 2002-03-01 5:47 ` Bart Schaefer @ 2002-03-04 8:50 ` Sven Wischnowsky 0 siblings, 0 replies; 15+ messages in thread From: Sven Wischnowsky @ 2002-03-04 8:50 UTC (permalink / raw) To: zsh-workers Bart Schaefer wrote: > ... > > I like this idea a lot, now that I've had a chance to digest it fully. Yes, me too. Thanks to Oliver for bringing this up. > } - I wished there were an easier way than to use `${(e):-...}' in so > } many places. Sigh. > > We'd need namerefs; ${(P)...} doesn't cut it for hashes. You could use > `eval' in a few places, I think, but not all of them. Which isn't much nicer anyway... Felix Rosencrantz wrote: > Still having problem with the latest uncommitted patch: When trying to > complete TZ I get: > _do_type:31: ':' without '?' > > Which only happens from a shell where .zcompdump didn't pre-exist. Subsequent > shells seem to work. Yep, I had introduced that in another way. I found and fixed this, so it should be working now with the patch below. > Also, completion for command flags/args doesn't work. The command's completion > function is not being called. > I try: > gzip -<TAB> > > in an empty directory and get "no match for: `file'". I have no problems with this. > I like the new changes a lot (assuming they work). It wasn't clear to me how > completion for different redirection operators will work. It seems that you > can only specify one redirection completer. Which will have to do the > remaining work of figuring what completion function to use, if you want one for > input and one for output. (And another for stderr, etc.) It seems like that > information should be part of the compdef call. All my command specific > redirection completers currently are for commands that provide output, the > input comes from command line args, so it didn't matter. But I can easily see > there being commands where input and output files from redirection are > completely different. So the user will want to use different functions. See the comments in _redirection and _value. Of course the redirection operator is part of the string searched. E.g.: % compdef 'compadd a b c' 'foo:>' % foo > <TAB> a b c I'm now going to commit this change so that everyone can easily try it. I've renamed _do_type to _dispatch and removed _contexts (it's functionality is now in _dispatch). I'd be thankful if someone could have a look at the changes in the docs. I'm almost sure that this should be described better, somewhere else and that the strings looked up for each type of completion should be described somewhere (we never had this for normal commands either). And whoever wrote the functions for completing the values of CPPFLAGS and LDFLAGS might want to look at _gcc to see if that's ok (I followed Oliver's suggestion to put completion for these paramter-values there). Bye Sven Index: Completion/compdump =================================================================== RCS file: /cvsroot/zsh/zsh/Completion/compdump,v retrieving revision 1.2 diff -u -r1.2 compdump --- Completion/compdump 29 May 2001 17:54:08 -0000 1.2 +++ Completion/compdump 4 Mar 2002 08:50:44 -0000 @@ -16,7 +16,7 @@ emulate -L zsh setopt extendedglob noshglob -typeset _d_file _d_f _d_bks _d_line _d_als _d_files +typeset _d_file _d_f _d_bks _d_line _d_als _d_files _d_name _d_tmp _d_file=${_comp_dumpfile-${0:h}/compinit.dump}.$HOST.$$ [[ $_d_file = //* ]] && _d_file=${_d_file[2,-1]} @@ -35,33 +35,43 @@ print "#files: $#_d_files" > $_d_file -# First dump the arrays _comps, _services and _patcomps. The quoting +# First dump the arrays _comps, _servicecomps and _patcomps. The quoting # hieroglyphics ensure that a single quote inside a variable is itself # correctly quoted. -print "_comps=(" >> $_d_file -for _d_f in ${(ok)_comps}; do - print -r - "${(q)_d_f}" "${(q)_comps[$_d_f]}" -done >> $_d_file -print ")" >> $_d_file +for _d_name in $_comp_assocs; do -print "_services=(" >> $_d_file -for _d_f in ${(ok)_services}; do - print -r - "${(q)_d_f}" "${(q)_services[$_d_f]}" -done >> $_d_file -print ")" >> $_d_file + print "\n\ntypeset -gA _$_d_name _service$_d_name _pat$_d_name _postpat$_d_name" -print "\n_patcomps=(" >> $_d_file -for _d_f in "${(ok@)_patcomps}"; do - print -r - "${(q)_d_f}" "${(q)_patcomps[$_d_f]}" -done >> $_d_file -print ")" >> $_d_file + _d_tmp="_${_d_name}" + print "\n_${_d_name}=(" + for _d_f in ${(Pok)_d_tmp}; do + print -r - "${(q)_d_f}" "${(q)${(e):-\$${_d_tmp}[$_d_f]}}" + done + print ")" + + _d_tmp="_service${_d_name}" + print "\n_service${_d_name}=(" + for _d_f in ${(Pok)_d_tmp}; do + print -r - "${(q)_d_f}" "${(q)${(e):-\$${_d_tmp}[$_d_f]}}" + done + print ")" + + _d_tmp="_pat${_d_name}" + print "\n_pat${_d_name}=(" + for _d_f in ${(Pok)_d_tmp}; do + print -r - "${(q)_d_f}" "${(q)${(e):-\$${_d_tmp}[$_d_f]}}" + done + print ")" + + _d_tmp="_postpat${_d_name}" + print "\n_postpat${_d_name}=(" + for _d_f in ${(Pok)_d_tmp}; do + print -r - "${(q)_d_f}" "${(q)${(e):-\$${_d_tmp}[$_d_f]}}" + done + print ")" -print "\n_postpatcomps=(" >> $_d_file -for _d_f in "${(ok@)_postpatcomps}"; do - print -r - "${(q)_d_f}" "${(q)_postpatcomps[$_d_f]}" done >> $_d_file -print ")" >> $_d_file print "\n_compautos=(" >> $_d_file for _d_f in "${(ok@)_compautos}"; do @@ -128,6 +138,11 @@ for _i in "${(ok@)_compautos}"; do print "autoload -U $_compautos[$_i] $_i" >> $_d_file done + +print >> $_d_file + +print "typeset -gUa _comp_assocs" >> $_d_file +print "_comp_assocs=( ${(q)_comp_assocs} )" >> $_d_file mv $_d_file ${_d_file%.$HOST.$$} Index: Completion/compinit =================================================================== RCS file: /cvsroot/zsh/zsh/Completion/compinit,v retrieving revision 1.6 diff -u -r1.6 compinit --- Completion/compinit 21 Jun 2001 09:24:39 -0000 1.6 +++ Completion/compinit 4 Mar 2002 08:50:44 -0000 @@ -11,8 +11,10 @@ # If the first line looks like this, the file is autoloaded as a # function and that function will be called to generate the matches # when completing for one of the commands whose <names> are given. +# The names may also be interspersed with `-T <assoc>' options +# specifying for which set of functions this should be added. # -# `#compdef -p <pattern>' +# `#compdef -[pP] <patterns ...>' # This defines a function that should be called to generate matches # for commands whose name matches <pattern>. Note that only one pattern # may be given. @@ -100,13 +102,26 @@ esac done -# The associative array containing the definitions for the commands and +# The name suffixes for the associative arrays containing the functions +# to call. + +typeset -gUa _comp_assocs + +_comp_assocs=(comps) + +# The associative arrays containing the definitions for the commands and # services. -# Definitions for patterns will be stored in the associations `_patcomps' -# and `_postpatcomps'. `_compautos' contains the names and options -# for autoloaded functions that get options. +# Definitions for patterns will be stored in the associations `_pat*' +# and `_postpat*'. +# The assocs for the other function types are created automatically by +# compdef. + +typeset -gA _comps _servicecomps _patcomps _postpatcomps -typeset -gA _comps _services _patcomps _postpatcomps _compautos +# `_compautos' contains the names and options for autoloaded functions +# that get options. + +typeset -gA _compautos # The associative array use to report information about the last # completion to the outside. @@ -176,6 +191,9 @@ # The option `-P' is like `-p', but the function will be called after # trying to find a function defined for the command on the line if no # such function could be found. +# In each of these cases the argument list may also contain `-T assoc' +# options to specify the associactive arrays to which the following +# definitions should be added. # With the `-k' option a function for a special completion keys is # defined and immediately bound to those keys. Here, the extra arguments # are the name of one of the builtin completion widgets and any number @@ -191,7 +209,8 @@ # whose names are given as arguments. If combined with the `-p' option # it deletes the definitions for the patterns given as argument. # The `-d' option may not be combined with the `-k' option, i.e. -# definitions for key function can not be removed. +# definitions for key function can not be removed. But one `-T assoc' +# option may follow the `-d' to say which definitions should be removed. # # Examples: # @@ -213,12 +232,12 @@ # delete the definitions for the command names `bar' and `baz' compdef() { - local opt autol type func delete new i ret=0 cmd svc + local opt autol type func delete new i ret=0 cmd svc assoc=comps # Get the options. - if [[ $#* -eq 0 ]]; then - echo "$0: I needs arguments" + if (( ! $# )); then + echo "$0: I need arguments" return 1 fi @@ -247,8 +266,8 @@ done shift OPTIND-1 - if [[ $#* -eq 0 ]]; then - echo "$0: I needs arguments" + if (( ! $# )); then + echo "$0: I need arguments" return 1 fi @@ -257,25 +276,39 @@ # and we define which services to use for the commands. if [[ "$1" = *\=* ]]; then - for i; do - if [[ "$i" = *\=* ]]; then - cmd="${i%%\=*}" - svc="${i#*\=}" - func="$_comps[${(k)_services[(R)$svc]:-$svc}]" - (( $+_services[$svc] )) && svc=$_services[$svc] - [[ -z "$func" ]] && - func="${_patcomps[(K)$svc][1]:-${_postpatcomps[(K)$svc][1]}}" - if [[ -n "$func" ]]; then - _comps[$cmd]="$func" - _services[$cmd]="$svc" + while (( $# )); do + if [[ $1 = -T ]]; then + shift + if (( ! $# )); then + echo "$0: missing type" + return 1 + fi + _comp_assocs=( "$_comp_assocs[@]" "$1" ) + typeset -gA _$1 _service$1 _pat$1 _postpat$1 + assoc="$1" + shift + else + if [[ "$1" = *\=* ]]; then + cmd="${1%%\=*}" + svc="${1#*\=}" + func="$_comps[${(e):-\${(k)_service${assoc}[(R)$svc]:-$svc}}]" + [[ -n ${(e):-\$_service${assoc}[$svc]} ]] && + svc=${(e):-\$_service${assoc}[$svc]} + [[ -z "$func" ]] && + func="${${(e):-\$_pat${assoc}[(K)$svc][1]}:-${(e):-\$_postpat${assoc}[(K)$svc][1]}}" + if [[ -n "$func" ]]; then + eval "_${assoc}"'[$cmd]="$func"' + eval "_service${assoc}"'[$cmd]="$svc"' + else + echo "$0: unknown command or service: $svc" + ret=1 + fi else - echo "$0: unknown command or service: $svc" + echo "$0: invalid argument: $1" ret=1 fi - else - echo "$0: invalid argument: $i" - ret=1 - fi + shift + fi done return ret @@ -290,18 +323,40 @@ case "$type" in pattern) - if [[ $# -gt 1 ]]; then - echo "$0: only one pattern allowed" - return 1 - fi - _patcomps[$1]="$func" + while (( $# )); do + if [[ $1 = -T ]]; then + shift + if (( ! $# )); then + echo "$0: missing type" + return 1 + fi + _comp_assocs=( "$_comp_assocs[@]" "$1" ) + typeset -gA _$1 _service$1 _pat$1 _postpat$1 + assoc="$1" + shift + else + eval "_pat${assoc}"'[$1]="$func"' + shift + fi + done ;; postpattern) - if [[ $# -gt 1 ]]; then - echo "$0: only one pattern allowed" - return 1 - fi - _postpatcomps[$1]="$func" + while (( $# )); do + if [[ $1 = -T ]]; then + shift + if (( ! $# )); then + echo "$0: missing type" + return 1 + fi + _comp_assocs=( "$_comp_assocs[@]" "$1" ) + typeset -gA _$1 _service$1 _pat$1 _postpat$1 + assoc="$1" + shift + else + eval "_postpat${assoc}"'[$1]="$func"' + shift + fi + done ;; widgetkey) while [[ -n $1 ]]; do @@ -321,7 +376,7 @@ fi shift 3 done - ;; + ;; key) if [[ $# -lt 2 ]]; then echo "$0: missing keys" @@ -348,40 +403,66 @@ done ;; *) - # For commands store the function name in the `_comps' + # For commands store the function name in the # associative array, command names as keys. - for i; do - if [[ "$i" = *\=* ]]; then - cmd="${i%%\=*}" - svc=yes + while (( $# )); do + if [[ $1 = -T ]]; then + shift + if (( ! $# )); then + echo "$0: missing type" + return 1 + fi + _comp_assocs=( "$_comp_assocs[@]" "$1" ) + typeset -gA _$1 _service$1 _pat$1 _postpat$1 + assoc="$1" + shift else - cmd="$i" - svc= + if [[ "$1" = *\=* ]]; then + cmd="${1%%\=*}" + svc=yes + else + cmd="$1" + svc= + fi + if [[ -z "$new" || -z "${(e):-\$_${assoc}[$1]}" ]]; then + eval "_${assoc}"'[$cmd]="$func"' + [[ -n "$svc" ]] && eval "_service${assoc}"'[$cmd]="${1#*\=}"' + fi + shift fi - if [[ -z "$new" || "${+_comps[$i]}" -eq 0 ]]; then - _comps[$cmd]="$func" - if [[ -n "$svc" ]]; then _services[$cmd]="${i#*\=}"; fi - fi done ;; esac else # Handle the `-d' option, deleting. + + if [[ $1 = -T ]]; then + shift + if (( ! $# )); then + echo "$0: missing type" + return 1 + fi + _comp_assocs=( "$_comp_assocs[@]" "$1" ) + typeset -gA _$1 _service$1 _pat$1 _postpat$1 + assoc="$1" + shift + fi + case "$type" in pattern) - unset "_patcomps[$^@]" + unset "_pat${assoc}[$^@]" ;; postpattern) - unset "_postpatcomps[$^@]" + unset "_postpat${assoc}[$^@]" ;; key) # Oops, cannot do that yet. echo "$0: cannot restore key bindings" - return 1v + return 1 ;; *) - unset "_comps[$^@]" + unset "_${assoc}[$^@]" esac fi } Index: Completion/Base/Completer/_complete =================================================================== RCS file: /cvsroot/zsh/zsh/Completion/Base/Completer/_complete,v retrieving revision 1.3 diff -u -r1.3 _complete --- Completion/Base/Completer/_complete 22 Jan 2002 10:22:48 -0000 1.3 +++ Completion/Base/Completer/_complete 4 Mar 2002 08:50:44 -0000 @@ -95,7 +95,7 @@ comp="$_comps[-first-]" if [[ -n "$comp" ]]; then - service="${_services[-first-]:--first-}" + service="${_servicecomps[-first-]:--first-}" ccarray[3]=-first- eval "$comp" && ret=0 if [[ "$_compskip" = all ]]; then @@ -124,7 +124,7 @@ ccarray[3]="$cname" comp="$_comps[$cname]" - service="${_services[$cname]:-$cname}" + service="${_servicecomps[$cname]:-$cname}" # If not, we use default completion, if any. @@ -134,9 +134,9 @@ return 1 fi comp="$_comps[-default-]" + service="${_servicecomps[-default-]:--default-}" fi - [[ -n "$comp" ]] && - service="${_services[-default-]:--default-}" && eval "$comp" && ret=0 + [[ -n "$comp" ]] && eval "$comp" && ret=0 fi _compskip= Index: Completion/Base/Core/_dispatch =================================================================== RCS file: Completion/Base/Core/_dispatch diff -N Completion/Base/Core/_dispatch --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Completion/Base/Core/_dispatch 4 Mar 2002 08:50:44 -0000 @@ -0,0 +1,98 @@ +#autoload + +local comp pat val name i ret=1 _compskip="$_compskip" +local curcontext="$curcontext" service str comptype noskip def +local __comps __patcomps __postpatcomps __services + +# If we get the option `-s', we don't reset `_compskip'. + +while [[ "$1" = -[sd] ]]; do + if [[ "$1" = -s ]]; then + noskip=yes + else + def=yes + fi + shift +done + +[[ -z "$noskip" ]] && _compskip= + +comptype=$1 + +__comps=_$1 + +(( ${(P)+__comps} )) || return 1 + +__patcomps=_pat$1 +__postpatcomps=_postpat$1 +__services=_service$1 + +shift + +# See if there are any matching pattern completions. + +if [[ "$_compskip" != (all|*patterns*) ]]; then + + for str in "$@"; do + [[ -n "$str" ]] || continue + service="${${(e):-\$${__services}[\$str]}:-$str}" + for i in "${(@e):-\$${__patcomps}[(K)\$str]}"; do + "$i" && ret=0 + if [[ "$_compskip" = *patterns* ]]; then + break + elif [[ "$_compskip" = all ]]; then + _compskip='' + return ret + fi + done + done +fi + +# Now look up the names in the normal completion array. + +ret=1 +for str in "$@"; do + [[ -n "$str" ]] || continue + name="$str" + comp="${(e):-\$${__comps}[\$str]}" + service="${${(e):-\$${__services}[\$str]}:-$str}" + + [[ -z "$comp" ]] || break +done + +# And generate the matches, probably using default completion. + +if [[ -n "$comp" ]]; then + _compskip=patterns + eval "$comp" && ret=0 + [[ "$_compskip" = (all|*patterns*) ]] && return ret +elif [[ "$_compskip" != *default* ]]; then + name=-default- + comp="${(e):-\$${__comps}[-default-]}" +fi + +if [[ "$_compskip" != (all|*patterns*) ]]; then + for str; do + [[ -n "$str" ]] || continue + service="${${(e):-\$${__services}[\$str]}:-$str}" + for i in "${(@e):-\$${__postpatcomps}[(K)\$str]}"; do + _compskip=default + "$i" && ret=0 + if [[ "$_compskip" = *patterns* ]]; then + break + elif [[ "$_compskip" = all ]]; then + _compskip='' + return ret + fi + done + done +fi + +[[ "$name" = -default- && -n "$comp" && + "$_compskip" != (all|*default*) ]] && + service="${${(e):-\$${__services}[-default-]}:--default-}" && + eval "$comp" && ret=0 + +_compskip='' + +return ret Index: Completion/Base/Core/_normal =================================================================== RCS file: /cvsroot/zsh/zsh/Completion/Base/Core/_normal,v retrieving revision 1.2 diff -u -r1.2 _normal --- Completion/Base/Core/_normal 21 Jan 2002 16:13:18 -0000 1.2 +++ Completion/Base/Core/_normal 4 Mar 2002 08:50:44 -0000 @@ -1,20 +1,16 @@ #compdef -command-line- -local comp command cmd1 cmd2 pat val name i ret=1 _compskip="$_compskip" -local curcontext="$curcontext" service +local _comp_command1 _comp_command2 skip -# If we get the option `-s', we don't reset `_compskip'. This ensures -# that a value set in the function for the `-first-' context is kept, -# but that we still use pattern functions when we were called form -# another completion function. - -[[ "$1" = -s ]] || _compskip='' +if [[ "$1" = -s ]]; then + skip=(-s) +else + skip=() + _compskip='' +fi -# Completing in command position? If not we set up `cmd1' and `cmd2' as -# two strings we have to search in the completion definition arrays (e.g. -# a path and the last path name component). +# Completing in command position? -command="$words[1]" if [[ CURRENT -eq 1 ]]; then curcontext="${curcontext%:*:*}:-command-:" @@ -22,107 +18,8 @@ [[ -n "$comp" ]] && eval "$comp" && ret=0 return ret -else - if (( $+builtins[$command] + $+functions[$command] )); then - cmd1="$command" - curcontext="${curcontext%:*:*}:${cmd1}:" - elif [[ "$command[1]" = '=' ]]; then - eval cmd1\=$command - cmd2="$command[2,-1]" - curcontext="${curcontext%:*:*}:${cmd2}:" - elif [[ "$command" = ..#/* ]]; then - cmd1="${PWD}/$command" - cmd2="${command:t}" - curcontext="${curcontext%:*:*}:${cmd2}:" - elif [[ "$command" = */* ]]; then - cmd1="$command" - cmd2="${command:t}" - curcontext="${curcontext%:*:*}:${cmd2}:" - else - cmd1="$command" - cmd2="$commands[$command]" - curcontext="${curcontext%:*:*}:${cmd1}:" - fi -fi - -# See if there are any matching pattern completions. - -if [[ "$_compskip" != (all|*patterns*) ]]; then - service="${_services[$cmd1]:-$cmd1}" - for i in "${(@)_patcomps[(K)$cmd1]}"; do - "$i" && ret=0 - if [[ "$_compskip" = *patterns* ]]; then - break - elif [[ "$_compskip" = all ]]; then - _compskip='' - return ret - fi - done - if [[ -n "$cmd2" ]]; then - service="${_services[$cmd2]:-$cmd2}" - for i in "${(@)_patcomps[(K)$cmd2]}"; do - "$i" && ret=0 - if [[ "$_compskip" = *patterns* ]]; then - break - elif [[ "$_compskip" = all ]]; then - _compskip='' - return ret - fi - done - fi fi -# Now look up the two names in the normal completion array. - -ret=1 -name="$cmd1" -comp="$_comps[$cmd1]" -service="${_services[$cmd1]:-$cmd1}" - -[[ -z "$comp" ]] && - name="$cmd2" comp="$_comps[$cmd2]" service="${_services[$cmd2]:-$cmd2}" - -# And generate the matches, probably using default completion. - -if [[ -n "$comp" ]]; then - _compskip=patterns - eval "$comp" && ret=0 - [[ "$_compskip" = (all|*patterns*) ]] && return ret -elif [[ "$_compskip" != *default* ]]; then - name=-default- - comp="$_comps[-default-]" -fi - -if [[ "$_compskip" != (all|*patterns*) ]]; then - service="${_services[$cmd1]:-$cmd1}" - for i in "${(@)_postpatcomps[(K)$cmd1]}"; do - _compskip=default - "$i" && ret=0 - if [[ "$_compskip" = *patterns* ]]; then - break - elif [[ "$_compskip" = all ]]; then - _compskip='' - return ret - fi - done - if [[ -n "$cmd2" ]]; then - service="${_services[$cmd2]:-$cmd2}" - for i in "${(@)_postpatcomps[(K)$cmd2]}"; do - _compskip=default - "$i" && ret=0 - if [[ "$_compskip" = *patterns* ]]; then - break - elif [[ "$_compskip" = all ]]; then - _compskip='' - return ret - fi - done - fi -fi - -[[ "$name" = -default- && -n "$comp" && "$_compskip" != (all|*default*) ]] && - service="${_services[-default-]:--default-}" && eval "$comp" && ret=0 - -_compskip='' +_set_command -return ret +_dispatch -d "$skip[@]" comps "$_comp_command1" "$_comp_command2" Index: Completion/Base/Utility/_contexts =================================================================== RCS file: Completion/Base/Utility/_contexts diff -N Completion/Base/Utility/_contexts --- Completion/Base/Utility/_contexts 21 Jan 2002 16:13:18 -0000 1.2 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,23 +0,0 @@ -#autoload - -# This searches $* in the array for normal completions and calls the result. -# It is used to include completions for another command or special context -# into the list generated by the calling function. -# For example the function for `-subscript-' could call this as in -# `_contexts -math-' to get the completions that would be generated for a -# mathematical context. - -local i tmp ret=1 service or - -if [[ $1 = -o ]]; then - or=yes - shift -fi - -for i; do - tmp="$_comps[$i]" - [[ -n "$tmp" ]] && service="${_services[$i]:-$i}" && eval "$tmp" && ret=0 - [[ -n "$or" && ret -eq 0 ]] && return 0 -done - -return ret Index: Completion/Base/Utility/_set_command =================================================================== RCS file: Completion/Base/Utility/_set_command diff -N Completion/Base/Utility/_set_command --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Completion/Base/Utility/_set_command 4 Mar 2002 08:50:44 -0000 @@ -0,0 +1,31 @@ +#autoload + +# This sets the parameters _comp_command1 and _comp_command2 in the +# calling function. + +local command + +command="$words[1]" + +[[ -z "$command" ]] && return + +if (( $+builtins[$command] + $+functions[$command] )); then + _comp_command1="$command" + curcontext="${curcontext%:*:*}:${_comp_command1}:" +elif [[ "$command[1]" = '=' ]]; then + eval _comp_command2\=$command + _comp_command1="$command[2,-1]" + curcontext="${curcontext%:*:*}:${_comp_command2}:" +elif [[ "$command" = ..#/* ]]; then + _comp_command1="${PWD}/$command" + _comp_command2="${command:t}" + curcontext="${curcontext%:*:*}:${_comp_command2}:" +elif [[ "$command" = */* ]]; then + _comp_command1="$command" + _comp_command2="${command:t}" + curcontext="${curcontext%:*:*}:${_comp_command2}:" +else + _comp_command1="$command" + _comp_command2="$commands[$command]" + curcontext="${curcontext%:*:*}:${_comp_command1}:" +fi Index: Completion/Unix/Command/_gcc =================================================================== RCS file: /cvsroot/zsh/zsh/Completion/Unix/Command/_gcc,v retrieving revision 1.2 diff -u -r1.2 _gcc --- Completion/Unix/Command/_gcc 7 Dec 2001 12:43:33 -0000 1.2 +++ Completion/Unix/Command/_gcc 4 Mar 2002 08:50:44 -0000 @@ -1,8 +1,21 @@ -#compdef gcc +#compdef gcc g++ -T values LDFLAGS CFLAGS CPPFLAGS -local curcontext="$curcontext" state line ret=1 expl args +local curcontext="$curcontext" state line ret=1 expl args args2 typeset -A opt_args +if [[ "$comptype" = values ]]; then + compset -q + words=( fake "$words[@]" ) + (( CURRENT++ )) + if ("$service" = LDFLAGS ]]; then + args2=( '-R:runtime path:->rundir' ) + else + args2=() + fi +else + args2=( '*:input file:_files -g \*.\(\[cCmisSoak\]\|cc\|cxx\|ii\|k\[ih\]\)' ) +fi + args=() case $MACHTYPE in m68*) @@ -243,7 +256,7 @@ -freg-struct-return -fshared-data -fshort-enums \ -fshort-double -fvolatile -fvolatile-global \ -fverbose-asm -fpack-struct \ - '*:input file:_files -g \*.\(\[cCmisSoak\]\|cc\|cxx\|ii\|k\[ih\]\)' && ret=0 + "$args2[@]" && ret=0 case "$state" in @@ -275,6 +288,11 @@ library) _wanted libraries expl library \ compadd - ${^=LD_LIBRARY_PATH:-/usr/lib /usr/local/lib}/lib*.(a|so*)(:t:fr:s/lib//) && ret=0 + ;; +rundir) + compset -P '*:' + compset -S ':*' + _files -/ -S/ -r '\n\t\- /:' "$@" ;; esac Index: Completion/Unix/Command/_su =================================================================== RCS file: /cvsroot/zsh/zsh/Completion/Unix/Command/_su,v retrieving revision 1.2 diff -u -r1.2 _su --- Completion/Unix/Command/_su 21 Jan 2002 16:13:18 -0000 1.2 +++ Completion/Unix/Command/_su 4 Mar 2002 08:50:44 -0000 @@ -17,4 +17,4 @@ shell="${${(M@)${(@f)$(</etc/passwd)}:#$usr*}##*:}" compset -n $base -_contexts -o $shell $shell:t -default- +_dispatch comps $shell $shell:t -default- Index: Completion/Unix/Type/_files =================================================================== RCS file: /cvsroot/zsh/zsh/Completion/Unix/Type/_files,v retrieving revision 1.5 diff -u -r1.5 _files --- Completion/Unix/Type/_files 9 Oct 2001 12:56:03 -0000 1.5 +++ Completion/Unix/Type/_files 4 Mar 2002 08:50:44 -0000 @@ -1,4 +1,4 @@ -#autoload +#compdef -T redirs -default- local opts tmp glob pat pats expl tag i def descr end ign ret=1 match tried local type sdef Index: Completion/Unix/Type/_printers =================================================================== RCS file: /cvsroot/zsh/zsh/Completion/Unix/Type/_printers,v retrieving revision 1.2 diff -u -r1.2 _printers --- Completion/Unix/Type/_printers 25 Jul 2001 12:18:24 -0000 1.2 +++ Completion/Unix/Type/_printers 4 Mar 2002 08:50:44 -0000 @@ -1,4 +1,4 @@ -#autoload +#compdef -T values PRINTER LPDEST local expl ret=1 list disp sep Index: Completion/Unix/Type/_terminals =================================================================== RCS file: /cvsroot/zsh/zsh/Completion/Unix/Type/_terminals,v retrieving revision 1.1 diff -u -r1.1 _terminals --- Completion/Unix/Type/_terminals 16 Jan 2002 16:29:52 -0000 1.1 +++ Completion/Unix/Type/_terminals 4 Mar 2002 08:50:44 -0000 @@ -1,4 +1,4 @@ -#compdef infocmp +#compdef infocmp -T values TERM local desc expl Index: Completion/Unix/Type/_time_zone =================================================================== RCS file: /cvsroot/zsh/zsh/Completion/Unix/Type/_time_zone,v retrieving revision 1.3 diff -u -r1.3 _time_zone --- Completion/Unix/Type/_time_zone 4 Jan 2002 12:09:30 -0000 1.3 +++ Completion/Unix/Type/_time_zone 4 Mar 2002 08:50:44 -0000 @@ -1,4 +1,4 @@ -#compdef +#compdef -T values TZ local expl Index: Completion/X/Type/_x_display =================================================================== RCS file: /cvsroot/zsh/zsh/Completion/X/Type/_x_display,v retrieving revision 1.1 diff -u -r1.1 _x_display --- Completion/X/Type/_x_display 2 Apr 2001 12:09:25 -0000 1.1 +++ Completion/X/Type/_x_display 4 Mar 2002 08:50:44 -0000 @@ -1,3 +1,3 @@ -#autoload +#compdef -T values DISPLAY _tags displays && _hosts -S ':0 ' -r : Index: Completion/Zsh/Command/_compdef =================================================================== RCS file: /cvsroot/zsh/zsh/Completion/Zsh/Command/_compdef,v retrieving revision 1.1 diff -u -r1.1 _compdef --- Completion/Zsh/Command/_compdef 2 Apr 2001 11:27:07 -0000 1.1 +++ Completion/Zsh/Command/_compdef 4 Mar 2002 08:50:44 -0000 @@ -6,6 +6,7 @@ _arguments -C -s -A "-*" -S \ '(-d)-a[make function autoloadable]' \ '(-d -p -P)-n[leave existing definitions intact]' \ + "*-T[select type of completion function]:completion function type:($_comp_assocs)" \ ':completion function:->cfun' \ '*:commands: _command_names' \ - d \ Index: Completion/Zsh/Context/_default =================================================================== RCS file: /cvsroot/zsh/zsh/Completion/Zsh/Context/_default,v retrieving revision 1.1 diff -u -r1.1 _default --- Completion/Zsh/Context/_default 2 Apr 2001 11:22:38 -0000 1.1 +++ Completion/Zsh/Context/_default 4 Mar 2002 08:50:44 -0000 @@ -19,7 +19,7 @@ # allow completion to handle file names after any equals sign. if [[ -o magicequalsubst && "$PREFIX" = *\=* ]]; then - compstate[parameter]="${words[1]:t}-${PREFIX%%\=*}" + compstate[parameter]="${PREFIX%%\=*}" compset -P 1 '*=' _value "$@" else Index: Completion/Zsh/Context/_in_vared =================================================================== RCS file: /cvsroot/zsh/zsh/Completion/Zsh/Context/_in_vared,v retrieving revision 1.1 diff -u -r1.1 _in_vared --- Completion/Zsh/Context/_in_vared 2 Apr 2001 11:23:29 -0000 1.1 +++ Completion/Zsh/Context/_in_vared 4 Mar 2002 08:50:44 -0000 @@ -32,4 +32,4 @@ compstate[insert]="${compstate[insert]//tab /}" -_contexts "$also" +_dispatch comps "$also" Index: Completion/Zsh/Context/_redirect =================================================================== RCS file: /cvsroot/zsh/zsh/Completion/Zsh/Context/_redirect,v retrieving revision 1.1 diff -u -r1.1 _redirect --- Completion/Zsh/Context/_redirect 2 Apr 2001 11:24:17 -0000 1.1 +++ Completion/Zsh/Context/_redirect 4 Mar 2002 08:50:44 -0000 @@ -1,3 +1,17 @@ #compdef -redirect- -_files +# This searches for `<command-name>:<redir-op>' and `<redir-op>', where +# `<redir-op>' is something like `<' or `2>'. + +local strs _comp_command1 _comp_command2 + +_set_command + +strs=( "$compstate[redirect]" ) + +if [[ -n "$_comp_command1" ]]; then + strs=( "${_comp_command1}:$strs[-1]" "$strs[@]" ) + [[ -n "$_comp_command2" ]] && strs=( "${_comp_command2}:$strs[1]" "$strs[@]" ) +fi + +_dispatch -d redirs "$strs[@]" Index: Completion/Zsh/Context/_subscript =================================================================== RCS file: /cvsroot/zsh/zsh/Completion/Zsh/Context/_subscript,v retrieving revision 1.8 diff -u -r1.8 _subscript --- Completion/Zsh/Context/_subscript 11 Sep 2001 09:35:55 -0000 1.8 +++ Completion/Zsh/Context/_subscript 4 Mar 2002 08:50:44 -0000 @@ -113,5 +113,5 @@ return 1 else - _contexts -math- + _dispatch comps -math- fi Index: Completion/Zsh/Context/_value =================================================================== RCS file: /cvsroot/zsh/zsh/Completion/Zsh/Context/_value,v retrieving revision 1.4 diff -u -r1.4 _value --- Completion/Zsh/Context/_value 16 Jan 2002 16:29:52 -0000 1.4 +++ Completion/Zsh/Context/_value 4 Mar 2002 08:50:44 -0000 @@ -1,19 +1,39 @@ -#compdef -value- -array-value- +#compdef -value- -array-value- -T values -default- -_value () { - # You can customize completion for different parameters by writing a - # function `_value:<name>', where <name> is the name of the parameter. - # When completing values of elements of associative arrays, we first - # search for a function `_value:<assoc>-<key>' and then for - # `_value:<assoc>', so it's simple to define different functions - # for different keys or one function for a whole association. - - if (( $+functions[_value:$compstate[parameter]] )); then - "_value:$compstate[parameter]" "$@" - elif (( $+functions[_value:${compstate[parameter]%%-*}] )); then - "_value:${compstate[parameter]%%-*}" "$@" - elif [[ "$compstate[parameter]" != *-* && - "${(Pt)${compstate[parameter]}}" = assoc* ]]; then +# You can customize completion for different parameters by writing +# functions with the tag-line `#compdef -T value <name>'. +# The function searches for the strings `<param-name>:<param-type>' +# and `<param-name>'. If the line contains a command (as in `make foo=<TAB>') +# the string `<command>:<param-name>:<param-type>' is also searched for. + +if [[ "$service" != -default- ]]; then + local strs type + + type="${(Pt)compstate[parameter]}" + + if [[ -z "$type" ]]; then + if [[ "$compstate[parameter]" = *-* ]]; then + type=association-value + elif [[ "$compstate[context]" = value ]]; then + type=scalar + else + type=array + fi + fi + + strs=( "${compstate[parameter]}:$type" "$compstate[parameter]" ) + + if [[ "$compstate[context]" != *value && -n "$_comp_command1" ]]; then + strs=( "${_comp_command1}:$^strs[@]" "$strs[@]" ) + [[ -n "$_comp_command2" ]] && + strs=( "${_comp_command2}:${(@)^strs[-2,-1]}" "$strs[@]" ) + fi + + _dispatch -d values "$strs[@]" +else + if [[ "$compstate[parameter]" != *-* && + "$compstate[context]" = *value && + "${(Pt)${compstate[parameter]}}" = assoc* ]]; then if (( CURRENT & 1 )); then _wanted association-keys expl 'association key' \ compadd -k "$compstate[parameter]" @@ -34,37 +54,4 @@ _default "$@" fi fi -} - -_value:CPPFLAGS () { - compset -q - if compset -P '-I'; then - _files -/ "$@" - else - _default "$@" - fi -} - -_value:LDFLAGS () { - compset -q - if compset -P '-L'; then - _files -/ "$@" - elif compset -P '-R'; then - compset -P '*:' - compset -S ':*' - _files -/ -S/ -r '\n\t\- /:' "$@" - else - _default "$@" - fi -} - -_value:DISPLAY() { _x_display "$@" } - -_value:PRINTER() { _printers "$@" } -_value:LPDEST() { _printers "$@" } - -_value:TERM() { _terminals "$@" } - -_value:TZ() { _time_zone "$@" } - -_value "$@" +fi Index: Doc/Zsh/compsys.yo =================================================================== RCS file: /cvsroot/zsh/zsh/Doc/Zsh/compsys.yo,v retrieving revision 1.146 diff -u -r1.146 compsys.yo --- Doc/Zsh/compsys.yo 25 Feb 2002 09:09:36 -0000 1.146 +++ Doc/Zsh/compsys.yo 4 Mar 2002 08:50:45 -0000 @@ -173,14 +173,32 @@ arguments for the command `tt(cmd)', setting the parameter tt($service) to the string `tt(service)'. The function can then use that parameter to decide what to complete. + +Finally, the list of var(names) may contain tt(-T) options, each +followed by a type name. These type names describe in which set of +completion function definitions the function is to be stored. The +default without a tt(-T) option is `tt(comps)', saying that the +function is a normal completion function. Other type names currently +understood by the completion system are tt(redirs) and tt(values). +The first is used to define specialised completion functions for +use after redirection operators for certain commands and the latter is +used to define functions used when completing values of parameters. +For example, to define the function that should be used when +completing after `tt(foo=<TAB>)' one would use the tag line: + +example(#compdef -T values foo) + +When the function is called, the parameter tt($comptype) will be set +to the type name, making it easy to distinguish what should be +completed. ) -item(tt(#compdef -p) var(pattern))( +item(tt(#compdef -p) var(patterns...))( The file will be made autoloadable and the function defined in it will be called when completing for a command whose name matches the given -var(pattern) (a standard globbing pattern). Note that only one -var(pattern) may be given. +var(pattern) (a standard globbing pattern). As in the first case, the +list of var(patterns) may contain tt(-T) options. ) -item(tt(#compdef -P) var(pattern))( +item(tt(#compdef -P) var(patterns...))( Like the previous one, but the function will be called only if no completion function for the command on the line could be found. ) @@ -254,10 +272,10 @@ findex(compdef) cindex(completion system, adding definitions) startitem() -xitem(tt(compdef) [ tt(-an) ] var(function names...)) -xitem(tt(compdef -d) var(names...)) -xitem(tt(compdef -p) [ tt(-a) ] var(function pattern)) -xitem(tt(compdef -P) [ tt(-a) ] var(function pattern)) +xitem(tt(compdef) [ tt(-an) ] var(function names) [ tt(-T) var(type) ] ...)) +xitem(tt(compdef -d) [ tt(-T) var(type) ] var(names...)) +xitem(tt(compdef -p) [ tt(-a) ] var(function patterns) [ tt(-T) var(type) ] ...) +xitem(tt(compdef -P) [ tt(-a) ] var(function patterns) [ tt(-T) var(type) ] ...) xitem(tt(compdef -k) [ tt(-an) ] var(function style key-sequences...)) item(tt(compdef -K) [ tt(-an) ] var(function name style key-sequences ...))( The first form tells the completion system to call the given @@ -279,6 +297,14 @@ example(compdef '_files -g "*.h"' foo) +The tt(-T) options in the list of var(names) define for which type of +completions the function is to be used, i.e. in which set of +completion functions definitions it should be added. Currently used +tt(type)s are tt(comps) (the default, for normal completion functions +for command completion), tt(values) for completion of parameter values +in assignments and tt(redirs) for completion after redirection +operators. + If the tt(-n) option is given, any existing completion behaviour for particular contexts or commands will not be altered. These definitions can be deleted @@ -3552,19 +3578,6 @@ tt(compadd) when generating matches from the style value, or to the functions for the fields if they are called. ) -findex(_contexts) -item(tt(_contexts) [ tt(-o) ] var(names) ...)( -This function looks up the definitions for the context and command -names given as arguments and calls the handler functions for them if -there is a definition (given with the tt(compdef) function). For -example, the function completing inside subscripts might use -`tt(_contexts -math-)' to include the completions generated for -mathematical environments. - -If the tt(-o) option is given, tt(_contexts) returns after the first -context for which completions could be generated, without trying the -other contexts. -) findex(_describe) item(tt(_describe) [ tt(-o) ] var(descr) var(name1) [ var(name2) ] var(opts) ... tt(-)tt(-) ...)( This function is useful for preparing a list of command options or @@ -3643,6 +3656,19 @@ a similar format; this ensures that user-specified styles are correctly passed down to the builtins which implement the internals of completion. ) +findex(_dispatch) +item(tt(_dispatch) [ tt(-d) ] var(type strings ...))( +This function looks up the function defined for the first var(string) +in the set of definitions named var(type) (these are those definitions +defined with `tt(-T )var(type)'). If one is found, it is called to +generate completions. Otherwise the definition for the second +var(string) is looked up and so on. If none is found and the tt(-d) +option is given, the definition for the special name tt(-default-) is +used. + +This function is the one responsible for setting the parameters +tt($service) and tt($comptype). +) findex(_files) item(tt(_files))( The function tt(_files) uses the tt(file-patterns) style and calls @@ -3789,7 +3815,7 @@ ) ) findex(_normal) -item(tt(_normal))( +item(tt(_normal) [ var(type) ])( This function is used for normal command completion. It has two tasks: completing the first word on the command line as the name of a command, and completing the arguments to this command. In the second case, the name of @@ -3808,6 +3834,13 @@ checked after the call to the corresponding completion function. This has the same effect here as in the tt(-first-) context: if it is set, no more completion functions are called even if there are no matches so far. + +If the optional var(type) argument is given, tt(_normal) does not use +the normal associative arrays for its lookup but instead uses the ones +defined for the given var(type), which may currently be one of +tt(comps) for normal completion, tt(redirs) for completion of +command-specific redirections or tt(values) to complete on the right +hand side of parameter assignments. ) findex(_options) item(tt(_options))( -- Sven Wischnowsky wischnow@berkom.de ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Per command _redirect completion 2002-02-28 8:42 ` Sven Wischnowsky 2002-03-01 5:47 ` Bart Schaefer @ 2002-03-01 9:24 ` Oliver Kiddle 2002-03-01 10:49 ` Sven Wischnowsky 1 sibling, 1 reply; 15+ messages in thread From: Oliver Kiddle @ 2002-03-01 9:24 UTC (permalink / raw) To: Sven Wischnowsky, zsh-workers Sven wrote: > - Does anyone know about other places than redirections and values > where this might be interesting to use? Even now it is already easy > to define more sets. Contexts. They've always been mixed in with the commands but I think it'd be logical to now separate them off (with the possible exception of -default-). There wouldn't be much use for service and patterns with them though so the value of separating them is questionable. The only other places I can think of are arguments to math functions and condition codes but they are probably best left until we need them (I thought about adding a file size math function to the stat module so it might be useful someday with that sort of thing). > > Have I also understood correctly, that the compdef changes allow > > multiple uses of -T so that _gzip might start with: > > #compdef gzip gunzip gzcat=gunzip -T values GZIP > > Right. Good? ;-) Yes. Good. Only I just wonder now: if we have to triplicate the list of commands just to handle redirections (normal, < and >) it might end up being a bit tedious. > Felix Rosencrantz wrote: > > > Looks good to me. Though am seeing an error with the value completions. While > > the redirs and normal completion don't seem to have a problem. > > > > host@ TZ=<TAB> > > _normal:74: division by zero > > host@ DISPLAY=<TAB> > > _normal:74: ':' without '?' > > > > _normal:74:service="${${(e):-\$${__services}[$_comp_command1]}:-$_comp_command1}" > > Yup, had this too, somtimes. Try the new and improved patch below... Doesn't seem to be solved - `_do_type:31: ':' without '?'' after TZ=<tab> And, f < <tab> is a bad math expression: operand expected at `<' > +++ ./Completion/Base/Core/_normal Wed Feb 27 22:29:17 2002 > +_set_command > > -return ret > +_do_type "$skip[@]" comps "_$comp_command1" "_$comp_command2" This last line needs the dollars and underscores swapped otherwise all you get is service=_ and default completion. > Only two small value-functions left. And those aren't so small and could arguably live inside _gcc. > > > diff -ur -r ../oz/Completion/Base/Utility/_contexts > > > +# You may also select the assocs to use with the `-T assoc' option. > > > > I know we only renamed it a year ago but _contexts perhaps could be > > better named. > > Hm. I don't think it's too bad, but then I'm not a native English > speaker. It isn't particularly easy thinking of good names even when it is my first language. My problem with the name _contexts is that it isn't just a context (i.e. -parameter-, -equal- etc) that can be given to it as an argument. It can be commands and now also values. > The stuff in _normal has been put into separate function > `_do_type', which needs a better name (for which I need help). > > Between the things to do: > > - Decide on a name for the concept so that we can give _do_type its > final name and update the docs. How about _dispatch? _contexts might then be _redispatch. Could they be merged as one function? I can't see a reason why _contexts oughtn't to be honouring pattern compdefs and they do basically the same job. Thanks. Oliver __________________________________________________ Do You Yahoo!? Everything you'll ever need on one web page from News and Sport to Email and Music Charts http://uk.my.yahoo.com ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Per command _redirect completion 2002-03-01 9:24 ` Oliver Kiddle @ 2002-03-01 10:49 ` Sven Wischnowsky 0 siblings, 0 replies; 15+ messages in thread From: Sven Wischnowsky @ 2002-03-01 10:49 UTC (permalink / raw) To: zsh-workers Patch below is probably the last not-to-be-committed version of this. Oliver Kiddle wrote: > ... > > Contexts. They've always been mixed in with the commands but I think > it'd be logical to now separate them off (with the possible exception > of -default-). There wouldn't be much use for service and patterns with > them though so the value of separating them is questionable. But interesting to think about, good idea. > ... > > Only I just wonder now: if we have to triplicate the list of commands > just to handle redirections (normal, < and >) it might end up being a > bit tedious. I fear I don't understand this. We don't have to change anything unless we want to be able to offer new features (and if anything doesn't work this way it's a bug and I'd like to hear about it). The change is that we now *can* offer different completions after different redirection operators, for different commands and whatnot, and that we can do that conveniently by putting it in the #compdef lines, probably looking at $service in the implementation (as in the _value function in the patch below, for example). > ... > _normal:74:service="${${(e):-\$${__services}[$_comp_command1]}:-$_comp_command1}" > ... > > +_do_type "$skip[@]" comps "_$comp_command1" "_$comp_command2" > > This last line needs the dollars and underscores swapped otherwise all > you get is service=_ and default completion. Yep, I found these, too. Sorry for that. > > Only two small value-functions left. > > And those aren't so small and could arguably live inside _gcc. Another thing I hadn't thought about... sounds sensible. > ... > > It isn't particularly easy thinking of good names even when it is my > first language. My problem with the name _contexts is that it isn't > just a context (i.e. -parameter-, -equal- etc) that can be given to it > as an argument. It can be commands and now also values. But then we are also talking a lot about `contexts' when we really mean `completion after option -foo in command bar'. I'd actually like to think about... > ... > > How about _dispatch? > > _contexts might then be _redispatch. Could they be merged as one > function? I can't see a reason why _contexts oughtn't to be honouring > pattern compdefs and they do basically the same job. ...this. Something I had been thinking about, too. Bye Sven diff -ur -r ../oz/Completion/Base/Completer/_complete ./Completion/Base/Completer/_complete --- ../oz/Completion/Base/Completer/_complete Tue Feb 26 20:56:19 2002 +++ ./Completion/Base/Completer/_complete Wed Feb 27 22:32:22 2002 @@ -95,7 +95,7 @@ comp="$_comps[-first-]" if [[ -n "$comp" ]]; then - service="${_services[-first-]:--first-}" + service="${_servicecomps[-first-]:--first-}" ccarray[3]=-first- eval "$comp" && ret=0 if [[ "$_compskip" = all ]]; then @@ -124,7 +124,7 @@ ccarray[3]="$cname" comp="$_comps[$cname]" - service="${_services[$cname]:-$cname}" + service="${_servicecomps[$cname]:-$cname}" # If not, we use default completion, if any. @@ -134,9 +134,9 @@ return 1 fi comp="$_comps[-default-]" + service="${_servicecomps[-default-]:--default-}" fi - [[ -n "$comp" ]] && - service="${_services[-default-]:--default-}" && eval "$comp" && ret=0 + [[ -n "$comp" ]] && eval "$comp" && ret=0 fi _compskip= diff -ur -r ../oz/Completion/Base/Core/_do_type ./Completion/Base/Core/_do_type --- ../oz/Completion/Base/Core/_do_type Wed Feb 27 22:28:45 2002 +++ ./Completion/Base/Core/_do_type Thu Feb 28 22:34:42 2002 @@ -0,0 +1,91 @@ +#autoload + +local comp pat val name i ret=1 _compskip="$_compskip" +local curcontext="$curcontext" service str +local __comps __patcomps __postpatcomps __services + +# If we get the option `-s', we don't reset `_compskip'. + +if [[ "$1" = -s ]]; then + shift +else + _compskip='' +fi + +__comps=_$1 + +(( ${(P)+__comps} )) || return 1 + +__patcomps=_pat$1 +__postpatcomps=_postpat$1 +__services=_service$1 + +shift + +# See if there are any matching pattern completions. + +if [[ "$_compskip" != (all|*patterns*) ]]; then + + for str in "$@"; do + [[ -n "$str" ]] || continue + service="${${(e):-\$${__services}[\$str]}:-$str}" + for i in "${(@e):-\$${__patcomps}[(K)\$str]}"; do + "$i" && ret=0 + if [[ "$_compskip" = *patterns* ]]; then + break + elif [[ "$_compskip" = all ]]; then + _compskip='' + return ret + fi + done + done +fi + +# Now look up the names in the normal completion array. + +ret=1 +for str in "$@"; do + [[ -n "$str" ]] || continue + name="$str" + comp="${(e):-\$${__comps}[\$str]}" + service="${${(e):-\$${__services}[\$str]}:-$str}" + + [[ -z "$comp" ]] || break +done + +# And generate the matches, probably using default completion. + +if [[ -n "$comp" ]]; then + _compskip=patterns + eval "$comp" && ret=0 + [[ "$_compskip" = (all|*patterns*) ]] && return ret +elif [[ "$_compskip" != *default* ]]; then + name=-default- + comp="${(e):-\$${__comps}[-default-]}" +fi + +if [[ "$_compskip" != (all|*patterns*) ]]; then + for str; do + [[ -n "$str" ]] || continue + service="${${(e):-\$${__services}[\$str]}:-$str}" + for i in "${(@e):-\$${__postpatcomps}[(K)\$str]}"; do + _compskip=default + "$i" && ret=0 + if [[ "$_compskip" = *patterns* ]]; then + break + elif [[ "$_compskip" = all ]]; then + _compskip='' + return ret + fi + done + done +fi + +[[ "$name" = -default- && -n "$comp" && + "$_compskip" != (all|*default*) ]] && + service="${${(e):-\$${__services}[-default-]}:--default-}" && + eval "$comp" && ret=0 + +_compskip='' + +return ret diff -ur -r ../oz/Completion/Base/Core/_normal ./Completion/Base/Core/_normal --- ../oz/Completion/Base/Core/_normal Tue Feb 26 20:56:19 2002 +++ ./Completion/Base/Core/_normal Wed Feb 27 22:29:17 2002 @@ -1,20 +1,16 @@ #compdef -command-line- -local comp command cmd1 cmd2 pat val name i ret=1 _compskip="$_compskip" -local curcontext="$curcontext" service +local _comp_command1 _comp_command2 skip -# If we get the option `-s', we don't reset `_compskip'. This ensures -# that a value set in the function for the `-first-' context is kept, -# but that we still use pattern functions when we were called form -# another completion function. - -[[ "$1" = -s ]] || _compskip='' +if [[ "$1" = -s ]]; then + skip=(-s) +else + skip=() + _compskip='' +fi -# Completing in command position? If not we set up `cmd1' and `cmd2' as -# two strings we have to search in the completion definition arrays (e.g. -# a path and the last path name component). +# Completing in command position? -command="$words[1]" if [[ CURRENT -eq 1 ]]; then curcontext="${curcontext%:*:*}:-command-:" @@ -22,107 +18,8 @@ [[ -n "$comp" ]] && eval "$comp" && ret=0 return ret -else - if (( $+builtins[$command] + $+functions[$command] )); then - cmd1="$command" - curcontext="${curcontext%:*:*}:${cmd1}:" - elif [[ "$command[1]" = '=' ]]; then - eval cmd1\=$command - cmd2="$command[2,-1]" - curcontext="${curcontext%:*:*}:${cmd2}:" - elif [[ "$command" = ..#/* ]]; then - cmd1="${PWD}/$command" - cmd2="${command:t}" - curcontext="${curcontext%:*:*}:${cmd2}:" - elif [[ "$command" = */* ]]; then - cmd1="$command" - cmd2="${command:t}" - curcontext="${curcontext%:*:*}:${cmd2}:" - else - cmd1="$command" - cmd2="$commands[$command]" - curcontext="${curcontext%:*:*}:${cmd1}:" - fi -fi - -# See if there are any matching pattern completions. - -if [[ "$_compskip" != (all|*patterns*) ]]; then - service="${_services[$cmd1]:-$cmd1}" - for i in "${(@)_patcomps[(K)$cmd1]}"; do - "$i" && ret=0 - if [[ "$_compskip" = *patterns* ]]; then - break - elif [[ "$_compskip" = all ]]; then - _compskip='' - return ret - fi - done - if [[ -n "$cmd2" ]]; then - service="${_services[$cmd2]:-$cmd2}" - for i in "${(@)_patcomps[(K)$cmd2]}"; do - "$i" && ret=0 - if [[ "$_compskip" = *patterns* ]]; then - break - elif [[ "$_compskip" = all ]]; then - _compskip='' - return ret - fi - done - fi fi -# Now look up the two names in the normal completion array. - -ret=1 -name="$cmd1" -comp="$_comps[$cmd1]" -service="${_services[$cmd1]:-$cmd1}" - -[[ -z "$comp" ]] && - name="$cmd2" comp="$_comps[$cmd2]" service="${_services[$cmd2]:-$cmd2}" - -# And generate the matches, probably using default completion. - -if [[ -n "$comp" ]]; then - _compskip=patterns - eval "$comp" && ret=0 - [[ "$_compskip" = (all|*patterns*) ]] && return ret -elif [[ "$_compskip" != *default* ]]; then - name=-default- - comp="$_comps[-default-]" -fi - -if [[ "$_compskip" != (all|*patterns*) ]]; then - service="${_services[$cmd1]:-$cmd1}" - for i in "${(@)_postpatcomps[(K)$cmd1]}"; do - _compskip=default - "$i" && ret=0 - if [[ "$_compskip" = *patterns* ]]; then - break - elif [[ "$_compskip" = all ]]; then - _compskip='' - return ret - fi - done - if [[ -n "$cmd2" ]]; then - service="${_services[$cmd2]:-$cmd2}" - for i in "${(@)_postpatcomps[(K)$cmd2]}"; do - _compskip=default - "$i" && ret=0 - if [[ "$_compskip" = *patterns* ]]; then - break - elif [[ "$_compskip" = all ]]; then - _compskip='' - return ret - fi - done - fi -fi - -[[ "$name" = -default- && -n "$comp" && "$_compskip" != (all|*default*) ]] && - service="${_services[-default-]:--default-}" && eval "$comp" && ret=0 - -_compskip='' +_set_command -return ret +_do_type "$skip[@]" comps "_$comp_command1" "_$comp_command2" diff -ur -r ../oz/Completion/Base/Utility/_contexts ./Completion/Base/Utility/_contexts --- ../oz/Completion/Base/Utility/_contexts Tue Feb 26 20:56:19 2002 +++ ./Completion/Base/Utility/_contexts Tue Feb 26 23:44:51 2002 @@ -6,8 +6,19 @@ # For example the function for `-subscript-' could call this as in # `_contexts -math-' to get the completions that would be generated for a # mathematical context. +# You may also select the assocs to use with the `-T assoc' option. -local i tmp ret=1 service or +local i tmp ret=1 service or type + +type=(-T comps) +zparseopts -D o=or T:=type + +type="$type[2]" +if (( $#or )); then + or=yes +else + or= +fi if [[ $1 = -o ]]; then or=yes @@ -15,8 +26,9 @@ fi for i; do - tmp="$_comps[$i]" - [[ -n "$tmp" ]] && service="${_services[$i]:-$i}" && eval "$tmp" && ret=0 + tmp="${(e):-\$_${type}[$i]}" + [[ -n "$tmp" ]] && service="${${(e):-\$_service${type}[$i]}:-$i}" && + eval "$tmp" && ret=0 [[ -n "$or" && ret -eq 0 ]] && return 0 done diff -ur -r ../oz/Completion/Base/Utility/_set_command ./Completion/Base/Utility/_set_command --- ../oz/Completion/Base/Utility/_set_command Wed Feb 27 22:28:17 2002 +++ ./Completion/Base/Utility/_set_command Thu Feb 28 22:11:13 2002 @@ -0,0 +1,31 @@ +#autoload + +# This sets the parameters _comp_command1 and _comp_command2 in the +# calling function. + +local command + +command="$words[1]" + +[[ -z "$command" ]] && return + +if (( $+builtins[$command] + $+functions[$command] )); then + _comp_command1="$command" + curcontext="${curcontext%:*:*}:${_comp_command1}:" +elif [[ "$command[1]" = '=' ]]; then + eval _comp_command2\=$command + _comp_command1="$command[2,-1]" + curcontext="${curcontext%:*:*}:${_comp_command2}:" +elif [[ "$command" = ..#/* ]]; then + _comp_command1="${PWD}/$command" + _comp_command2="${command:t}" + curcontext="${curcontext%:*:*}:${_comp_command2}:" +elif [[ "$command" = */* ]]; then + _comp_command1="$command" + _comp_command2="${command:t}" + curcontext="${curcontext%:*:*}:${_comp_command2}:" +else + _comp_command2="$command" + _comp_command1="$commands[$command]" + curcontext="${curcontext%:*:*}:${_comp_command1}:" +fi diff -ur -r ../oz/Completion/Unix/Type/_files ./Completion/Unix/Type/_files --- ../oz/Completion/Unix/Type/_files Tue Feb 26 20:56:19 2002 +++ ./Completion/Unix/Type/_files Wed Feb 27 22:35:35 2002 @@ -1,4 +1,4 @@ -#autoload +#compdef -T redirs -default- local opts tmp glob pat pats expl tag i def descr end ign ret=1 match tried local type sdef diff -ur -r ../oz/Completion/Unix/Type/_printers ./Completion/Unix/Type/_printers --- ../oz/Completion/Unix/Type/_printers Tue Feb 26 20:56:19 2002 +++ ./Completion/Unix/Type/_printers Wed Feb 27 21:18:55 2002 @@ -1,4 +1,4 @@ -#autoload +#compdef -T values PRINTER LPDEST local expl ret=1 list disp sep diff -ur -r ../oz/Completion/Unix/Type/_terminals ./Completion/Unix/Type/_terminals --- ../oz/Completion/Unix/Type/_terminals Tue Feb 26 20:56:19 2002 +++ ./Completion/Unix/Type/_terminals Wed Feb 27 21:19:33 2002 @@ -1,4 +1,4 @@ -#compdef infocmp +#compdef infocmp -T values TERM local desc expl diff -ur -r ../oz/Completion/Unix/Type/_time_zone ./Completion/Unix/Type/_time_zone --- ../oz/Completion/Unix/Type/_time_zone Tue Feb 26 20:56:19 2002 +++ ./Completion/Unix/Type/_time_zone Wed Feb 27 21:20:11 2002 @@ -1,4 +1,4 @@ -#compdef +#compdef -T values TZ local expl diff -ur -r ../oz/Completion/X/Type/_x_display ./Completion/X/Type/_x_display --- ../oz/Completion/X/Type/_x_display Tue Feb 26 20:56:19 2002 +++ ./Completion/X/Type/_x_display Wed Feb 27 21:18:14 2002 @@ -1,3 +1,3 @@ -#autoload +#compdef -T values DISPLAY _tags displays && _hosts -S ':0 ' -r : diff -ur -r ../oz/Completion/Zsh/Context/_default ./Completion/Zsh/Context/_default --- ../oz/Completion/Zsh/Context/_default Tue Feb 26 20:56:19 2002 +++ ./Completion/Zsh/Context/_default Wed Feb 27 21:58:26 2002 @@ -19,7 +19,7 @@ # allow completion to handle file names after any equals sign. if [[ -o magicequalsubst && "$PREFIX" = *\=* ]]; then - compstate[parameter]="${words[1]:t}-${PREFIX%%\=*}" + compstate[parameter]="${PREFIX%%\=*}" compset -P 1 '*=' _value "$@" else diff -ur -r ../oz/Completion/Zsh/Context/_redirect ./Completion/Zsh/Context/_redirect --- ../oz/Completion/Zsh/Context/_redirect Tue Feb 26 20:56:19 2002 +++ ./Completion/Zsh/Context/_redirect Thu Feb 28 22:11:51 2002 @@ -1,3 +1,14 @@ #compdef -redirect- -_files +local strs _comp_command1 _comp_command2 + +_set_command + +strs=( "$compstate[redirect]" ) + +if [[ -n "$_comp_command1" ]]; then + strs=( "${_comp_command1}:$strs[-1]" "$strs[@]" ) + [[ -n "$_comp_command2" ]] && strs=( "${_comp_command2}:$strs[1]" "$strs[@]" ) +fi + +_do_type redirs "$strs[@]" diff -ur -r ../oz/Completion/Zsh/Context/_value ./Completion/Zsh/Context/_value --- ../oz/Completion/Zsh/Context/_value Wed Feb 27 00:14:27 2002 +++ ./Completion/Zsh/Context/_value Thu Feb 28 22:35:36 2002 @@ -1,19 +1,36 @@ -#compdef -value- -array-value- +#compdef -value- -array-value- -T values -default- -_value () { - # You can customize completion for different parameters by writing a - # function `_value:<name>', where <name> is the name of the parameter. - # When completing values of elements of associative arrays, we first - # search for a function `_value:<assoc>-<key>' and then for - # `_value:<assoc>', so it's simple to define different functions - # for different keys or one function for a whole association. - - if (( $+functions[_value:$compstate[parameter]] )); then - "_value:$compstate[parameter]" "$@" - elif (( $+functions[_value:${compstate[parameter]%%-*}] )); then - "_value:${compstate[parameter]%%-*}" "$@" - elif [[ "$compstate[parameter]" != *-* && - "${(Pt)${compstate[parameter]}}" = assoc* ]]; then +# You can customize completion for different parameters by writing +# functions with the tag-line `#compdef -T value <name>'. + +if [[ "$service" != -default- ]]; then + local strs type + + type="${(Pt)compstate[parameter]}" + + if [[ -z "$type" ]]; then + if [[ "$compstate[parameter]" = *-* ]]; then + type=association-value + elif [[ "$compstate[context]" = value ]]; then + type=scalar + else + type=array + fi + fi + + strs=( "${compstate[parameter]}:$type" "$compstate[parameter]" ) + + if [[ "$compstate[context]" != *value && -n "$_comp_command1" ]]; then + strs=( "${_comp_command1}:$^strs[@]" "$strs[@]" ) + [[ -n "$_comp_command2" ]] && + strs=( "${_comp_command2}:${(@)^strs[-2,-1]}" "$strs[@]" ) + fi + + _do_type values "$strs[@]" +else + if [[ "$compstate[parameter]" != *-* && + "$compstate[context]" = *value && + "${(Pt)${compstate[parameter]}}" = assoc* ]]; then if (( CURRENT & 1 )); then _wanted association-keys expl 'association key' \ compadd -k "$compstate[parameter]" @@ -34,37 +51,4 @@ _default "$@" fi fi -} - -_value:CPPFLAGS () { - compset -q - if compset -P '-I'; then - _files -/ "$@" - else - _default "$@" - fi -} - -_value:LDFLAGS () { - compset -q - if compset -P '-L'; then - _files -/ "$@" - elif compset -P '-R'; then - compset -P '*:' - compset -S ':*' - _files -/ -S/ -r '\n\t\- /:' "$@" - else - _default "$@" - fi -} - -_value:DISPLAY() { _x_display "$@" } - -_value:PRINTER() { _printers "$@" } -_value:LPDEST() { _printers "$@" } - -_value:TERM() { _terminals "$@" } - -_value:TZ() { _time_zone "$@" } - -_value "$@" +fi diff -ur -r ../oz/Completion/Zsh/Context/_value_CPPFLAGS ./Completion/Zsh/Context/_value_CPPFLAGS --- ../oz/Completion/Zsh/Context/_value_CPPFLAGS Wed Feb 27 00:14:27 2002 +++ ./Completion/Zsh/Context/_value_CPPFLAGS Wed Feb 27 00:25:03 2002 @@ -0,0 +1,8 @@ +#compdef -T values CPPFLAGS + +compset -q +if compset -P '-I'; then + _files -/ "$@" +else + _default "$@" +fi diff -ur -r ../oz/Completion/Zsh/Context/_value_LDFLAGS ./Completion/Zsh/Context/_value_LDFLAGS --- ../oz/Completion/Zsh/Context/_value_LDFLAGS Wed Feb 27 00:14:27 2002 +++ ./Completion/Zsh/Context/_value_LDFLAGS Wed Feb 27 00:25:24 2002 @@ -0,0 +1,12 @@ +#compdef -T values LDFLAGS + +compset -q +if compset -P '-L'; then + _files -/ "$@" +elif compset -P '-R'; then + compset -P '*:' + compset -S ':*' + _files -/ -S/ -r '\n\t\- /:' "$@" +else + _default "$@" +fi diff -ur -r ../oz/Completion/Zsh/Context/_value~ ./Completion/Zsh/Context/_value~ --- ../oz/Completion/Zsh/Context/_value~ Wed Feb 27 00:14:27 2002 +++ ./Completion/Zsh/Context/_value~ Wed Feb 27 22:03:03 2002 @@ -0,0 +1,52 @@ +#compdef -value- -array-value- + +# You can customize completion for different parameters by writing +# functions with the tag-line `#compdef -T value <name>'. + +local strs type + +type="${(Pt)compstate[parameter]}" + +if [[ -z "$type" ]]; then + if [[ "$compstate[parameter]" = *-* ]]; then + type=association-value + elif [[ "$compstate[context]" = value ]]; then + type=scalar + else + type=array + fi +fi + +strs=( "$compstate[parameter]" "${compstate[parameter]}:$type" ) + +if [[ "$compstate[context]" != *value && -n "$_comp_command1" ]]; then + strs=( "$strs[@]" "${_comp_command1}:$^strs[@]" ) + [[ -n "$_comp_command2" ]] && + strs=( "$strs[@]" "${_comp_command2}:${(@)^strs[1,2]}" ) +fi + +_do_type values "$strs[@]" && return 0 + +if [[ "$compstate[parameter]" != *-* && + "$compstate[context]" = *value && + "${(Pt)${compstate[parameter]}}" = assoc* ]]; then + if (( CURRENT & 1 )); then + _wanted association-keys expl 'association key' \ + compadd -k "$compstate[parameter]" + else + compstate[parameter]="${compstate[parameter]}-${words[CURRENT-1]}" + _value "$@" + fi +else + local pats + + if { zstyle -a ":completion:${curcontext}:" assign-list pats && + [[ "$compstate[parameter]" = (${(j:|:)~pats}) ]] } || + [[ "$PREFIX$SUFFIX" = *:* ]]; then + compset -P '*:' + compset -S ':*' + _default -r '\-\n\t /:' "$@" + else + _default "$@" + fi +fi diff -ur -r ../oz/Completion/compdump ./Completion/compdump --- ../oz/Completion/compdump Tue Feb 26 20:56:19 2002 +++ ./Completion/compdump Wed Feb 27 23:10:35 2002 @@ -16,7 +16,7 @@ emulate -L zsh setopt extendedglob noshglob -typeset _d_file _d_f _d_bks _d_line _d_als _d_files +typeset _d_file _d_f _d_bks _d_line _d_als _d_files _d_name _d_tmp _d_file=${_comp_dumpfile-${0:h}/compinit.dump}.$HOST.$$ [[ $_d_file = //* ]] && _d_file=${_d_file[2,-1]} @@ -35,33 +35,43 @@ print "#files: $#_d_files" > $_d_file -# First dump the arrays _comps, _services and _patcomps. The quoting +# First dump the arrays _comps, _servicecomps and _patcomps. The quoting # hieroglyphics ensure that a single quote inside a variable is itself # correctly quoted. -print "_comps=(" >> $_d_file -for _d_f in ${(ok)_comps}; do - print -r - "${(q)_d_f}" "${(q)_comps[$_d_f]}" -done >> $_d_file -print ")" >> $_d_file - -print "_services=(" >> $_d_file -for _d_f in ${(ok)_services}; do - print -r - "${(q)_d_f}" "${(q)_services[$_d_f]}" -done >> $_d_file -print ")" >> $_d_file - -print "\n_patcomps=(" >> $_d_file -for _d_f in "${(ok@)_patcomps}"; do - print -r - "${(q)_d_f}" "${(q)_patcomps[$_d_f]}" -done >> $_d_file -print ")" >> $_d_file +for _d_name in $_comp_assocs; do + + print "\n\ntypeset -gA _$_d_name _service$_d_name _pat$_d_name _postpat$_d_name" + + _d_tmp="_${_d_name}" + print "\n_${_d_name}=(" + for _d_f in ${(Pok)_d_tmp}; do + print -r - "${(q)_d_f}" "${(q)${(e):-\$${_d_tmp}[$_d_f]}}" + done + print ")" + + _d_tmp="_service${_d_name}" + print "\n_service${_d_name}=(" + for _d_f in ${(Pok)_d_tmp}; do + print -r - "${(q)_d_f}" "${(q)${(e):-\$${_d_tmp}[$_d_f]}}" + done + print ")" + + _d_tmp="_pat${_d_name}" + print "\n_pat${_d_name}=(" + for _d_f in ${(Pok)_d_tmp}; do + print -r - "${(q)_d_f}" "${(q)${(e):-\$${_d_tmp}[$_d_f]}}" + done + print ")" + + _d_tmp="_postpat${_d_name}" + print "\n_postpat${_d_name}=(" + for _d_f in ${(Pok)_d_tmp}; do + print -r - "${(q)_d_f}" "${(q)${(e):-\$${_d_tmp}[$_d_f]}}" + done + print ")" -print "\n_postpatcomps=(" >> $_d_file -for _d_f in "${(ok@)_postpatcomps}"; do - print -r - "${(q)_d_f}" "${(q)_postpatcomps[$_d_f]}" done >> $_d_file -print ")" >> $_d_file print "\n_compautos=(" >> $_d_file for _d_f in "${(ok@)_compautos}"; do diff -ur -r ../oz/Completion/compinit ./Completion/compinit --- ../oz/Completion/compinit Tue Feb 26 20:56:19 2002 +++ ./Completion/compinit Wed Feb 27 23:08:37 2002 @@ -11,8 +11,10 @@ # If the first line looks like this, the file is autoloaded as a # function and that function will be called to generate the matches # when completing for one of the commands whose <names> are given. +# The names may also be interspersed with `-T <assoc>' options +# specifying for which set of functions this should be added. # -# `#compdef -p <pattern>' +# `#compdef -[pP] <patterns ...>' # This defines a function that should be called to generate matches # for commands whose name matches <pattern>. Note that only one pattern # may be given. @@ -100,13 +102,26 @@ esac done -# The associative array containing the definitions for the commands and +# The name suffixes for the associative arrays containing the functions +# to call. + +typeset -Ua _comp_assocs + +_comp_assocs=(comps) + +# The associative arrays containing the definitions for the commands and # services. -# Definitions for patterns will be stored in the associations `_patcomps' -# and `_postpatcomps'. `_compautos' contains the names and options -# for autoloaded functions that get options. +# Definitions for patterns will be stored in the associations `_pat*' +# and `_postpat*'. +# The assocs for the other function types are created automatically by +# compdef. + +typeset -gA _comps _servicecomps _patcomps _postpatcomps -typeset -gA _comps _services _patcomps _postpatcomps _compautos +# `_compautos' contains the names and options for autoloaded functions +# that get options. + +typeset -gA _compautos # The associative array use to report information about the last # completion to the outside. @@ -176,6 +191,9 @@ # The option `-P' is like `-p', but the function will be called after # trying to find a function defined for the command on the line if no # such function could be found. +# In each of these cases the argument list may also contain `-T assoc' +# options to specify the associactive arrays to which the following +# definitions should be added. # With the `-k' option a function for a special completion keys is # defined and immediately bound to those keys. Here, the extra arguments # are the name of one of the builtin completion widgets and any number @@ -191,7 +209,8 @@ # whose names are given as arguments. If combined with the `-p' option # it deletes the definitions for the patterns given as argument. # The `-d' option may not be combined with the `-k' option, i.e. -# definitions for key function can not be removed. +# definitions for key function can not be removed. But one `-T assoc' +# option may follow the `-d' to say which definitions should be removed. # # Examples: # @@ -213,12 +232,12 @@ # delete the definitions for the command names `bar' and `baz' compdef() { - local opt autol type func delete new i ret=0 cmd svc + local opt autol type func delete new i ret=0 cmd svc assoc=comps # Get the options. - if [[ $#* -eq 0 ]]; then - echo "$0: I needs arguments" + if (( ! $# )); then + echo "$0: I need arguments" return 1 fi @@ -247,8 +266,8 @@ done shift OPTIND-1 - if [[ $#* -eq 0 ]]; then - echo "$0: I needs arguments" + if (( ! $# )); then + echo "$0: I need arguments" return 1 fi @@ -257,25 +276,39 @@ # and we define which services to use for the commands. if [[ "$1" = *\=* ]]; then - for i; do - if [[ "$i" = *\=* ]]; then - cmd="${i%%\=*}" - svc="${i#*\=}" - func="$_comps[${(k)_services[(R)$svc]:-$svc}]" - (( $+_services[$svc] )) && svc=$_services[$svc] - [[ -z "$func" ]] && - func="${_patcomps[(K)$svc][1]:-${_postpatcomps[(K)$svc][1]}}" - if [[ -n "$func" ]]; then - _comps[$cmd]="$func" - _services[$cmd]="$svc" + while (( $# )); do + if [[ $1 = -T ]]; then + shift + if (( ! $# )); then + echo "$0: missing type" + return 1 + fi + _comp_assocs=( "$_comp_assocs[@]" "$1" ) + typeset -gA _$1 _service_$1 _pat$1 _postpat$1 + assoc="$1" + shift + else + if [[ "$1" = *\=* ]]; then + cmd="${1%%\=*}" + svc="${1#*\=}" + func="$_comps[${(e):-\${(k)_service${assoc}[(R)$svc]:-$svc}}]" + [[ -n ${(e):-\$_service${assoc}[$svc]} ]] && + svc=${(e):-\$_service${assoc}[$svc]} + [[ -z "$func" ]] && + func="${${(e):-\$_pat${assoc}[(K)$svc][1]}:-${(e):-\$_postpat${assoc}[(K)$svc][1]}}" + if [[ -n "$func" ]]; then + eval "_${assoc}"'[$cmd]="$func"' + eval "_service${assoc}"'[$cmd]="$svc"' + else + echo "$0: unknown command or service: $svc" + ret=1 + fi else - echo "$0: unknown command or service: $svc" + echo "$0: invalid argument: $1" ret=1 fi - else - echo "$0: invalid argument: $i" - ret=1 - fi + shift + fi done return ret @@ -290,18 +323,40 @@ case "$type" in pattern) - if [[ $# -gt 1 ]]; then - echo "$0: only one pattern allowed" - return 1 - fi - _patcomps[$1]="$func" + while (( $# )); do + if [[ $1 = -T ]]; then + shift + if (( ! $# )); then + echo "$0: missing type" + return 1 + fi + _comp_assocs=( "$_comp_assocs[@]" "$1" ) + typeset -gA _$1 _service_$1 _pat$1 _postpat$1 + assoc="$1" + shift + else + eval "_pat${assoc}"'[$1]="$func"' + shift + fi + done ;; postpattern) - if [[ $# -gt 1 ]]; then - echo "$0: only one pattern allowed" - return 1 - fi - _postpatcomps[$1]="$func" + while (( $# )); do + if [[ $1 = -T ]]; then + shift + if (( ! $# )); then + echo "$0: missing type" + return 1 + fi + _comp_assocs=( "$_comp_assocs[@]" "$1" ) + typeset -gA _$1 _service_$1 _pat$1 _postpat$1 + assoc="$1" + shift + else + eval "_postpat${assoc}"'[$1]="$func"' + shift + fi + done ;; widgetkey) while [[ -n $1 ]]; do @@ -321,7 +376,7 @@ fi shift 3 done - ;; + ;; key) if [[ $# -lt 2 ]]; then echo "$0: missing keys" @@ -348,40 +403,66 @@ done ;; *) - # For commands store the function name in the `_comps' + # For commands store the function name in the # associative array, command names as keys. - for i; do - if [[ "$i" = *\=* ]]; then - cmd="${i%%\=*}" - svc=yes + while (( $# )); do + if [[ $1 = -T ]]; then + shift + if (( ! $# )); then + echo "$0: missing type" + return 1 + fi + _comp_assocs=( "$_comp_assocs[@]" "$1" ) + typeset -gA _$1 _service_$1 _pat$1 _postpat$1 + assoc="$1" + shift else - cmd="$i" - svc= + if [[ "$1" = *\=* ]]; then + cmd="${1%%\=*}" + svc=yes + else + cmd="$1" + svc= + fi + if [[ -z "$new" || -z "${(e):-\$_${assoc}[$1]}" ]]; then + eval "_${assoc}"'[$cmd]="$func"' + [[ -n "$svc" ]] && eval "_service${assoc}"'[$cmd]="${1#*\=}"' + fi + shift fi - if [[ -z "$new" || "${+_comps[$i]}" -eq 0 ]]; then - _comps[$cmd]="$func" - if [[ -n "$svc" ]]; then _services[$cmd]="${i#*\=}"; fi - fi done ;; esac else # Handle the `-d' option, deleting. + + if [[ $1 = -T ]]; then + shift + if (( ! $# )); then + echo "$0: missing type" + return 1 + fi + _comp_assocs=( "$_comp_assocs[@]" "$1" ) + typeset -gA _$1 _service_$1 _pat$1 _postpat$1 + assoc="$1" + shift + fi + case "$type" in pattern) - unset "_patcomps[$^@]" + unset "_pat${assoc}[$^@]" ;; postpattern) - unset "_postpatcomps[$^@]" + unset "_postpat${assoc}[$^@]" ;; key) # Oops, cannot do that yet. echo "$0: cannot restore key bindings" - return 1v + return 1 ;; *) - unset "_comps[$^@]" + unset "_${assoc}[$^@]" esac fi } diff -ur -r ../oz/Doc/Zsh/compsys.yo ./Doc/Zsh/compsys.yo --- ../oz/Doc/Zsh/compsys.yo Tue Feb 26 20:56:17 2002 +++ ./Doc/Zsh/compsys.yo Wed Feb 27 00:37:21 2002 @@ -173,14 +173,27 @@ arguments for the command `tt(cmd)', setting the parameter tt($service) to the string `tt(service)'. The function can then use that parameter to decide what to complete. + +Finally, the list of var(names) may contain tt(-T) options, each +followed by a type name. These type names describe in what kind of +overall context the function is to be used. The default without a +tt(-T) option is `tt(comps)', saying that the function is a normal +completion function. Other type names currently understood by the +completion system are tt(redirs) and tt(values). The first is used to +define specialised completion functions for certain commands and the +latter is used to define functions used when completing values of +parameters. For example, to define the function that should be used +when completing after `tt(foo=<TAB>)' one would use the tag line: + +example(#compdef -T values foo) ) -item(tt(#compdef -p) var(pattern))( +item(tt(#compdef -p) var(patterns...))( The file will be made autoloadable and the function defined in it will be called when completing for a command whose name matches the given -var(pattern) (a standard globbing pattern). Note that only one -var(pattern) may be given. +var(pattern) (a standard globbing pattern). As in the first case, the +list of var(patterns) may contain tt(-T) options. ) -item(tt(#compdef -P) var(pattern))( +item(tt(#compdef -P) var(patterns...))( Like the previous one, but the function will be called only if no completion function for the command on the line could be found. ) @@ -254,10 +267,10 @@ findex(compdef) cindex(completion system, adding definitions) startitem() -xitem(tt(compdef) [ tt(-an) ] var(function names...)) -xitem(tt(compdef -d) var(names...)) -xitem(tt(compdef -p) [ tt(-a) ] var(function pattern)) -xitem(tt(compdef -P) [ tt(-a) ] var(function pattern)) +xitem(tt(compdef) [ tt(-an) ] var(function names) [ tt(-T) var(type) ] ...)) +xitem(tt(compdef -d) [ tt(-T) var(type) ] var(names...)) +xitem(tt(compdef -p) [ tt(-a) ] var(function patterns) [ tt(-T) var(type) ] ...) +xitem(tt(compdef -P) [ tt(-a) ] var(function patterns) [ tt(-T) var(type) ] ...) xitem(tt(compdef -k) [ tt(-an) ] var(function style key-sequences...)) item(tt(compdef -K) [ tt(-an) ] var(function name style key-sequences ...))( The first form tells the completion system to call the given @@ -3553,7 +3566,7 @@ the functions for the fields if they are called. ) findex(_contexts) -item(tt(_contexts) [ tt(-o) ] var(names) ...)( +item(tt(_contexts) [ tt(-o) ] [ tt(-T) var(type) ] var(names) ...)( This function looks up the definitions for the context and command names given as arguments and calls the handler functions for them if there is a definition (given with the tt(compdef) function). For @@ -3564,6 +3577,10 @@ If the tt(-o) option is given, tt(_contexts) returns after the first context for which completions could be generated, without trying the other contexts. + +This function basically calls the tt(_normal) function repeatedly and +if the tt(-T) option is given the var(type) is given to tt(_normal) as +an argument to tell it which type of completion function to use. ) findex(_describe) item(tt(_describe) [ tt(-o) ] var(descr) var(name1) [ var(name2) ] var(opts) ... tt(-)tt(-) ...)( @@ -3789,7 +3806,7 @@ ) ) findex(_normal) -item(tt(_normal))( +item(tt(_normal) [ var(type) ])( This function is used for normal command completion. It has two tasks: completing the first word on the command line as the name of a command, and completing the arguments to this command. In the second case, the name of @@ -3808,6 +3825,13 @@ checked after the call to the corresponding completion function. This has the same effect here as in the tt(-first-) context: if it is set, no more completion functions are called even if there are no matches so far. + +If the optional var(type) argument is given, tt(_normal) does not use +the normal associative arrays for its lookup but instead uses the ones +defined for the given var(type), which may currently be one of +tt(comps) for normal completion, tt(redirs) for completion of +command-specific redirections or tt(values) to complete on the right +hand side of parameter assignments. ) findex(_options) item(tt(_options))( -- Sven Wischnowsky wischnow@berkom.de ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Per command _redirect completion @ 2002-03-02 16:28 Felix Rosencrantz 0 siblings, 0 replies; 15+ messages in thread From: Felix Rosencrantz @ 2002-03-02 16:28 UTC (permalink / raw) To: zsh-workers Still having problem with the latest uncommitted patch: When trying to complete TZ I get: _do_type:31: ':' without '?' Which only happens from a shell where .zcompdump didn't pre-exist. Subsequent shells seem to work. Also, completion for command flags/args doesn't work. The command's completion function is not being called. I try: gzip -<TAB> in an empty directory and get "no match for: `file'". I like the new changes a lot (assuming they work). It wasn't clear to me how completion for different redirection operators will work. It seems that you can only specify one redirection completer. Which will have to do the remaining work of figuring what completion function to use, if you want one for input and one for output. (And another for stderr, etc.) It seems like that information should be part of the compdef call. All my command specific redirection completers currently are for commands that provide output, the input comes from command line args, so it didn't matter. But I can easily see there being commands where input and output files from redirection are completely different. So the user will want to use different functions. -FR __________________________________________________ Do You Yahoo!? Yahoo! Sports - sign up for Fantasy Baseball http://sports.yahoo.com ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2002-03-04 8:52 UTC | newest] Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2002-02-25 5:59 Per command _redirect completion Felix Rosencrantz 2002-02-25 8:18 ` Sven Wischnowsky 2002-02-25 9:47 ` Oliver Kiddle 2002-02-26 6:56 ` Felix Rosencrantz 2002-02-26 8:44 ` Sven Wischnowsky 2002-02-27 9:35 ` Sven Wischnowsky 2002-02-27 13:10 ` Oliver Kiddle 2002-02-27 14:30 ` Sven Wischnowsky 2002-02-28 6:35 ` Felix Rosencrantz 2002-02-28 8:42 ` Sven Wischnowsky 2002-03-01 5:47 ` Bart Schaefer 2002-03-04 8:50 ` Sven Wischnowsky 2002-03-01 9:24 ` Oliver Kiddle 2002-03-01 10:49 ` Sven Wischnowsky 2002-03-02 16:28 Felix Rosencrantz
Code repositories for project(s) associated with this public inbox https://git.vuxu.org/mirror/zsh/ This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).