diff options
-rw-r--r-- | ChangeLog | 19 | ||||
-rw-r--r-- | Completion/Base/Completer/_complete | 8 | ||||
-rw-r--r-- | Completion/Base/Core/_dispatch | 98 | ||||
-rw-r--r-- | Completion/Base/Core/_normal | 123 | ||||
-rw-r--r-- | Completion/Base/Utility/_contexts | 23 | ||||
-rw-r--r-- | Completion/Base/Utility/_set_command | 31 | ||||
-rw-r--r-- | Completion/Unix/Command/_gcc | 24 | ||||
-rw-r--r-- | Completion/Unix/Command/_su | 2 | ||||
-rw-r--r-- | Completion/Unix/Type/_files | 2 | ||||
-rw-r--r-- | Completion/Unix/Type/_printers | 2 | ||||
-rw-r--r-- | Completion/Unix/Type/_terminals | 2 | ||||
-rw-r--r-- | Completion/Unix/Type/_time_zone | 2 | ||||
-rw-r--r-- | Completion/X/Type/_x_display | 2 | ||||
-rw-r--r-- | Completion/Zsh/Command/_compdef | 1 | ||||
-rw-r--r-- | Completion/Zsh/Context/_default | 2 | ||||
-rw-r--r-- | Completion/Zsh/Context/_in_vared | 2 | ||||
-rw-r--r-- | Completion/Zsh/Context/_redirect | 16 | ||||
-rw-r--r-- | Completion/Zsh/Context/_subscript | 2 | ||||
-rw-r--r-- | Completion/Zsh/Context/_value | 83 | ||||
-rw-r--r-- | Completion/compdump | 61 | ||||
-rw-r--r-- | Completion/compinit | 189 | ||||
-rw-r--r-- | Doc/Zsh/compsys.yo | 77 |
22 files changed, 471 insertions, 300 deletions
diff --git a/ChangeLog b/ChangeLog index e10fccc38..86ad59746 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2002-03-04 Sven Wischnowsky <wischnow@zsh.org> + + * 16755: Completion/compdump, Completion/compinit, + Completion/Base/Completer/_complete, + Completion/Base/Core/_dispatch, Completion/Base/Core/_normal, + Completion/Base/Utility/_contexts, + Completion/Base/Utility/_set_command, + Completion/Unix/Command/_gcc, Completion/Unix/Command/_su, + Completion/Unix/Type/_files, Completion/Unix/Type/_printers, + Completion/Unix/Type/_terminals, Completion/Unix/Type/_time_zone, + Completion/X/Type/_x_display, Completion/Zsh/Command/_compdef, + Completion/Zsh/Context/_default, + Completion/Zsh/Context/_in_vared, + Completion/Zsh/Context/_redirect, + Completion/Zsh/Context/_subscript, Completion/Zsh/Context/_value, + Doc/Zsh/compsys.yo: allow different sets of completion + definitions selected with option -T to compdef; use this for + parameter values and redirections + 2002-03-01 Sven Wischnowsky <wischnow@zsh.org> * 16751: Src/Zle/comp.h, Src/Zle/compcore.c, Src/Zle/complete.c, diff --git a/Completion/Base/Completer/_complete b/Completion/Base/Completer/_complete index 16e0f5e9f..23670f7c0 100644 --- a/Completion/Base/Completer/_complete +++ b/Completion/Base/Completer/_complete @@ -95,7 +95,7 @@ fi 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 @@ else 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 @@ else 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 --git a/Completion/Base/Core/_dispatch b/Completion/Base/Core/_dispatch new file mode 100644 index 000000000..124aea112 --- /dev/null +++ b/Completion/Base/Core/_dispatch @@ -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 diff --git a/Completion/Base/Core/_normal b/Completion/Base/Core/_normal index 9ddfab1cd..028687fd1 100644 --- a/Completion/Base/Core/_normal +++ b/Completion/Base/Core/_normal @@ -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 @@ if [[ CURRENT -eq 1 ]]; then [[ -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" diff --git a/Completion/Base/Utility/_contexts b/Completion/Base/Utility/_contexts deleted file mode 100644 index f0e5ba874..000000000 --- a/Completion/Base/Utility/_contexts +++ /dev/null @@ -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 diff --git a/Completion/Base/Utility/_set_command b/Completion/Base/Utility/_set_command new file mode 100644 index 000000000..daf532686 --- /dev/null +++ b/Completion/Base/Utility/_set_command @@ -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 diff --git a/Completion/Unix/Command/_gcc b/Completion/Unix/Command/_gcc index e6c81e408..f297126d1 100644 --- a/Completion/Unix/Command/_gcc +++ b/Completion/Unix/Command/_gcc @@ -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 @@ _arguments -C -M 'L:|-{fW}no-=-{fW} r:|[_-]=* r:|=*' \ -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 @@ -276,6 +289,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 return ret diff --git a/Completion/Unix/Command/_su b/Completion/Unix/Command/_su index d8ed17183..a1dd69db8 100644 --- a/Completion/Unix/Command/_su +++ b/Completion/Unix/Command/_su @@ -17,4 +17,4 @@ fi shell="${${(M@)${(@f)$(</etc/passwd)}:#$usr*}##*:}" compset -n $base -_contexts -o $shell $shell:t -default- +_dispatch comps $shell $shell:t -default- diff --git a/Completion/Unix/Type/_files b/Completion/Unix/Type/_files index fa98ce574..4a57cdbc7 100644 --- a/Completion/Unix/Type/_files +++ b/Completion/Unix/Type/_files @@ -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 --git a/Completion/Unix/Type/_printers b/Completion/Unix/Type/_printers index 03f950c9c..7229c1dc6 100644 --- a/Completion/Unix/Type/_printers +++ b/Completion/Unix/Type/_printers @@ -1,4 +1,4 @@ -#autoload +#compdef -T values PRINTER LPDEST local expl ret=1 list disp sep diff --git a/Completion/Unix/Type/_terminals b/Completion/Unix/Type/_terminals index 7dbfeeba5..039430ad5 100644 --- a/Completion/Unix/Type/_terminals +++ b/Completion/Unix/Type/_terminals @@ -1,4 +1,4 @@ -#compdef infocmp +#compdef infocmp -T values TERM local desc expl diff --git a/Completion/Unix/Type/_time_zone b/Completion/Unix/Type/_time_zone index 1ae921b61..215d8bd4a 100644 --- a/Completion/Unix/Type/_time_zone +++ b/Completion/Unix/Type/_time_zone @@ -1,4 +1,4 @@ -#compdef +#compdef -T values TZ local expl diff --git a/Completion/X/Type/_x_display b/Completion/X/Type/_x_display index f547a64fa..647ff1f5a 100644 --- a/Completion/X/Type/_x_display +++ b/Completion/X/Type/_x_display @@ -1,3 +1,3 @@ -#autoload +#compdef -T values DISPLAY _tags displays && _hosts -S ':0 ' -r : diff --git a/Completion/Zsh/Command/_compdef b/Completion/Zsh/Command/_compdef index eb1a2ebb6..db4309642 100644 --- a/Completion/Zsh/Command/_compdef +++ b/Completion/Zsh/Command/_compdef @@ -6,6 +6,7 @@ typeset -A opt_args _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 \ diff --git a/Completion/Zsh/Context/_default b/Completion/Zsh/Context/_default index 8176f392c..81744cdef 100644 --- a/Completion/Zsh/Context/_default +++ b/Completion/Zsh/Context/_default @@ -19,7 +19,7 @@ _files "$@" && return 0 # 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 --git a/Completion/Zsh/Context/_in_vared b/Completion/Zsh/Context/_in_vared index abd24dd95..03f6d404e 100644 --- a/Completion/Zsh/Context/_in_vared +++ b/Completion/Zsh/Context/_in_vared @@ -32,4 +32,4 @@ fi compstate[insert]="${compstate[insert]//tab /}" -_contexts "$also" +_dispatch comps "$also" diff --git a/Completion/Zsh/Context/_redirect b/Completion/Zsh/Context/_redirect index 6e02636da..5e454014b 100644 --- a/Completion/Zsh/Context/_redirect +++ b/Completion/Zsh/Context/_redirect @@ -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[@]" diff --git a/Completion/Zsh/Context/_subscript b/Completion/Zsh/Context/_subscript index 9ea628fdb..0f1138e1a 100644 --- a/Completion/Zsh/Context/_subscript +++ b/Completion/Zsh/Context/_subscript @@ -113,5 +113,5 @@ elif [[ ${(Pt)${compstate[parameter]}} = array* ]]; then return 1 else - _contexts -math- + _dispatch comps -math- fi diff --git a/Completion/Zsh/Context/_value b/Completion/Zsh/Context/_value index 6ee8f4235..9d0acaa0e 100644 --- a/Completion/Zsh/Context/_value +++ b/Completion/Zsh/Context/_value @@ -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. +# 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 (( $+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 [[ "$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 @@ _value () { _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 --git a/Completion/compdump b/Completion/compdump index 62840b9fe..194fcf07b 100644 --- a/Completion/compdump +++ b/Completion/compdump @@ -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 @@ fi 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 @@ -129,6 +139,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.$$} unfunction compdump diff --git a/Completion/compinit b/Completion/compinit index bd879b11c..94f5f7091 100644 --- a/Completion/compinit +++ b/Completion/compinit @@ -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 @@ while [[ $# -gt 0 && $1 = -[dDiuC] ]]; do 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 @@ comppostfuncs=() # 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 @@ comppostfuncs=() # 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 @@ comppostfuncs=() # 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 @@ compdef() { 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 @@ compdef() { # 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 @@ compdef() { 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 @@ compdef() { fi shift 3 done - ;; + ;; key) if [[ $# -lt 2 ]]; then echo "$0: missing keys" @@ -348,40 +403,66 @@ compdef() { 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 --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo index d6b464002..1fb337329 100644 --- a/Doc/Zsh/compsys.yo +++ b/Doc/Zsh/compsys.yo @@ -173,14 +173,32 @@ makes the completion system call the function when completing 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 @@ also be called directly by the user. 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 @@ arguments to the command tt(foo), one would use: 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 @@ All arguments after the requested field name are passed to 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 @@ matches. Almost all calls to tt(compadd) within the completion system use 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 @@ return ret ) ) 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 @@ If the command name matches a pattern, the parameter tt(_compskip) is 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))( |