From 8ceb54fbc2f879e0e80f58c18761bd54db07e5f7 Mon Sep 17 00:00:00 2001 From: Tanaka Akira Date: Thu, 15 Apr 1999 18:25:40 +0000 Subject: zsh-3.1.5-pws-15 --- Completion/Base/_brace_parameter | 2 +- Completion/Base/_command_names | 2 +- Completion/Base/_condition | 2 +- Completion/Base/_default | 2 +- Completion/Base/_equal | 2 +- Completion/Base/_long_options | 86 +++-- Completion/Base/_math | 4 +- Completion/Base/_parameter | 2 +- Completion/Base/_precommand | 2 +- Completion/Base/_redirect | 2 +- Completion/Base/_subscript | 2 +- Completion/Base/_tilde | 2 +- Completion/Base/_vars | 2 +- Completion/Builtins/_aliases | 2 +- Completion/Builtins/_arrays | 2 +- Completion/Builtins/_autoload | 2 +- Completion/Builtins/_bg_jobs | 2 +- Completion/Builtins/_bindkey | 2 +- Completion/Builtins/_builtin | 2 +- Completion/Builtins/_cd | 4 +- Completion/Builtins/_command | 2 +- Completion/Builtins/_dirs | 2 +- Completion/Builtins/_disable | 2 +- Completion/Builtins/_echotc | 2 +- Completion/Builtins/_enable | 2 +- Completion/Builtins/_fc | 2 +- Completion/Builtins/_functions | 2 +- Completion/Builtins/_hash | 2 +- Completion/Builtins/_jobs | 2 +- Completion/Builtins/_kill | 2 +- Completion/Builtins/_limits | 2 +- Completion/Builtins/_sched | 2 +- Completion/Builtins/_set | 2 +- Completion/Builtins/_setopt | 2 +- Completion/Builtins/_source | 2 +- Completion/Builtins/_trap | 2 +- Completion/Builtins/_unhash | 2 +- Completion/Builtins/_unsetopt | 2 +- Completion/Builtins/_vars_eq | 2 +- Completion/Builtins/_wait | 2 +- Completion/Builtins/_which | 2 +- Completion/Builtins/_zftp | 4 +- Completion/Builtins/_zle | 2 +- Completion/Builtins/_zmodload | 2 +- Completion/Commands/_correct_filename | 2 +- Completion/Commands/_correct_word | 12 + Completion/Commands/_most_recent_file | 2 +- Completion/Core/_compalso | 12 +- Completion/Core/_multi_parts | 287 ++++++-------- Completion/Core/_path_files | 443 +++++++++------------- Completion/Core/_sep_parts | 78 ++-- Completion/Core/compinit | 72 ++-- Completion/README | 359 +----------------- Completion/User/_a2ps | 2 +- Completion/User/_compress | 2 +- Completion/User/_configure | 9 +- Completion/User/_dd | 2 +- Completion/User/_dvi | 2 +- Completion/User/_find | 2 +- Completion/User/_gunzip | 2 +- Completion/User/_gzip | 2 +- Completion/User/_hosts | 2 +- Completion/User/_make | 4 +- Completion/User/_man | 2 +- Completion/User/_mh | 2 +- Completion/User/_pdf | 2 +- Completion/User/_ps | 2 +- Completion/User/_rcs | 2 +- Completion/User/_rlogin | 2 +- Completion/User/_strip | 2 +- Completion/User/_stty | 2 +- Completion/User/_tar | 2 +- Completion/User/_tex | 2 +- Completion/User/_uncompress | 2 +- Completion/User/_x_options | 2 +- Completion/User/_xfig | 2 +- Config/version.mk | 4 +- Doc/Makefile.in | 6 +- Doc/Zsh/compctl.yo | 3 +- Doc/Zsh/compsys.yo | 691 ++++++++++++++++++++++++++++++++++ Doc/Zsh/compwid.yo | 94 ++++- Doc/Zsh/guide.yo | 1 + Doc/Zsh/intro.yo | 1 + Doc/Zsh/modules.yo | 2 +- Doc/Zsh/seealso.yo | 1 + Doc/Zsh/zle.yo | 6 + Doc/zsh.yo | 2 + Doc/zshcompsys.yo | 3 + Misc/compctl-examples | 20 +- Src/Zle/comp.h | 12 +- Src/Zle/comp1.c | 18 +- Src/Zle/comp1.export | 5 + Src/Zle/compctl.c | 30 +- Src/Zle/zle_main.c | 3 +- Src/Zle/zle_params.c | 12 + Src/Zle/zle_refresh.c | 29 +- Src/Zle/zle_tricky.c | 441 +++++++++++++++++----- Src/glob.c | 51 ++- Src/subst.c | 24 +- Src/utils.c | 5 +- patchlist.txt | 72 ++++ 101 files changed, 1909 insertions(+), 1127 deletions(-) create mode 100644 Completion/Commands/_correct_word create mode 100644 Doc/Zsh/compsys.yo create mode 100644 Doc/zshcompsys.yo diff --git a/Completion/Base/_brace_parameter b/Completion/Base/_brace_parameter index 3d663a777..d45e317be 100644 --- a/Completion/Base/_brace_parameter +++ b/Completion/Base/_brace_parameter @@ -1,4 +1,4 @@ -#defcomp -brace-parameter- +#compdef -brace-parameter- if [[ "$SUFFIX" = *\}* ]]; then ISUFFIX="${SUFFIX#*\}}$ISUFFIX" diff --git a/Completion/Base/_command_names b/Completion/Base/_command_names index f21af674c..8f75f1a77 100644 --- a/Completion/Base/_command_names +++ b/Completion/Base/_command_names @@ -1,4 +1,4 @@ -#defcomp -command- +#compdef -command- local nm=$compstate[nmatches] ret=1 diff --git a/Completion/Base/_condition b/Completion/Base/_condition index df1bf913e..c617d9d90 100644 --- a/Completion/Base/_condition +++ b/Completion/Base/_condition @@ -1,4 +1,4 @@ -#defcomp -condition- +#compdef -condition- local prev="$words[CURRENT-1]" diff --git a/Completion/Base/_default b/Completion/Base/_default index 9ea1a09db..b49ca7115 100644 --- a/Completion/Base/_default +++ b/Completion/Base/_default @@ -1,4 +1,4 @@ -#defcomp -default- +#compdef -default- # We first try the `compctl's. This is without first (-T) and default (-D) # completion. If you want them add `-T' and/or `-D' to this command. diff --git a/Completion/Base/_equal b/Completion/Base/_equal index f407014fe..0e2a11e46 100644 --- a/Completion/Base/_equal +++ b/Completion/Base/_equal @@ -1,3 +1,3 @@ -#defcomp -equal- +#compdef -equal- compgen -am diff --git a/Completion/Base/_long_options b/Completion/Base/_long_options index 97b11f2dc..6288fc3a0 100644 --- a/Completion/Base/_long_options +++ b/Completion/Base/_long_options @@ -32,12 +32,25 @@ # for option descriptions containing `=FILE' and paths for option # descriptions that contain `=DIR' or `=PATH'. These builtin patterns # can be overridden by patterns given as arguments, though. +# +# This function accepts following options: +# +# -t do completion only on words starting with two hyphens +# +# -i list of patterns. Options, matching these patterns, are ignored. +# The list may be given as array name or as literal list in braces. +# E.g. _long_options -i '(--(enable|disable)-FEATURE*)' will ignore +# --enable-FEATURE, that is listed in configure help output +# +# -s list of pattern/replacement pairs. The argument is the same as above. +# E.g. configure often lists only --enable but accepts both +# --enable and --disable options. +# _long_options -s '(#--enable- --disable)' will accept both forms. # # This function also accepts the `-X', `-J', and `-V' options which -# are given to `compadd'. Finally, it accepts the option `-t'. If this -# is given, completion is only done on words starting with two hyphens. +# are given to `compadd'. -local opt expl group test i name action ret=1 tmp suffix +local opt expl group test i name action ret=1 tmp suffix iopts sopts setopt extendedglob @@ -46,11 +59,23 @@ setopt extendedglob group=() expl=() if [[ $1 = -*~--* ]]; then - while getopts "J:V:X:t" opt; do + while getopts "J:V:X:ti:s:" opt; do case "$opt" in [JV]) group=("-$opt" "$OPTARG");; X) expl=(-X "$OPTARG");; t) test=yes;; + i) if [[ "$OPTARG[1]" = '(' ]]; then + iopts=( ${=OPTARG[2,-2]} ) + else + iopts=( ${(P)${OPTARG}} ) + fi + ;; + s) if [[ "$OPTARG[1]" = '(' ]]; then + sopts=( ${=OPTARG[2,-2]} ) + else + sopts=( ${(P)${OPTARG}} ) + fi + ;; esac done shift OPTIND-1 @@ -77,6 +102,7 @@ if [[ "$tmp" != $_lo_cache_cmd ]]; then (( $+_lo_cache_actions )) && unset "$_lo_cache_names[@]" _lo_cache_actions _lo_cache_names local opts pattern anum=1 tmpo str + typeset -U opts # Now get the long option names by calling the command with `--help'. # The parameter expansion trickery first gets the lines as separate @@ -87,11 +113,24 @@ if [[ "$tmp" != $_lo_cache_cmd ]]; then # the old array elements with newlines between them. Then we select # those elements that start with two hyphens, remove anything up to # those hyphens and anything from the space or comma after the - # option up to the end. Finally all elements with option strings - # that contain uppercase letters are removed. + # option up to the end. + + opts=("--${(@)^${(@)${(@M)${(@ps:\n:j:\n:)${(@)${(@M)${(@f)$("$words[1]" --help)}:#[ ]#-*}//,/ +}}:#[ ]#--*}#*--}%%[, ]*}") - opts=("--${(@)^${(@)${(@)${(@M)${(@ps:\n:j:\n:)${(@)${(@M)${(@f)$("$words[1]" --help)}:#[ ]#-*}//,/ -}}:#[ ]#--*}#*--}%%[, ]*}:#(*-[A-Z]*|)}") + # Now remove all ignored options ... + + while (($#iopts)) ; do + opts=( ${opts:#$~iopts[1]} ) + shift iopts + done + + # ... and add "same" options + + while (($#sopts)) ; do + opts=( $opts ${opts/$sopts[1]/$sopts[2]} ) + shift 2 sopts + done # The interpretation of the options is completely table driven. We # use the positional parameters we were given and a few standard @@ -173,7 +212,7 @@ if [[ "$tmp" != $_lo_cache_cmd ]]; then # Now filter out any option strings we don't like and stuff them # in an array, if there are still some. - tmp=("${(@)${(@)tmp%%\=*}//[^a-z0-9-]}") + tmp=("${(@)${(@)tmp%%\=*}//[^a-zA-Z0-9-]}") if (( $#tmp )); then _lo_cache_names[anum]="$name" _lo_cache_actions[anum]="$action" @@ -200,20 +239,6 @@ if [[ "$str" = *\=* ]]; then osuf="$SUFFIX" pre="${str%%\=*}" - IPREFIX="${IPREFIX}${pre}=" - PREFIX="${str#*\=}" - SUFFIX="" - - # We will check if the arrays contain an option matching what's on - # the line. To do this good, we build a pattern. - - [[ -n "$_comp_correct" && $#pre -le _comp_correct ]] && return 1 - - pat="${pre}*" - patflags='' - _match_pattern _long_options pat patflags - - [[ -n "$_comp_correct" ]] && patflags="$patflags(#a$_comp_correct)" # Then we walk through the array names. For each array we test if it # contains the option string. If so, we `invoke' the action stored @@ -223,6 +248,9 @@ if [[ "$str" = *\=* ]]; then for name in "$_lo_cache_names[@]"; do action="$_lo_cache_actions[anum]" if (( ${(@)${(@P)name}[(I)$pre]} )); then + IPREFIX="${oipre}${pre}=" + PREFIX="${str#*\=}" + SUFFIX="" if [[ "$action[1]" = (\[|\() ]]; then compadd - ${=action[2,-2]} elif (( $#action )); then @@ -240,7 +268,10 @@ if [[ "$str" = *\=* ]]; then # element from `_lo_actions' in `parta'. If we find more than one # such option or if we already had one, we set `parto' to `-'. - tmp=("${(@M)${(@P)name}:#${~pat}}") + PREFIX="${str%%\=*}" + SUFFIX="" + compadd -O tmp -M 'r:|-=* r:|=*' - "${(@P)name}" + if [[ $#tmp -eq 1 ]]; then if [[ -z "$parto" ]]; then parto="$tmp[1]" @@ -258,8 +289,9 @@ if [[ "$str" = *\=* ]]; then # try to complete the string after the `='. if [[ -n "$parto" && "$parto" != - ]]; then - IPREFIX="${parto}=" - + IPREFIX="${oipre}${parto}=" + PREFIX="${str#*\=}" + SUFFIX="" if (( $#parta )); then if [[ "$parta[1]" = (\[|\() ]]; then compadd - ${=parta[2,-2]} @@ -281,7 +313,7 @@ fi # The string on the line did not contain a `=', or we couldn't # complete the option string since there were more than one matching -# what's on the line. So we just ad the option string as possible +# what's on the line. So we just add the option strings as possible # matches, giving the string from the `=' on as a suffix. if [[ "$str" = *\=* ]]; then diff --git a/Completion/Base/_math b/Completion/Base/_math index f7f4c360f..90a2c5f7b 100644 --- a/Completion/Base/_math +++ b/Completion/Base/_math @@ -1,4 +1,4 @@ -#defcomp -math- +#compdef -math- if [[ "$PREFIX" = *[^a-zA-Z0-9_]* ]]; then IPREFIX="$IPREFIX${PREFIX%%[a-zA-Z0-9_]#}" @@ -10,7 +10,7 @@ if [[ "$SUFFIX" = *[^a-zA-Z0-9_]* ]]; then fi compgen -v -#defcomp -math- +#compdef -math- IPREFIX="$IPREFIX${PREFIX%[a-zA-Z0-9_]*}" PREFIX="${PREFIX##*[^a-zA-Z0-9_]}" diff --git a/Completion/Base/_parameter b/Completion/Base/_parameter index 2bd66ec93..7200ae440 100644 --- a/Completion/Base/_parameter +++ b/Completion/Base/_parameter @@ -1,3 +1,3 @@ -#defcomp -parameter- +#compdef -parameter- compgen -v diff --git a/Completion/Base/_precommand b/Completion/Base/_precommand index c13cd7465..bcda9fc8b 100644 --- a/Completion/Base/_precommand +++ b/Completion/Base/_precommand @@ -1,4 +1,4 @@ -#defcomp - nohup nice eval time rusage noglob nocorrect exec +#compdef - nohup nice eval time rusage noglob nocorrect exec shift words (( CURRENT-- )) diff --git a/Completion/Base/_redirect b/Completion/Base/_redirect index 32113ad7c..6e02636da 100644 --- a/Completion/Base/_redirect +++ b/Completion/Base/_redirect @@ -1,3 +1,3 @@ -#defcomp -redirect- +#compdef -redirect- _files diff --git a/Completion/Base/_subscript b/Completion/Base/_subscript index e783d04e7..abaabec8c 100644 --- a/Completion/Base/_subscript +++ b/Completion/Base/_subscript @@ -1,4 +1,4 @@ -#defcomp -subscript- +#compdef -subscript- if [[ ${(Pt)${compstate[parameter]}} = assoc* ]]; then compgen -S ']' -k "( ${(kP)${compstate[parameter]}} )" diff --git a/Completion/Base/_tilde b/Completion/Base/_tilde index c5ebb66d5..c24c65701 100644 --- a/Completion/Base/_tilde +++ b/Completion/Base/_tilde @@ -1,4 +1,4 @@ -#defcomp -tilde- +#compdef -tilde- # We use all named directories and user names here. If this is too slow # for you or if there are too many of them, you may want to use diff --git a/Completion/Base/_vars b/Completion/Base/_vars index 497a9316f..f06562694 100644 --- a/Completion/Base/_vars +++ b/Completion/Base/_vars @@ -1,3 +1,3 @@ -#defcomp getopts read unset vared +#compdef getopts read unset vared compgen -v diff --git a/Completion/Builtins/_aliases b/Completion/Builtins/_aliases index 2ccf18439..94c8a0f7c 100644 --- a/Completion/Builtins/_aliases +++ b/Completion/Builtins/_aliases @@ -1,3 +1,3 @@ -#defcomp unalias +#compdef unalias compgen -a diff --git a/Completion/Builtins/_arrays b/Completion/Builtins/_arrays index 94401f28a..b79bf711c 100644 --- a/Completion/Builtins/_arrays +++ b/Completion/Builtins/_arrays @@ -1,3 +1,3 @@ -#defcomp shift +#compdef shift compgen -A diff --git a/Completion/Builtins/_autoload b/Completion/Builtins/_autoload index d1462e09a..d1c255b73 100644 --- a/Completion/Builtins/_autoload +++ b/Completion/Builtins/_autoload @@ -1,3 +1,3 @@ -#defcomp autoload +#compdef autoload compgen -s '${^fpath}/*(N:t)' diff --git a/Completion/Builtins/_bg_jobs b/Completion/Builtins/_bg_jobs index 4abee070c..ef1cd4d3c 100644 --- a/Completion/Builtins/_bg_jobs +++ b/Completion/Builtins/_bg_jobs @@ -1,3 +1,3 @@ -#defcomp bg +#compdef bg compgen -z -P '%' diff --git a/Completion/Builtins/_bindkey b/Completion/Builtins/_bindkey index 6fca200ba..57b3d8a85 100644 --- a/Completion/Builtins/_bindkey +++ b/Completion/Builtins/_bindkey @@ -1,4 +1,4 @@ -#defcomp bindkey +#compdef bindkey # Normally, this completes names of zle widgets, whether the builtin ones # or ones defined by the user. Note that a - allows a wildcard before it, diff --git a/Completion/Builtins/_builtin b/Completion/Builtins/_builtin index bee67fe8f..0e6d613be 100644 --- a/Completion/Builtins/_builtin +++ b/Completion/Builtins/_builtin @@ -1,4 +1,4 @@ -#defcomp builtin +#compdef builtin if (( $CURRENT > 2 )); then shift words diff --git a/Completion/Builtins/_cd b/Completion/Builtins/_cd index a4fd56327..61abd2068 100644 --- a/Completion/Builtins/_cd +++ b/Completion/Builtins/_cd @@ -1,4 +1,4 @@ -#defcomp cd pushd +#compdef cd pushd # Handling of cd. # - Normally just completes directories. Uses cdpath if that's set @@ -55,7 +55,7 @@ elif [[ $words[1] = pu* && $PREFIX = [-+]* ]]; then list=(${list%%[ ]*}) compgen -y '$lines' -Q -k list && ret=0 [[ -z $compstate[list] ]] && compstate[list]=list && ret=0 - [[ -n $compstate[insert] ]] && compstat[insert]=menu && ret=0 + [[ -n $compstate[insert] ]] && compstate[insert]=menu && ret=0 return ret elif [[ $PREFIX != (\~|/|./|../)* && $#cdpath -ne 0 ]]; then diff --git a/Completion/Builtins/_command b/Completion/Builtins/_command index 4facceb12..6103ee81f 100644 --- a/Completion/Builtins/_command +++ b/Completion/Builtins/_command @@ -1,4 +1,4 @@ -#defcomp command +#compdef command if [[ CURRENT -ge 3 ]]; then compset -n 2 diff --git a/Completion/Builtins/_dirs b/Completion/Builtins/_dirs index bc426e322..04c4b75d9 100644 --- a/Completion/Builtins/_dirs +++ b/Completion/Builtins/_dirs @@ -1,3 +1,3 @@ -#defcomp rmdir df du dircmp +#compdef rmdir df du dircmp _files -/ diff --git a/Completion/Builtins/_disable b/Completion/Builtins/_disable index 27db5c18f..5572fbcf3 100644 --- a/Completion/Builtins/_disable +++ b/Completion/Builtins/_disable @@ -1,4 +1,4 @@ -#defcomp disable +#compdef disable local prev="$words[CURRENT-1]" ret=1 diff --git a/Completion/Builtins/_echotc b/Completion/Builtins/_echotc index 135cabada..ce282437d 100644 --- a/Completion/Builtins/_echotc +++ b/Completion/Builtins/_echotc @@ -1,3 +1,3 @@ -#defcomp echotc +#compdef echotc compgen -k '(al dc dl do le up al bl cd ce cl cr dc dl do ho is le ma nd nl se so up)' diff --git a/Completion/Builtins/_enable b/Completion/Builtins/_enable index 1baa09ed6..483661efe 100644 --- a/Completion/Builtins/_enable +++ b/Completion/Builtins/_enable @@ -1,4 +1,4 @@ -#defcomp enable +#compdef enable local prev="$words[CURRENT-1]" ret=1 diff --git a/Completion/Builtins/_fc b/Completion/Builtins/_fc index f8cf4dde8..5b493dc3b 100644 --- a/Completion/Builtins/_fc +++ b/Completion/Builtins/_fc @@ -1,4 +1,4 @@ -#defcomp fc +#compdef fc local prev="$words[CURRENT-1]" diff --git a/Completion/Builtins/_functions b/Completion/Builtins/_functions index 7e3174af5..052dfca00 100644 --- a/Completion/Builtins/_functions +++ b/Completion/Builtins/_functions @@ -1,3 +1,3 @@ -#defcomp unfunction +#compdef unfunction compgen -F diff --git a/Completion/Builtins/_hash b/Completion/Builtins/_hash index 4d4ba4244..b03cf7fb9 100644 --- a/Completion/Builtins/_hash +++ b/Completion/Builtins/_hash @@ -1,4 +1,4 @@ -#defcomp hash +#compdef hash if [[ "$words[2]" = -*d* ]]; then if compset -P 1 '*\='; then diff --git a/Completion/Builtins/_jobs b/Completion/Builtins/_jobs index 8f6991de0..bce005b4e 100644 --- a/Completion/Builtins/_jobs +++ b/Completion/Builtins/_jobs @@ -1,3 +1,3 @@ -#defcomp fg jobs +#compdef fg jobs compgen -j -P '%' diff --git a/Completion/Builtins/_kill b/Completion/Builtins/_kill index 0b0f5c188..979c87804 100644 --- a/Completion/Builtins/_kill +++ b/Completion/Builtins/_kill @@ -1,4 +1,4 @@ -#defcomp kill +#compdef kill local list diff --git a/Completion/Builtins/_limits b/Completion/Builtins/_limits index 8b0b41c71..be5c35593 100644 --- a/Completion/Builtins/_limits +++ b/Completion/Builtins/_limits @@ -1,3 +1,3 @@ -#defcomp limit unlimit +#compdef limit unlimit compgen -k "(${(j: :)${(f)$(limit)}%% *})" diff --git a/Completion/Builtins/_sched b/Completion/Builtins/_sched index 5fba71eac..581438b0e 100644 --- a/Completion/Builtins/_sched +++ b/Completion/Builtins/_sched @@ -1,3 +1,3 @@ -#defcomp sched +#compdef sched compset -n 3 && _normal diff --git a/Completion/Builtins/_set b/Completion/Builtins/_set index 959dac75d..59a38b654 100644 --- a/Completion/Builtins/_set +++ b/Completion/Builtins/_set @@ -1,4 +1,4 @@ -#defcomp set +#compdef set local prev="$words[CURRENT-1]" diff --git a/Completion/Builtins/_setopt b/Completion/Builtins/_setopt index e5a6c054f..17ecafb20 100644 --- a/Completion/Builtins/_setopt +++ b/Completion/Builtins/_setopt @@ -1,4 +1,4 @@ -#defcomp setopt +#compdef setopt # If you first want to complete only unset options, un-comment the lines # setting the _unset_options array and then use: diff --git a/Completion/Builtins/_source b/Completion/Builtins/_source index efac4f32b..a232aa458 100644 --- a/Completion/Builtins/_source +++ b/Completion/Builtins/_source @@ -1,4 +1,4 @@ -#defcomp source +#compdef source if [[ CURRENT -ge 3 ]]; then compset -n 2 diff --git a/Completion/Builtins/_trap b/Completion/Builtins/_trap index 36ab1f1a8..bb0630638 100644 --- a/Completion/Builtins/_trap +++ b/Completion/Builtins/_trap @@ -1,4 +1,4 @@ -#defcomp trap +#compdef trap if [[ CURRENT -eq 2 ]]; then compgen -c diff --git a/Completion/Builtins/_unhash b/Completion/Builtins/_unhash index a9050cb49..825c130b2 100644 --- a/Completion/Builtins/_unhash +++ b/Completion/Builtins/_unhash @@ -1,4 +1,4 @@ -#defcomp unhash +#compdef unhash local fl="$words[2]" ret=1 diff --git a/Completion/Builtins/_unsetopt b/Completion/Builtins/_unsetopt index cdc2ab9f3..d862aa0e1 100644 --- a/Completion/Builtins/_unsetopt +++ b/Completion/Builtins/_unsetopt @@ -1,4 +1,4 @@ -#defcomp unsetopt +#compdef unsetopt # If you first want to complete only unset options, uncomment the lines # setting the _set_options array and then use: diff --git a/Completion/Builtins/_vars_eq b/Completion/Builtins/_vars_eq index 9488cb7f9..892c1f57e 100644 --- a/Completion/Builtins/_vars_eq +++ b/Completion/Builtins/_vars_eq @@ -1,3 +1,3 @@ -#defcomp declare export integer local readonly typeset +#compdef declare export integer local readonly typeset compgen -v -q -S '=' diff --git a/Completion/Builtins/_wait b/Completion/Builtins/_wait index 9281a5cc2..0fadc087b 100644 --- a/Completion/Builtins/_wait +++ b/Completion/Builtins/_wait @@ -1,4 +1,4 @@ -#defcomp wait +#compdef wait local list ret=1 diff --git a/Completion/Builtins/_which b/Completion/Builtins/_which index 9248f9c9f..db5271653 100644 --- a/Completion/Builtins/_which +++ b/Completion/Builtins/_which @@ -1,3 +1,3 @@ -#defcomp which whence where type +#compdef which whence where type compgen -caF diff --git a/Completion/Builtins/_zftp b/Completion/Builtins/_zftp index 178d9d9e3..71404fb2b 100644 --- a/Completion/Builtins/_zftp +++ b/Completion/Builtins/_zftp @@ -1,4 +1,4 @@ -#defpatcomp zf* +#compdef -p zf* # Don't try any more completion after this. _compskip=1 @@ -10,7 +10,7 @@ _compskip=1 local subcom if [[ $words[1] = zftp ]]; then - if [[ $CURRENT -eq 1 ]]; then + if [[ $CURRENT -eq 2 ]]; then compadd open params user login type ascii binary mode put \ putat get getat append appendat ls dir local remote mkdir rmdir return diff --git a/Completion/Builtins/_zle b/Completion/Builtins/_zle index 0a9ad0a9e..f0860c5e3 100644 --- a/Completion/Builtins/_zle +++ b/Completion/Builtins/_zle @@ -1,4 +1,4 @@ -#defcomp zle +#compdef zle if [[ "$words[2]" = -N && CURRENT -eq 3 ]]; then compgen -F diff --git a/Completion/Builtins/_zmodload b/Completion/Builtins/_zmodload index 9247ba0ce..4b0e91442 100644 --- a/Completion/Builtins/_zmodload +++ b/Completion/Builtins/_zmodload @@ -1,4 +1,4 @@ -#defcomp zmodload +#compdef zmodload local fl="$words[2]" diff --git a/Completion/Commands/_correct_filename b/Completion/Commands/_correct_filename index 72bac5f1b..53ed6d113 100644 --- a/Completion/Commands/_correct_filename +++ b/Completion/Commands/_correct_filename @@ -1,4 +1,4 @@ -#defkeycomp complete-word \C-xc +#compdef -k complete-word \C-xc # Function to correct a filename. Can be used as a completion widget, # or as a function in its own right, in which case it will print the diff --git a/Completion/Commands/_correct_word b/Completion/Commands/_correct_word new file mode 100644 index 000000000..db3023860 --- /dev/null +++ b/Completion/Commands/_correct_word @@ -0,0 +1,12 @@ +#compdef -k complete-word \C-xc + +# Simple completion front-end implementing spelling correction. +# The maximum number of errors is set quite high, and +# the numeric prefix can be used to specify a different value. + +local oca="$compconfig[correct_accept]" +compconfig[correct_accept]=6n + +_main_complete _correct + +compconfig[correct_accept]=$oca diff --git a/Completion/Commands/_most_recent_file b/Completion/Commands/_most_recent_file index 5bd737fd2..c571483ca 100644 --- a/Completion/Commands/_most_recent_file +++ b/Completion/Commands/_most_recent_file @@ -1,4 +1,4 @@ -#defkeycomp complete-word \C-xm +#compdef -k complete-word \C-xm # Complete the most recent file matching the pattern on the line so # far: globbing is active, i.e. *.txt will be expanded to the most recent diff --git a/Completion/Core/_compalso b/Completion/Core/_compalso index 52fb08f05..61649901e 100644 --- a/Completion/Core/_compalso +++ b/Completion/Core/_compalso @@ -1,15 +1,17 @@ #autoload -# This searches $1 in the array for normal completions and calls the result. +# 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 # `_compalso -math-' to get the completions that would be generated for a # mathematical context. -local tmp ret=1 +local i tmp -tmp="$_comps[$1]" -[[ -z "$tmp" ]] || "$tmp" && ret=0 +for i; do + tmp="$_comps[$1]" + [[ -z "$tmp" ]] || "$tmp" && return 0 +done -return ret +return 1 diff --git a/Completion/Core/_multi_parts b/Completion/Core/_multi_parts index ab9438494..b49c41e22 100644 --- a/Completion/Core/_multi_parts +++ b/Completion/Core/_multi_parts @@ -7,15 +7,8 @@ # The parts of words from the array that are separated by the # separator character are then completed independently. -local sep matches patstr orig matchflags pref i tmp1 tmp2 nm -local group expl menu origflags mflags - -_match_test _multi_parts || return 1 - -# Save the current number of matches to be able to return if we added -# matches or not. - -nm=$compstate[nmatches] +local sep matches pref npref i tmp1 group expl menu pre suf +typeset -U tmp2 # Get the options. @@ -41,193 +34,159 @@ else matches=( "${(@P)2}" ) fi -# Now build the pattern from what we have on the line. We also save -# the original string in `orig'. +# In `pre' and `suf' we will hold the prefix and the suffix from the +# line while we walk through them. The original string are used +# temporarily for matching. -if [[ $#compstate[pattern_match] -ne 0 ]]; then - if [[ "${compstate[pattern_match]-*}" = \** ]]; then - str="${PREFIX}*${SUFFIX}*" - else - str="${PREFIX}${SUFFIX}" - fi -else - patstr="${PREFIX:q}*${SUFFIX:q}*" -fi -orig="${PREFIX}${SUFFIX}" +pre="$PREFIX" +suf="$SUFFIX" +orig="$PREFIX$SUFFIX" -[[ $compstate[insert] = *menu || -n "$_comp_correct" || +# Special handling for menucompletion? + +[[ $compstate[insert] = (*menu|[0-9]*) || -n "$_comp_correct" || ( $#compstate[pattern_match] -ne 0 && "$orig" != "${orig:q}" ) ]] && menu=yes -matchflags="" -_match_pattern _path_files patstr matchflags -origflags="$matchflags" -[[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)" - -patstr="${${patstr//$sep/*$sep}//\*##/*}" - -# First we will skip over those parts of the matches for which we have -# exact substrings on the line. In `pref' we will build the -# unambiguous prefix string. +# In `pref' we collect the unambiguous prefix path. pref='' -while [[ "$orig" = *${sep}* ]] do - # First build the pattern to use, then collect all strings from - # `matches' that match the prefix we have and the exact substring in - # the array `tmp1'. +# If the string from the line matches at least one of the strings, +# we use only the matching strings. - if [[ -n "$_comp_correct" && "${#orig%%${sep}*}" -le _comp_correct ]]; then - mflags="$origflags" - else - mflags="$matchflags" - fi - - pat="${${${patstr#*${sep}}%${sep}*}//\*/[^${sep}]#}" - tmp1=( "${(@M)matches:#${~mflags}${orig%%${sep}*}${sep}${~pat}}" ) +compadd -O tmp1 -M "r:|${sep}=* r:|=*" - "$matches[@]" - # If there are no words matching the exact substring, stop. +(( $#tmp1 )) && matches=( "$tmp1[@]" ) - (( $#tmp1 )) || break +while true; do - # Otherwise add the part to the prefix, remove it from the matches - # (and also remove all words not matching the string at all), and - # set `patstr' and `orig' to the next component. + # Get the prefix and suffix for matching. - tmp1="${orig%%${sep}*}${sep}" - pref="$pref$tmp1" - matches=("${(@)${(@)${(@M)matches:#${tmp1}*}#$tmp1}:#}") - orig="${orig#*${sep}}" - patstr="${patstr#*${sep}}" -done - -# Now we get all the words that still match in `tmp1'. - -if [[ "$patstr" = *${sep}* ]]; then - tmp1="${patstr%${sep}*}${sep}" - pat="${tmp1//\*/[^${sep}]#}${patstr##*${sep}}" -else - pat="$patstr" -fi -if [[ -n "$_comp_correct" && "${#orig%%${sep}*}" -le _comp_correct ]]; then - mflags="$origflags" -else - mflags="$matchflags" -fi -tmp1=( "${(@M)matches:#${~mflags}${~pat}}" ) - -if (( $#tmp1 )); then - - # There are words that are matched, put them into `matches' and then - # move all unambiguous components from the beginning into `pref'. + if [[ "$pre" = *${sep}* ]]; then + PREFIX="${pre%%${sep}*}" + SUFFIX="" + else + PREFIX="${pre}" + SUFFIX="${suf%%${sep}*}" + fi - matches=( "$tmp1[@]" ) - while [[ "$matches[1]" = *${sep}* ]]; do + # Check if the component for some of the possible matches is equal + # to the string from the line. If there are such strings, we directly + # use the stuff from the line. This avoids having `foo' complete to + # both `foo' and `foobar'. - # We just take the first component of the first match and see if - # there are other matches with a different prefix (these are - # collected in `tmp2'). If there are any, we give up. + tmp1=( "${(@M)matches:#${PREFIX}${SUFFIX}${sep}*}" ) - tmp1="${matches[1]%%${sep}*}${sep}" - tmp2=( "${(@)matches:#${tmp1}*}" ) - (( $#tmp2 )) && break + if (( $#tmp1 )); then + npref="${PREFIX}${SUFFIX}${sep}" + else + # No exact match, see how many strings match what's on the line. - # All matches have the same prefix, put it into `pref' and remove - # it from the matches. + tmp2=( "${(@)matches%%${sep}*}" ) + compadd -O tmp1 - "$tmp2[@]" - pref="$pref$tmp1" - matches=( "${(@)${(@)matches#$tmp1}:#}" ) + if [[ $#tmp1 -eq 1 ]]; then - if [[ "$orig" = *${sep}* ]]; then - orig="${orig#*${sep}}" - else - orig='' - fi - done + # Only one match. If there are still separators from the line + # we just accept this component. Otherwise we insert what we + # have collected, probably giving it a separator character + # as a suffix. - # Now we can tell the completion code about the things we - # found. Strings that have a separator will be added with a suffix. - - if [[ -z "$orig" && "$PREFIX$SUFFIX" != "$pref$orig" ]]; then - compadd -QU "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" -S '' - \ - "${pref}${orig}" - elif [[ -n "$menu" ]]; then - if [[ "$orig" = *${sep}* ]]; then - orig="${sep}${orig#*${sep}}" - else - orig='' - fi - for i in "$matches[@]" ; do - if [[ "$i" = *${sep}* ]]; then - compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ - -p "$pref" -s "$orig" - "${i%%${sep}*}${sep}" + if [[ "$pre$suf" = *${sep}* ]]; then + npref="${tmp1[1]}${sep}" else - compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ - -p "$pref" -s "$orig" - "${i%%${sep}*}" + matches=( "${(@M)matches:#${tmp1[1]}*}" ) + tmp2=( "${(@M)matches:#${tmp1[1]}${sep}*}" ) + + if (( $#tmp2 )); then + compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ + -p "$pref" -qS "$sep" - "$tmp1[1]" + else + compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ + -p "$pref" - "$tmp1[1]" + fi + return 1 fi - done - else - for i in "$matches[@]" ; do - if [[ "$i" = *${sep}* ]]; then - compadd -U -i "$IPREFIX" -I "$ISUFFIX" -p "$pref" -s "${i#*${sep}}" \ - "$group[@]" "$expl[@]" -M "r:|${sep:q}=*" - "${i%%${sep}*}${sep}" + elif (( $#tmp1 )); then + + # More than one match. First we get all strings that match the + # rest from the line. + + PREFIX="$pre" + SUFFIX="$suf" + compadd -O matches -M "r:|${sep}=* r:|=*" - "$matches[@]" + + if [[ -n "$menu" ]]; then + # With menucompletion we just add matches for the matching + # components with the prefix we collected and the rest from the + # line as a suffix. + + tmp2="$pre$suf" + if [[ "$tmp2" = *${sep}* ]]; then + compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ + -p "$pref" -s "${sep}${tmp2#*${sep}}" - "$tmp1[@]" + else + compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ + -p "$pref" - "$tmp1[@]" + fi else - compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ - -p "$pref" - "$i" + # With normal completion we add all matches one-by-one with + # the unmatched part as a suffix. This will insert the longest + # unambiguous string for all matching strings. + + for i in "${(@M)matches:#(${(j:|:)~tmp1})*}"; do + if [[ "$i" = *${sep}* ]]; then + compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ + -S '' -p "$pref" -s "${i#*${sep}}" - "${i%%${sep}*}${sep}" + else + compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ + -S '' -p "$pref" - "$i" + fi + done fi - done - fi -elif [[ "$patstr" = *${sep}* ]]; then - - # We had no words matching the string from the line. But we want to - # be friendly and at least expand the prefix as far as we can. So we - # will loop through the rest of the string from the line and test - # the components one by one. - - while [[ "$patstr" = *${sep}* ]]; do - - # First we get all words matching at least this component in - # `tmp1'. If there are none, we give up. - - if [[ -n "$_comp_correct" && "${#orig%%${sep}*}" -le _comp_correct ]]; then - mflags="$origflags" + return 0 else - mflags="$matchflags" - fi - tmp1=( "${(@M)matches:#${~mflags}${~patstr%%${sep}*}${sep}*}" ) - (( $#tmp1 )) || break - - # Then we check if there are words that have a different prefix. + # We are here if no string matched what's on the line. In this + # case we insert the expanded prefix we collected if it differs + # from the original string from the line. - tmp2=( "${(@)tmp1:#${tmp1[1]%%${sep}*}${sep}*}" ) - if (( $#tmp2 )); then + [[ "$orig" = "$pref$pre$suf" ]] && return 1 - # There are words with another prefix, so we have found an - # ambiguous component. So we just give all possible prefixes to - # the completion code together with our prefix and the rest of - # the string from the line as the suffix. - - compadd -U "$group[@]" "$expl[@]" -S '' -i "$IPREFIX" -I "$ISUFFIX" \ - -p "$pref" -s "${sep}${orig#*${sep}}" - "${(@)matches%%${sep}*}" + if [[ -n "$suf" ]]; then + compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ + -s "$suf" - "$pref$pre" + else + compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ + -S '' - "$pref$pre$suf" + fi return 0 fi + fi - # All words have the same prefix, so add it to `pref' again and - # try the next component. + # We just accepted and/or expanded a component from the line. We + # remove it from the matches (using only those that have a least + # the skipped string) and ad it the `pref'. - pref="$pref${tmp1[1]%%${sep}*}${sep}" - matches=( "${(@)matches#${tmp1[1]%%${sep}*}${sep}}" ) - orig="${orig#*${sep}}" - patstr="${patstr#*${sep}}" - done + matches=( "${(@)${(@)${(@M)matches:#${npref}*}#*${sep}}:#}" ) + pref="$pref$npref" - # Finally, add the unambiguous prefix and the rest of the string - # from the line. + # Now we set `pre' and `suf' to their new values. - compadd -U "$group[@]" "$expl[@]" -S '' -i "$IPREFIX" -I "$ISUFFIX" \ - -p "$pref" - "$orig" -fi + if [[ "$pre" = *${sep}* ]]; then + pre="${pre#*${sep}}" + elif [[ "$suf" = *${sep}* ]]; then + pre="${suf#*${sep}}" + suf="" + else + # The string from the line is fully handled. If we collected an + # unambiguous prefix and that differs from the original string, + # we insert it. -# This sets the return value to indicate that we added matches (or not). + [[ -n "$pref" && "$orig" != "$pref" ]] && + compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ + -S '' - "$pref" -[[ nm -ne compstate[nmatches] ]] + return + fi +done diff --git a/Completion/Core/_path_files b/Completion/Core/_path_files index 54b04a368..21837ade2 100644 --- a/Completion/Core/_path_files +++ b/Completion/Core/_path_files @@ -7,10 +7,9 @@ # the last have the same syntax and meaning as for `compgen' or # `compadd', respectively. The `-F ' option may be used to give # a list of suffixes either by giving the name of an array or -# literally by giving them in a string surrounded by -# parentheses. Files with one of the suffixes thus given are treated -# like files with one of the suffixes in the `fignore' array in normal -# completion. +# literally by giving them in a string surrounded by parentheses. Files +# with one of the suffixes thus given are treated like files with one +# of the suffixes in the `fignore' array in normal completion. # # This function supports one configuration key: # @@ -18,22 +17,13 @@ # If this is set to a non-empty string, the partially typed path # from the line will be expanded as far as possible even if trailing # pathname components can not be completed. -# -# -# This function uses the helper functions `_match_test' and `_match_pattern'. - -# First see if we should generate matches for the global matcher in use. - -_match_test _path_files || return 1 -# Yes, so... +local linepath realpath donepath prepath testpath exppath +local tmp1 tmp2 tmp3 tmp4 i orig pre suf tpre tsuf +local pats ignore group expl addpfx addsfx remsfx +local nm=$compstate[nmatches] menu -local nm str linepath realpath donepath patstr prepath testpath rest -local tmp1 collect tmp2 suffixes i ignore matchflags opt group sopt pats gopt -local addpfx addsfx expl orig ostr nm=$compstate[nmatches] menu remsfx patlast -local origflags mflags tmp3 tmp4 exppaths - -typeset -U prepaths +typeset -U prepaths exppaths setopt localoptions nullglob rcexpandparam extendedglob unsetopt markdirs globsubst shwordsplit nounset @@ -109,35 +99,27 @@ if [[ "$sopt" = - ]]; then fi fi -# str holds the whole string from the command line with a `*' between -# the prefix and the suffix. Then we see if we will do menucompletion. +# We get the prefix and the suffix from the line and save the whole +# original string. Then we see if we will do menucompletion. -if [[ $#compstate[pattern_match] -ne 0 ]]; then - if [[ "${compstate[pattern_match]-*}" = \** ]]; then - str="${PREFIX}*${SUFFIX}" - else - str="${PREFIX}${SUFFIX}" - fi -else - str="${PREFIX:q}*${SUFFIX:q}" - [[ "$str" = \\\~* ]] && str="$str[2,-1]" -fi +pre="$PREFIX" +suf="$SUFFIX" orig="${PREFIX}${SUFFIX}" -[[ $compstate[insert] = *menu || -n "$_comp_correct" || +[[ $compstate[insert] = (*menu|[0-9]*) || -n "$_comp_correct" || ( $#compstate[pattern_match] -ne 0 && "${orig#\~}" != "${${orig#\~}:q}" ) ]] && menu=yes - # We will first try normal completion called with `compgen', but only if we -# weren't given a `-F', `-r', or `-R' option. +# weren't given a `-F', `-r', or `-R' option or we are in the string. -if [[ $#ignore -eq 0 && $#remsfx -eq 0 && -z "$_comp_correct" ]]; then +if [[ -z "$suf" && $#ignore -eq 0 && $#remsfx -eq 0 && + -z "$_comp_correct" ]]; then # First build an array containing the `-W' option, if there is any and we # want to use it. We don't want to use it if the string from the command line # is a absolute path or relative to the current directory. - if [[ -z "$tmp1[1]" || "$str[1]" = [~/] || "$str" = (.|..)/* ]]; then + if [[ -z "$prepaths[1]" || "$pre[1]" = [~/] || "$pre" = (.|..)/* ]]; then tmp1=() else tmp1=(-W "( $prepaths )") @@ -145,7 +127,6 @@ if [[ $#ignore -eq 0 && $#remsfx -eq 0 && -z "$_comp_correct" ]]; then # Now call compgen. - nm=$compstate[nmatches] if [[ -z "$gopt" ]]; then compgen "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" "$tmp1[@]" $sopt else @@ -157,13 +138,13 @@ if [[ $#ignore -eq 0 && $#remsfx -eq 0 && -z "$_comp_correct" ]]; then [[ compstate[nmatches] -eq nm ]] || return 0 fi -# No `-F' option, so we want to use `fignore'. +# If given no `-F' option, we want to use `fignore'. (( $#ignore )) || ignore=(-F fignore) # Now let's have a closer look at the string to complete. -if [[ "$str[1]" = \~ ]]; then +if [[ "$pre[1]" = \~ ]]; then # It begins with `~', so remember anything before the first slash to be able # to report it to the completion code. Also get an expanded version of it # (in `realpath'), so that we can generate the matches. Then remove that @@ -171,10 +152,10 @@ if [[ "$str[1]" = \~ ]]; then # paths and make sure that the loop below is run only once with an empty # prefix path by setting `prepaths'. - linepath="${str%%/*}/" + linepath="${pre%%/*}/" eval realpath\=$linepath [[ "$realpath" = "$linepath" ]] && return 1 - str="${str#*/}" + pre="${pre#*/}" orig="${orig#*/}" donepath='' prepaths=( '' ) @@ -185,12 +166,12 @@ else linepath='' realpath='' - if [[ "$str[1]" = / ]]; then + if [[ "$pre[1]" = / ]]; then # If it is a absolut path name, we remove the first slash and put it in # `donepath' meaning that we treat it as the path that was already handled. # Also, we don't use the paths from `-W'. - str="$str[2,-1]" + pre="$pre[2,-1]" orig="$orig[2,-1]" donepath='/' prepaths=( '' ) @@ -198,278 +179,204 @@ else # The common case, we just use the string as it is, unless it begins with # `./' or `../' in which case we don't use the paths from `-W'. - [[ "$str" = (.|..)/* ]] && prepaths=( '' ) + [[ "$pre" = (.|..)/* ]] && prepaths=( '' ) donepath='' fi fi -# Now build the glob pattern by calling `_match_pattern'. -patstr="$str" -matchflags="" -_match_pattern _path_files patstr matchflags -origflags="$matchflags" -[[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)" - -# We almost expect the pattern to have changed `..' into `*.*.', `/.' into -# `/*.', and probably to contain two or more consecutive `*'s. Since these -# have special meaning for globbing, we remove them. But before that, we -# add the pattern for matching any characters before a slash. - -patstr="$patstr:gs-/-*/-:gs/*.*./../:gs/**/*/:gs-.*/-./-" - -# We take the last pathname component from the pattern and store it in -# `patlast', replacing `*'s in it with patterns that match any character -# but not slashes. Later we will generate matches using `patstr' with the -# patterns we were given (like `*.c') appended to it, producing all matching -# files. These filenames are then compared to `patlast' and all names not -# matching that will be removed. All this is needed to be able to correctly -# support `completeinword' as otherwise we would have something like `a*x' -# from the line (the `*' was inserted above) and appending the `-g' pattern -# `*.tex' would yield `a*x*.tex' which is not what we want. - -if [[ "$patstr" = */* ]]; then - if [[ -n "$_comp_correct" && "${#orig##*/}" -le _comp_correct ]]; then - patlast="*/${origflags}${${${patstr##*/}//\*/[^/]#}:gs.\[^/]#.\\\*.}" - else - patlast="*/${matchflags}${${${patstr##*/}//\*/[^/]#}:gs.\[^/]#.\\\*.}" - fi - patstr="${patstr%/*}/" -else - if [[ -n "$_comp_correct" && "$#orig" -le _comp_correct ]]; then - patlast="${origflags}${${patstr//\*/[^/]#}:gs.\[^/]#.\\\*.}" - else - patlast="${matchflags}${${patstr//\*/[^/]#}:gs.\[^/]#.\\\*.}" - fi - patstr="" -fi - -# First we skip over all pathname components in `str' which really exist in -# the file-system, so that `/usr/lib/l' doesn't offer you `lib' and -# `lib5'. Pathname components skipped this way are taken from `orig' and added -# to `donepath'. +# Now we generate the matches. First we loop over all prefix paths given +# with the `-W' option. -while [[ "$orig" = */* ]] do - tmp1=( $realpath$donepath${orig%%/*}/${~matchflags}${~patstr#*/}${^~pats} ) - tmp1=("${(@M)tmp1:#$~patlast}") - [[ $#tmp1 -gt 0 && -e "$realpath$donepath${orig%%/*}" ]] || break - donepath="$donepath${orig%%/*}/" - orig="${orig#*/}" - patstr="${patstr#*/}" -done +for prepath in "$prepaths[@]"; do -# Finally, generate the matches. First we loop over all the paths from `-W'. -# Note that in this loop `str' is used as a modifyable version of `patstr' -# and `testpath' is a modifyable version of `donepath'. + # Get local copies of the prefix, suffix, and the prefix path to use + # in the following loop, which walks through the pathname components + # in the string from the line. -for prepath in "$prepaths[@]"; do - str="$patstr" + tpre="$pre" + tsuf="$suf" testpath="$donepath" - ostr="$orig" - [[ -z "$prepath" || "$prepath[-1]" = / ]] || prepath="${prepath}/" + tmp1=( "$prepath$realpath$donepath" ) - # The second loop tests the components of the path in `str' to get the - # possible matches. + while true; do - while [[ "$str" = */* ]] do - # `rest' is the pathname after the first slash that is left. In `tmp1' - # we get the globbing matches for the pathname component currently - # handled. + # Skip over `./' and `../'. + + if [[ "$tpre" = (.|..)/* ]]; then + tmp1=( ${^tmp1}${tpre%%/*}/ ) + tpre="${tpre#*/}" + continue + fi - if [[ -n "$_comp_correct" && "${#ostr%%/*}" -le _comp_correct ]]; then - mflags="$origflags" + # Get the prefix and suffix for matching. + + if [[ "$tpre" = */* ]]; then + PREFIX="${tpre%%/*}" + SUFFIX="" else - mflags="$matchflags" + PREFIX="${tpre}" + SUFFIX="${tsuf%%/*}" fi - rest="${str#*/}" - tmp1="${prepath}${realpath}${testpath}${~mflags}${str%%/*}(-/)" - tmp1=( $~tmp1 ) - if [[ $#tmp1 -eq 0 ]]; then - # If this didn't produce any matches, we don't need to test this path - # any further, so continue with the next `-W' path, if any. + # Get the matching files by globbing. - continue 2 - elif [[ $#tmp1 -gt 1 ]]; then - # If it produced more than one match, we want to remove those which - # don't have possible following pathname components matching the - # rest of the string we are completing. (The case with only one - # match is handled below.) - # In `collect' we will collect those of the produced pathnames that - # have a matching possible path-suffix. In `suffixes' we build an - # array containing strings build from the rest of the string to - # complete and the glob patterns we were given as arguments. - - collect=() - suffixes=( $rest$^pats ) - suffixes=( "${(@)suffixes:gs.**.*.}" ) - - if [[ -n "$_comp_correct" && "${#ostr#*/}" -le _comp_correct ]]; then - mflags="$origflags" - else - mflags="$matchflags" - fi + if [[ "$tpre$tsuf" = */* ]]; then + tmp1=( ${^tmp1}*(D/) ) + else + tmp1=( ${^tmp1}${^~pats} ) + fi + + if [[ -n "$PREFIX$SUFFIX" ]]; then + # See which of them match what's on the line. - # In the loop the prefixes from the `tmp1' array produced above and - # the suffixes we just built are used to produce possible matches - # via globbing. - - for i in "$tmp1[@]" ; do - tmp2=( ${~i}/${~mflags}${~suffixes} ) - tmp2=("${(@M)tmp2:#$~patlast}") - [[ $#tmp2 -ne 0 ]] && collect=( $collect $i ) - done - - # If this test showed that none of the matches from the glob in `tmp1' - # has a possible sub-path matching what's on the line, we add the - # matches found in `tmp1' and otherwise give up and continue with the - # next `-W' path. - - if [[ $#collect -eq 0 ]]; then - # Before giving, we first try to get the longest expandable path- - # prefix, though. The result is stored in `exppaths' - - tmp2=() - tmp3="$rest" - tmp4="${ostr##*/}" - ostr="${ostr%/*}" - while [[ "$tmp3" = */* ]]; do - tmp2=( ${^tmp1}/${~mflags}${~tmp3} ) - if [[ $#tmp2 -eq 1 ]]; then - exppaths=( "$exppaths[@]" "${tmp2[1]}${tmp4}" ) - exppaths=( "${(@)exppaths#${prepath}${realpath}}" ) - break; - fi - tmp3="${tmp3%/*}" - tmp4="${ostr##*/}/${tmp4}" - ostr="${ostr%/*}" - done + compadd -O tmp2 "$ignore[@]" - "${(@)tmp1##*/}" + + # If no file matches, save the expanded path and continue with + # the outer loop. + + if [[ $#tmp2 -eq 0 ]]; then + [[ "$tmp1[1]" = */* ]] && + exppaths=( "$exppaths[@]" ${^tmp1%/*}/${tpre}${tsuf} ) continue 2 - elif [[ $#collect -ne 1 ]]; then - # If we have more than one possible match, this means that the - # pathname component currently handled is ambiguous, so we give - # it to the completion code. - # First we build the full path prefix in `tmp1'. + fi - tmp1="$prepath$realpath$testpath" + # Remove all files that weren't matched. - # Now produce all matching pathnames in `collect'. + if [[ "$tmp1[1]" = */* ]]; then + tmp1=( "${(@M)tmp1:#*/(${(j:|:)~${(@)tmp2:q}})}" ) + else + tmp1=( "${(@M)tmp1:#(${(j:|:)~${(@)tmp2:q}})}" ) + fi + elif (( ! $#tmp1 )); then + [[ "$tmp1[1]" = */* ]] && + exppaths=( "$exppaths[@]" ${^tmp1%/*}/${tpre}${tsuf} ) + continue 2 + fi - collect=( ${~collect}/${~matchflags}${~suffixes} ) - collect=("${(@M)collect:#$~patlast}") + # Step over to the next component, if any. - # And then remove the common path prefix from all these matches. + if [[ "$tpre" = */* ]]; then + tpre="${tpre#*/}" + elif [[ "$tsuf" = */* ]]; then + tpre="${tsuf#*/}" + tsuf="" + else + break + fi - collect=( ${collect#$tmp1} ) + # There are more components, so add a slash to the files we are + # collecting. - # Finally, we add all these matches with the common (unexpanded) - # pathprefix (the `-p' option), the path-prefix (the `-W' option) - # to allow the completion code to test file type, and the path- - # suffix (the `-s' option). We also tell the completion code that - # these are file names and that `fignore' should be used as usual - # (the `-f' and `-F' options). + tmp1=( ${^tmp1}/ ) + done - if [[ -n "$menu" ]]; then - compadd -QU "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" \ - -i "$IPREFIX" -I "$ISUFFIX" -p "$linepath${testpath:q}" \ - -s "/${ostr#*/}" \ - -W "$tmp1" -f "$ignore[@]" - "${(@)${(@)collect%%/*}:q}" - else - for i in $collect; do - compadd -QU "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" \ - -i "$IPREFIX" -I "$ISUFFIX" \ - -p "$linepath${testpath:q}" -s "/${${i#*/}:q}" \ - -M 'r:|/=*' -W "$tmp1" -f "$ignore[@]" - "${${i%%/*}:q}" - done - fi + # The next loop searches the first ambiguous component. - # We have just finished handling all the matches from above, so we - # can continue with the next `-W' path. + tmp3="$pre$suf" + tmp1=( "${(@)tmp1#${prepath}${realpath}${testpath}}" ) - continue 2 - fi + while true; do - # We reach this point if only one of the path prefixes in `tmp1' - # has a existing path-suffix matching the string from the line. - # In this case we accept this match and continue with the next - # path-name component. + # First we check if some of the files match the original string + # for this component. If there are some we remove all other + # names. This avoid having `foo' complete to `foo' and `foobar'. - tmp1=( "$collect[1]" ) - elif [[ -n "$_comp_correct" && "$mflags" = "$matchflags" ]]; then + if [[ "$tmp3" = */* ]]; then + tmp4=( "${(@M)tmp1:#${tmp3%%/*}/*}" ) + if (( $#tmp4 )); then + tmp1=( "$tmp4[@]" ) + fi + fi - # If we got only one match with auto-correction and if we get none - # without correction, stop now. + # Next we see if this component is ambiguous. - tmp2="${prepath}${realpath}${testpath}${~origflags}${str%%/*}(-/)" - tmp2=( $~tmp2 ) + if [[ "$tmp3" = */* ]]; then + tmp4=( "${(@)tmp1:#${tmp1[1]%%/*}/*}" ) + else + tmp4=( "${(@)tmp1:#${tmp1[1]}}" ) + fi - if [[ $#tmp1 -ne $#tmp2 ]]; then - compadd -QU "$addpfx[@]" -S '' "$group[@]" "$expl[@]" \ - -i "$IPREFIX" -I "$ISUFFIX" \ - -p "$linepath${testpath:q}" -s "/${ostr#*/}" \ - - "${${tmp1#${prepath}${realpath}${testpath}}:q}" - continue 2 + if (( $#tmp4 )); then + + # It is. For menucompletion we now add the possible completions + # for this component with the unambigous prefix we have built + # and the rest of the string from the line as the suffix. + # For normal completion we add the rests of the filenames + # collected as the suffixes to make the completion code expand + # it as far as possible. + + if [[ -n $menu ]]; then + if [[ "$tmp3" = */* ]]; then + compadd -Uf -p "$linepath$testpath" -s "/${tmp3#*/}" \ + -W "$prepath$realpath$testpath" "$ignore[@]" \ + "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \ + "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ + - "${(@)tmp1%%/*}" + else + compadd -Uf -p "$linepath$testpath" \ + -W "$prepath$realpath$testpath" "$ignore[@]" \ + "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \ + "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ + - "$tmp1[@]" + fi + else + if [[ "$tmp3" = */* ]]; then + for i in "$tmp1[@]"; do + compadd -Uf -p "$linepath$testpath" -s "/${i#*/}" \ + -W "$prepath$realpath$testpath" "$ignore[@]" \ + "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" -M 'r:|/=* r:|=*' \ + "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ + - "${i%%/*}" + done + else + compadd -Uf -p "$linepath$testpath" \ + -W "$prepath$realpath$testpath" "$ignore[@]" \ + "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \ + "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ + - "$tmp1[@]" + fi fi + tmp4=- + break fi - # This is also reached if the first globbing produced only one match - # in this case we just continue with the next pathname component, too. - tmp1="$tmp1[1]" - testpath="$testpath${tmp1##*/}/" - str="$rest" - ostr="${ostr#*/}" - done + # If we have checked all components, we stop now and add the + # strings collected after the loop. - # We are here if all pathname components except the last one (which is still - # not tested) are unambiguous. So we add matches with the full path prefix, - # no path suffix, the `-W' we are currently handling, all the matches we - # can produce in this directory, if any. + if [[ "$tmp3" != */* ]]; then + tmp4="" + break + fi - if [[ -n "$_comp_correct" && "${#ostr#*/}" -le _comp_correct ]]; then - mflags="$origflags" - else - mflags="$matchflags" - fi - tmp1="$prepath$realpath$testpath" - suffixes=( $str$^pats ) - suffixes=( "${(@)suffixes:gs.**.*.}" ) - tmp2=( ${~tmp1}${~matchflags}${~suffixes} ) - if [[ "$tmp1" = */* && "$patlast" != \*/* ]]; then - tmp2=("${(@M)tmp2:#*${~patlast}}") - else - tmp2=("${(@M)tmp2:#$~patlast}") - fi - if [[ $#tmp2 -eq 0 ]]; then - # No match, insert the expanded path and add the original tail. + # Otherwise we add the unambiguous component to `testpath' and + # take it from the filenames. - [[ "$testpath[-1]" = / ]] && testpath="$testpath[1,-2]" - [[ -z "$testpath" && "$linepath[-1]" = / ]] && linepath="$linepath[1,-2]" - [[ -n "$ostr" && -n "$linepath$testpath" ]] && ostr="/$ostr" + testpath="${testpath}${tmp1[1]%%/*}/" + tmp1=( "${(@)tmp1#*/}" ) - # But only if something changed. - [[ "${PREFIX}${SUFFIX}" = $linepath$testpath$ostr(|/) ]] && return 1 + tmp3="${tmp3#*/}" + done - compadd -QU -S '' "$group[@]" "$expl[@]" \ - -i "$IPREFIX" -I "$ISUFFIX" -f - "$linepath${testpath:q}$ostr" - else - compadd -QU "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" "$group[@]" "$expl[@]" \ - -i "$IPREFIX" -I "$ISUFFIX" \ - -p "$linepath${testpath:q}" -f "$ignore[@]" \ - -W "$prepath$realpath$testpath" - "${(@)${(@)tmp2#$tmp1}:q}" + if [[ -z "$tmp4" ]]; then + compadd -Uf -p "$linepath$testpath" \ + -W "$prepath$realpath$testpath" "$ignore[@]" \ + "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \ + "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ + - "$tmp1[@]" fi done -# If no matches were found but we have expanded paths which are different -# from the original string, use them. +# If we are configured to expand paths as far as possible and we collected +# expanded paths that are different from the string on the line, we add +# them as possible matches. exppaths=( "${(@)exppaths:#$orig}" ) if [[ -n "$compconfig[path_expand]" && - nm -eq compstate[nmatches] && $#exppaths -ne 0 ]]; then - compadd -UQ -S '' "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" - \ - "${linepath}${(@)^exppaths}" + $#exppaths -ne 0 && nm -eq compstate[nmatches] ]]; then + compadd -U -S '' "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" - \ + "${(@)exppaths}" fi -# This sets the return value to indicate that we added matches (or not). - -[[ nm -ne compstate[nmatches] ]] +[[ nm -eq compstate[nmatches] ]] diff --git a/Completion/Core/_sep_parts b/Completion/Core/_sep_parts index fc927163b..b906a3042 100644 --- a/Completion/Core/_sep_parts +++ b/Completion/Core/_sep_parts @@ -9,24 +9,17 @@ # # _sep_parts '(foo bar)' @ hosts # -# This will make this function complete the strings in the array -# `friends'. If the string on the line contains a `@', the substring -# after it will be completed from the array `hosts'. Of course more -# arrays may be given, each preceded by another separator string. +# This will make this function complete the strings `foo' and `bar' +# If the string on the line contains a `@', the substring after it +# will be completed from the array `hosts'. Of course more arrays +# may be given, each preceded by another separator string. # # This function understands the `-J group', `-V group', and # `-X explanation' options. -# -# This function does part of the matching itself and calls the functions -# `_match_test' and `_match_pattern' for this. local str arr sep test testarr tmparr prefix suffixes matchers autosuffix local matchflags opt group expl nm=$compstate[nmatches] -# Test if we should use this function for the global matcher in use. - -_match_test _sep_parts || return 1 - # Get the options. group=() @@ -42,7 +35,7 @@ shift OPTIND-1 # Get the string from the line. str="$PREFIX$SUFFIX" -[[ $#compstate[pattern_match] -ne 0 ]] || str="$str:q" +SUFFIX="" prefix="" # Walk through the arguments to find the longest unambiguous prefix. @@ -56,61 +49,49 @@ while [[ $# -gt 1 ]]; do tmparr=( ${=arr[2,-2]} ) arr=tmparr fi - # Is the separator on the line? - [[ "$str" != *${sep}* ]] && break - # Build a pattern matching the possible matches and get all these - # matches in an array. + # Is the separator on the line? - test="${str%%${sep}*}" - [[ -n "$_comp_correct" && $#test -le _comp_correct ]] && return 1 + [[ "$str" != *${sep}* ]] && break - matchflags="" - _match_pattern _sep_parts test matchflags - [[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)" + # Get the matching array elements. - test="${matchflags}${test}" - testarr=( "${(@M)${(@P)arr}:#${~test}*}" ) - testarr=( "${(@)testarr:#}" ) + PREFIX="${str%%${sep}*}" + compadd -O testarr - "${(@P)arr}" # If there are no matches we give up. If there is more than one # match, this is the part we will complete. + (( $#testarr )) || return 1 [[ $#testarr -gt 1 ]] && break # Only one match, add it to the prefix and skip over it in `str', # continuing with the next array and separator. + prefix="${prefix}${testarr[1]}${sep}" str="${str#*${sep}}" shift 2 done # Get the array to work upon. + arr="$1" if [[ "$arr[1]" == '(' ]]; then tmparr=( ${=arr[2,-2]} ) arr=tmparr fi + if [[ $# -le 1 || "$str" != *${2}* ]]; then # No more separators, build the matches. - test="$str" - [[ -n "$_comp_correct" && $#test -le _comp_correct ]] && return 1 - - matchflags="" - _match_pattern _sep_parts test matchflags - [[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)" - - [[ "${compstate[pattern_match]-*}" != \** ]] && test="$test:gs/*//" - - test="${matchflags}${test}" - testarr=( "${(@M)${(@P)arr}:#${~test}*}" ) - testarr=( "${(@)testarr:#}" ) + PREFIX="$str" + compadd -O testarr - "${(@P)arr}" fi [[ $#testarr -eq 0 || ${#testarr[1]} -eq 0 ]] && return 1 # Now we build the suffixes to give to the completion code. + shift matchers=() suffixes=("") @@ -118,26 +99,18 @@ autosuffix=() while [[ $# -gt 0 && "$str" == *${1}* ]]; do # Remove anything up to the the suffix. + str="${str#*${1}}" # Again, we get the string from the line up to the next separator # and build a pattern from it. + if [[ $# -gt 2 ]]; then - test="${str%%${3}*}" + PREFIX="${str%%${3}*}" else - test="$str" + PREFIX="$str" fi - [[ -n "$_comp_correct" && $#test -le _comp_correct ]] && return 1 - - matchflags="" - _match_pattern _sep_parts test matchflags - [[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)" - - [[ "${compstate[pattern_match]-*}" != \** ]] && test="$test:gs/*//" - - test="${matchflags}${test}" - # We incrementally add suffixes by appending to them the seperators # and the strings from the next array that match the pattern we built. @@ -146,26 +119,31 @@ while [[ $# -gt 0 && "$str" == *${1}* ]]; do tmparr=( ${=arr[2,-2]} ) arr=tmparr fi - tmparr=( "${(@M)${(@P)arr}:#${~test}*}" ) - tmparr=( "${(@)tmparr:#}" ) + + compadd -O tmparr - "${(@P)arr}" + suffixes=("${(@)^suffixes[@]}${1}${(@)^tmparr}") # We want the completion code to generate the most specific suffix # for us, so we collect matching specifications that allow partial # word matching before the separators on the fly. + matchers=("$matchers[@]" "r:|${1:q}=*") shift 2 done # If we were given at least one more separator we make the completion # code offer it by appending it as a autoremovable suffix. + (( $# )) && autosuffix=(-qS "$1") # If we have collected matching specifications, we build an array # from it that can be used as arguments to `compadd'. + [[ $#matchers -gt 0 ]] && matchers=(-M "$matchers") # Add the matches for each of the suffixes. + for i in "$suffixes[@]"; do compadd -U "$group[@]" "$expl[@]" "$matchers[@]" "$autosuffix[@]" \ -i "$IPREFIX" -I "$ISUFFIX" -p "$prefix" -s "$i" - "$testarr[@]" diff --git a/Completion/Core/compinit b/Completion/Core/compinit index 19a0fd1ad..20b1262ec 100644 --- a/Completion/Core/compinit +++ b/Completion/Core/compinit @@ -1,25 +1,23 @@ # Initialisation for new style completion. This mainly contains some helper -# function and aliases. Everything else is split into different files in this -# directory that will automatically be made autoloaded (see the end of this -# file). +# functions and aliases. Everything else is split into different files that +# will automatically be made autoloaded (see the end of this file). # The names of the files that will be considered for autoloading have to -# start with a underscores (like `_setopt). +# start with an underscores (like `_setopt). # The first line of these files will be read and has to say what should be # done with its contents: # -# `#defcomp ' -# 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 is given +# `#compdef ' +# 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 are given. # -# `#defpatcomp ' -# this defines a function that should be called to generate -# matches for commands whose name matches ; note -# that only one pattern may be given +# `#compdef -p ' +# This defines a function that should be called to generate matches +# for commands whose name matches . Note that only one pattern +# may be given. # -# `#defkeycomp