From 7a0415cfd70a02b2280d27556c6c54cef1c86e1a Mon Sep 17 00:00:00 2001 From: Tanaka Akira Date: Thu, 15 Apr 1999 18:18:42 +0000 Subject: zsh-3.1.5-pws-11 --- Completion/Base/_brace_parameter | 5 + Completion/Base/_command_names | 6 +- Completion/Base/_condition | 10 +- Completion/Base/_default | 3 +- Completion/Base/_equal | 3 + Completion/Base/_match_pattern | 6 +- Completion/Base/_match_test | 8 +- Completion/Base/_parameter | 3 + Completion/Base/_precommand | 5 +- Completion/Base/_subscript | 5 +- Completion/Base/_tilde | 10 ++ Completion/Base/_vars | 2 +- Completion/Builtins/_aliases | 2 +- Completion/Builtins/_arrays | 2 +- Completion/Builtins/_autoload | 2 +- Completion/Builtins/_bg_jobs | 2 +- Completion/Builtins/_bindkey | 6 +- Completion/Builtins/_builtin | 8 +- Completion/Builtins/_cd | 63 +++++++++- Completion/Builtins/_command | 6 +- Completion/Builtins/_disable | 10 +- Completion/Builtins/_echotc | 2 +- Completion/Builtins/_enable | 10 +- Completion/Builtins/_fc | 8 +- Completion/Builtins/_functions | 2 +- Completion/Builtins/_hash | 6 +- Completion/Builtins/_jobs | 2 +- Completion/Builtins/_kill | 6 +- Completion/Builtins/_limits | 2 +- Completion/Builtins/_sched | 2 +- Completion/Builtins/_set | 10 +- Completion/Builtins/_setopt | 7 +- Completion/Builtins/_source | 4 +- Completion/Builtins/_trap | 6 +- Completion/Builtins/_unhash | 10 +- Completion/Builtins/_unsetopt | 7 +- Completion/Builtins/_vars_eq | 2 +- Completion/Builtins/_wait | 4 +- Completion/Builtins/_which | 2 +- Completion/Builtins/_zftp | 14 +-- Completion/Builtins/_zle | 6 +- Completion/Builtins/_zmodload | 12 +- Completion/Commands/_correct_filename | 6 +- Completion/Commands/_most_recent_file | 24 +++- Completion/Core/_comp_parts | 25 +++- Completion/Core/_compalso | 6 +- Completion/Core/_files | 7 +- Completion/Core/_main_complete | 219 ++++++++++++++++++++++++++++------ Completion/Core/_multi_parts | 201 +++++++++++++++++++++++++++++++ Completion/Core/_normal | 30 ++--- Completion/Core/_path_files | 110 +++++++++++------ Completion/README | 31 +++-- Completion/User/_a2ps | 8 +- Completion/User/_configure | 29 ++++- Completion/User/_dd | 4 +- Completion/User/_find | 24 ++-- Completion/User/_hosts | 2 +- Completion/User/_make | 2 +- Completion/User/_man | 6 +- Completion/User/_mh | 36 +++--- Completion/User/_rcs | 8 +- Completion/User/_rlogin | 10 +- Completion/User/_stty | 6 +- Completion/User/_tar | 68 ++++++++++- Completion/User/_x_options | 2 +- 65 files changed, 892 insertions(+), 263 deletions(-) create mode 100644 Completion/Base/_brace_parameter create mode 100644 Completion/Base/_equal create mode 100644 Completion/Base/_parameter create mode 100644 Completion/Base/_tilde create mode 100644 Completion/Core/_multi_parts (limited to 'Completion') diff --git a/Completion/Base/_brace_parameter b/Completion/Base/_brace_parameter new file mode 100644 index 000000000..092376e78 --- /dev/null +++ b/Completion/Base/_brace_parameter @@ -0,0 +1,5 @@ +#defcomp -brace-parameter- + +# Simple but without spiffy suffix handling: compgen -v -S '} ' + +compadd -S '} ' -r '-:?#%+=[/' - "${(@)${${${(f)$(typeset)}%%\=*}##* }:gs/'//}" diff --git a/Completion/Base/_command_names b/Completion/Base/_command_names index d3b8a109a..eab314dfa 100644 --- a/Completion/Base/_command_names +++ b/Completion/Base/_command_names @@ -1,3 +1,7 @@ #defcomp -command- -complist -c +local nm=$compstate[nmatches] + +compgen -c + +[[ nm -eq compstate[nmatches] ]] && _path_files -/g "*(*)" diff --git a/Completion/Base/_condition b/Completion/Base/_condition index 3e45e1b8f..fb6b98b1b 100644 --- a/Completion/Base/_condition +++ b/Completion/Base/_condition @@ -1,10 +1,12 @@ #defcomp -condition- -if [[ -current -1 -o ]]; then - complist -o -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -elif [[ -current -1 -nt || -current -1 -ot || -current -1 -ef ]]; then +local prev="$words[CURRENT-1]" + +if [[ "$prev" = -o ]]; then + compgen -o -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' +elif [[ "$prev" = -([no]t|ef) ]]; then _files else _files - complist -v + compgen -v fi diff --git a/Completion/Base/_default b/Completion/Base/_default index 8bcf14f6a..569bd6382 100644 --- a/Completion/Base/_default +++ b/Completion/Base/_default @@ -6,7 +6,8 @@ # immediatly. If you want to use new style completion anyway, remove the # `|| return'. Also, you may want to use new style completion if the # `compctl' didn't produce any matches. In that case remove the `|| return' -# and at the line `[[ -nmatches 0 ]] || return' after `compcall'. +# and insert the line `[[ compstate[nmatches] -eq 0 ]] || return' after +# `compcall'. compcall || return diff --git a/Completion/Base/_equal b/Completion/Base/_equal new file mode 100644 index 000000000..f407014fe --- /dev/null +++ b/Completion/Base/_equal @@ -0,0 +1,3 @@ +#defcomp -equal- + +compgen -am diff --git a/Completion/Base/_match_pattern b/Completion/Base/_match_pattern index c5debc0b9..3df115d5b 100644 --- a/Completion/Base/_match_pattern +++ b/Completion/Base/_match_pattern @@ -10,7 +10,7 @@ # the match specs currently in use do. # In the calling function this pattern may be changed again or used only # in parts. The second parameter whose name is given as the third argument -# allows to give pattern flags liek `(#l)' that are to be used whenever +# allows to give pattern flags like `(#l)' that are to be used whenever # matching is done. # # As an example, if you have global match specifications like: @@ -20,12 +20,12 @@ # This function would look like: # # eval "${3}='(#l)'" -# [[ MATCHER -eq 2 ]] && eval "$1='${(P)2:gs/./*./:gs/-/*-/}'" +# [[ compstate[matcher] -eq 2 ]] && eval "$2='${(P)2:gs/./*./:gs/-/*-/}'" # # The first line makes sure that matching is done case-insensitive as # specified by `m:{a-z}={A-Z}'. The second line replaces dots and hyphens # in the given string by patterns matching any characters before them, # like the `r:|[.-]=* r:|=*'. To make this work, the function `_match_test' -# would have to be changed to `(( MATCHERS <= 2 ))' +# would have to be changed to `(( compstate[matcher] <= 2 ))' # # The default implementation of this function is empty. diff --git a/Completion/Base/_match_test b/Completion/Base/_match_test index e8b6e6424..7db521e81 100644 --- a/Completion/Base/_match_test +++ b/Completion/Base/_match_test @@ -1,9 +1,9 @@ #autoload # This function is called at the beginning of functions that do matching in -# shell code. It should test the value of the `MATCHER' special parameter -# and return non-zero if the calling function should try to generate matches -# for the global match specification in use. +# shell code. It should test the value of `compstate[matcher]' and return +# non-zero if the calling function should try to generate matches for the +# global match specification in use. # # This function gets one argument, the name of the function calling it. # @@ -12,4 +12,4 @@ # match specifications and modify the function `_match_pattern' to build the # pattern to use in the calling function. -(( MATCHER == 1 )) +(( compstate[matcher] <= 1 )) diff --git a/Completion/Base/_parameter b/Completion/Base/_parameter new file mode 100644 index 000000000..2bd66ec93 --- /dev/null +++ b/Completion/Base/_parameter @@ -0,0 +1,3 @@ +#defcomp -parameter- + +compgen -v diff --git a/Completion/Base/_precommand b/Completion/Base/_precommand index 2cf661147..c13cd7465 100644 --- a/Completion/Base/_precommand +++ b/Completion/Base/_precommand @@ -1,5 +1,6 @@ #defcomp - nohup nice eval time rusage noglob nocorrect exec -[[ -position 1 -1 ]] +shift words +(( CURRENT-- )) -_normal "$@" +_normal diff --git a/Completion/Base/_subscript b/Completion/Base/_subscript index 2b827a117..d50fd8335 100644 --- a/Completion/Base/_subscript +++ b/Completion/Base/_subscript @@ -1,4 +1,5 @@ #defcomp -subscript- -_compalso -math- "$@" -[[ ${(Pt)${COMMAND}} = assoc* ]] && complist -k "( ${(kP)${COMMAND}} )" +_compalso -math- +[[ ${(Pt)${compstate[parameter]}} = assoc* ]] && + compgen -k "( ${(kP)${compstate[parameter]}} )" diff --git a/Completion/Base/_tilde b/Completion/Base/_tilde new file mode 100644 index 000000000..aef575e19 --- /dev/null +++ b/Completion/Base/_tilde @@ -0,0 +1,10 @@ +#defcomp -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 +# `compgen -k friends -qS/' or something like that. To get all user names +# if there are no matches in the `friends' array, add +# `(( compstate[nmatches] )) || compgen -nu -qS/' +# below that. + +compgen -nu -qS/ diff --git a/Completion/Base/_vars b/Completion/Base/_vars index 7153b6f38..92de51e1f 100644 --- a/Completion/Base/_vars +++ b/Completion/Base/_vars @@ -1,3 +1,3 @@ #defcomp -math- getopts read unset vared -complist -v +compgen -v diff --git a/Completion/Builtins/_aliases b/Completion/Builtins/_aliases index 1038a726e..2ccf18439 100644 --- a/Completion/Builtins/_aliases +++ b/Completion/Builtins/_aliases @@ -1,3 +1,3 @@ #defcomp unalias -complist -a +compgen -a diff --git a/Completion/Builtins/_arrays b/Completion/Builtins/_arrays index cbeac7118..94401f28a 100644 --- a/Completion/Builtins/_arrays +++ b/Completion/Builtins/_arrays @@ -1,3 +1,3 @@ #defcomp shift -complist -A +compgen -A diff --git a/Completion/Builtins/_autoload b/Completion/Builtins/_autoload index 4f506baeb..d1462e09a 100644 --- a/Completion/Builtins/_autoload +++ b/Completion/Builtins/_autoload @@ -1,3 +1,3 @@ #defcomp autoload -complist -s '${^fpath}/*(N:t)' +compgen -s '${^fpath}/*(N:t)' diff --git a/Completion/Builtins/_bg_jobs b/Completion/Builtins/_bg_jobs index 511bb8308..4abee070c 100644 --- a/Completion/Builtins/_bg_jobs +++ b/Completion/Builtins/_bg_jobs @@ -1,3 +1,3 @@ #defcomp bg -complist -z -P '%' +compgen -z -P '%' diff --git a/Completion/Builtins/_bindkey b/Completion/Builtins/_bindkey index 8eddeb2a8..d3d019492 100644 --- a/Completion/Builtins/_bindkey +++ b/Completion/Builtins/_bindkey @@ -1,7 +1,7 @@ #defcomp bindkey -if [[ -mword 1 -*[DAN]* || -mcurrent -1 -*M ]]; then - complist -s '$(bindkey -l)' +if [[ "$words[2]" = -*[DAN]* || "$words[CURRENT-1] = -*M ]]; then + compgen -s '$(bindkey -l)' else - complist -b + compgen -b fi diff --git a/Completion/Builtins/_builtin b/Completion/Builtins/_builtin index a967932ee..bee67fe8f 100644 --- a/Completion/Builtins/_builtin +++ b/Completion/Builtins/_builtin @@ -1,7 +1,9 @@ #defcomp builtin -if [[ -position 2 -1 ]]; then - _normal "$@" +if (( $CURRENT > 2 )); then + shift words + (( CURRENT -- )) + _normal else - complist -eB + compgen -eB fi diff --git a/Completion/Builtins/_cd b/Completion/Builtins/_cd index f3ce67ec7..65ce7f293 100644 --- a/Completion/Builtins/_cd +++ b/Completion/Builtins/_cd @@ -1,3 +1,62 @@ -#defcomp cd +#defcomp cd pushd -_files -W cdpath -g '*(-/)' +# Handling of cd. +# - Normally just completes directories. Uses cdpath if that's set +# and the string doesn't begin with ~, /, ./ or ../. +# - In the second argument to cd for the form `cd old new', completes +# possible `new' strings by examining `old' and $PWD. +# - After pushd - or pushd +, completes numbers, but the listing +# gives you the list of directories to complete. This turns on +# menu-completion and lists the possibilities automatically, otherwise +# it's not a lot of use. If you don't type the + or - it will +# complete directories as normal. + +local pushdminus +[[ -o pushdminus ]] && pushdminus=1 + +emulate -LR zsh +setopt extendedglob + +if [[ -position 3 ]]; then + # cd old new: look for old in $PWD and see what can replace it + local rep + # Get possible completions using word in position 2 + rep=(${~PWD/$words[2]/*}~$PWD(-/N)) + # Now remove all the common parts of $PWD and the completions from this + rep=(${${rep#${PWD%%$words[2]*}}%${PWD#*$words[2]}}) + (( $#rep )) && compadd $rep +elif [[ $words[1] = pu* && $PREFIX = [-+]* ]]; then + # pushd: just complete the numbers, but show the full directory list with + # numbers. + # For - we do the same thing, but reverse the numbering (other + # way round if pushdminus is set). + # The test is for pu* because I have an alias pu since I'm too + # lazy to type pushd. + IPREFIX=$PREFIX[1] + PREFIX=$PREFIX[2,-1] + local list lines + # get the list of directories with their canonical number + lines="$(dirs -v)" + # turn the lines into an array, removing the current directory + list=(${${(f)lines}##0*}) + if [[ ( $IPREFIX = - && -z $pushdminus ) || + ( $IPREFIX = + && -n $pushdminus ) ]]; then + # reverse the numbering: it counts the last one as -0, which + # is a little strange. + integer tot i + for (( i = 1, tot = $#list-1; tot >= 0; i++, tot-- )); do + list[$i]="$tot${list[$i]##[0-9]#}" + done + fi + # make sure -y treats this as a single string + lines="${(F)list}" + # get the array of numbers only + list=(${list%%[ ]*}) + compgen -y '$lines' -Q -k list + [[ -z $compstate[list] ]] && compstate[list]=list + [[ -n $compstate[insert] ]] && compstat[insert]=menu +elif [[ $PREFIX != (\~|/|./|../)* && $#cdpath -ne 0 ]]; then + _path_files -W cdpath -/ +else + _path_files -/ +fi diff --git a/Completion/Builtins/_command b/Completion/Builtins/_command index b2812de25..47eb0d667 100644 --- a/Completion/Builtins/_command +++ b/Completion/Builtins/_command @@ -1,7 +1,7 @@ #defcomp command -if [[ -position 2 -1 ]]; then - _normal "$@" +if [[ -position 3 -1 ]]; then + _normal else - complist -em + compgen -em fi diff --git a/Completion/Builtins/_disable b/Completion/Builtins/_disable index 063b65a7d..e3edafe2b 100644 --- a/Completion/Builtins/_disable +++ b/Completion/Builtins/_disable @@ -1,6 +1,8 @@ #defcomp disable -[[ -mcurrent -1 -*a* ]] && complist -ea -[[ -mcurrent -1 -*f* ]] && complist -eF -[[ -mcurrent -1 -*r* ]] && complist -ew -[[ ! -mcurrent -1 -* ]] && complist -eB +local prev="$words[CURRENT-1]" + +[[ "$prev" = -*a* ]] && compgen -ea +[[ "$prev" = -*f* ]] && compgen -eF +[[ "$prev" = -*r* ]] && compgen -ew +[[ "$prev" != -* ]] && compgen -eB diff --git a/Completion/Builtins/_echotc b/Completion/Builtins/_echotc index 85ebb97ce..135cabada 100644 --- a/Completion/Builtins/_echotc +++ b/Completion/Builtins/_echotc @@ -1,3 +1,3 @@ #defcomp echotc -complist -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)' +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 22ff53ee7..111d1ae26 100644 --- a/Completion/Builtins/_enable +++ b/Completion/Builtins/_enable @@ -1,6 +1,8 @@ #defcomp enable -[[ -mcurrent -1 -*a* ]] && complist -da -[[ -mcurrent -1 -*f* ]] && complist -dF -[[ -mcurrent -1 -*r* ]] && complist -dw -[[ ! -mcurrent -1 -* ]] && complist -dB +local prev="$words[CURRENT-1]" + +[[ "$prev" = -*a* ]] && compgen -da +[[ "$prev" = -*f* ]] && compgen -dF +[[ "$prev" = -*r* ]] && compgen -dw +[[ "$prev" != -* ]] && compgen -dB diff --git a/Completion/Builtins/_fc b/Completion/Builtins/_fc index f0d2c03fd..f8cf4dde8 100644 --- a/Completion/Builtins/_fc +++ b/Completion/Builtins/_fc @@ -1,7 +1,9 @@ #defcomp fc -if [[ -mcurrent -1 -*e ]]; then - complist -c -elif [[ -mcurrent -1 -[ARWI]## ]]; then +local prev="$words[CURRENT-1]" + +if [[ "$prev" = -*e ]]; then + compgen -c +elif [[ "$prev" = -[ARWI]## ]]; then _files fi diff --git a/Completion/Builtins/_functions b/Completion/Builtins/_functions index 8a352ea08..7e3174af5 100644 --- a/Completion/Builtins/_functions +++ b/Completion/Builtins/_functions @@ -1,3 +1,3 @@ #defcomp unfunction -complist -F +compgen -F diff --git a/Completion/Builtins/_hash b/Completion/Builtins/_hash index 171c5e2e8..8c100b801 100644 --- a/Completion/Builtins/_hash +++ b/Completion/Builtins/_hash @@ -1,13 +1,13 @@ #defcomp hash -if [[ -mword 1 -*d* ]]; then +if [[ "$words[2]" = -*d* ]]; then if [[ -string 1 '=' ]]; then _path_files -g '*(-/)' else - complist -n -q -S '=' + compgen -n -q -S '=' fi elif [[ -string 1 '=' ]]; then _files -/g '*(*)' else - complist -m -q -S '=' + compgen -m -q -S '=' fi diff --git a/Completion/Builtins/_jobs b/Completion/Builtins/_jobs index 018883c61..8f6991de0 100644 --- a/Completion/Builtins/_jobs +++ b/Completion/Builtins/_jobs @@ -1,3 +1,3 @@ #defcomp fg jobs -complist -j -P '%' +compgen -j -P '%' diff --git a/Completion/Builtins/_kill b/Completion/Builtins/_kill index 50796d36f..c1afa78cb 100644 --- a/Completion/Builtins/_kill +++ b/Completion/Builtins/_kill @@ -3,9 +3,9 @@ local list if [[ -iprefix '-' ]]; then - complist -k "($signals[1,-3])" + compgen -k "($signals[1,-3])" else - complist -P '%' -j + compgen -P '%' -j list=("$(ps 2>/dev/null)") - complist -y '$list' -s '`ps 2>/dev/null | tail +2 | cut -c1-5`' + compgen -y '$list' -s '`ps 2>/dev/null | tail +2 | cut -c1-5`' fi diff --git a/Completion/Builtins/_limits b/Completion/Builtins/_limits index 35ccbe07e..8b0b41c71 100644 --- a/Completion/Builtins/_limits +++ b/Completion/Builtins/_limits @@ -1,3 +1,3 @@ #defcomp limit unlimit -complist -k "(${(j: :)${(f)$(limit)}%% *})" +compgen -k "(${(j: :)${(f)$(limit)}%% *})" diff --git a/Completion/Builtins/_sched b/Completion/Builtins/_sched index 1e8ae3445..62cdbb070 100644 --- a/Completion/Builtins/_sched +++ b/Completion/Builtins/_sched @@ -1,3 +1,3 @@ #defcomp sched -[[ -position 2 -1 ]] && _normal "$@" +[[ -position 3 -1 ]] && _normal diff --git a/Completion/Builtins/_set b/Completion/Builtins/_set index 5597025bc..959dac75d 100644 --- a/Completion/Builtins/_set +++ b/Completion/Builtins/_set @@ -1,7 +1,9 @@ #defcomp set -if [[ -mcurrent -1 [-+]o ]]; then - complist -o -elif [[ -current -1 -A ]]; then - complist -A +local prev="$words[CURRENT-1]" + +if [[ "$prev" = [-+]o ]]; then + compgen -o +elif [[ "$prev" = -A ]]; then + compgen -A fi diff --git a/Completion/Builtins/_setopt b/Completion/Builtins/_setopt index 4abb3ccee..98800152f 100644 --- a/Completion/Builtins/_setopt +++ b/Completion/Builtins/_setopt @@ -1,7 +1,8 @@ #defcomp setopt -local nm=$NMATCHES +local nm=$compstate[nmatches] -complist -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \ +compgen -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \ -s '$({ unsetopt kshoptionprint; unsetopt } 2>/dev/null)' -[[ -nmatches nm ]] && complist -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o +[[ compstate[nmatches] -eq nm ]] && + compgen -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o diff --git a/Completion/Builtins/_source b/Completion/Builtins/_source index aae2c7320..1bbbf15a4 100644 --- a/Completion/Builtins/_source +++ b/Completion/Builtins/_source @@ -1,7 +1,7 @@ #defcomp source -if [[ -position 2 -1 ]]; then - _normal "$@" +if [[ -position 3 -1 ]]; then + _normal else _files fi diff --git a/Completion/Builtins/_trap b/Completion/Builtins/_trap index 59e81c589..36ab1f1a8 100644 --- a/Completion/Builtins/_trap +++ b/Completion/Builtins/_trap @@ -1,7 +1,7 @@ #defcomp trap -if [[ -position 1 ]]; then - complist -c +if [[ CURRENT -eq 2 ]]; then + compgen -c else - complist -k signals + compgen -k signals fi diff --git a/Completion/Builtins/_unhash b/Completion/Builtins/_unhash index fe40c25a2..63d61c991 100644 --- a/Completion/Builtins/_unhash +++ b/Completion/Builtins/_unhash @@ -1,6 +1,8 @@ #defcomp unhash -[[ -mword 1 -*d* ]] && complist -n -[[ -mword 1 -*a* ]] && complist -a -[[ -mword 1 -*f* ]] && complist -F -[[ ! -mword 1 -* ]] && complist -m +local fl="$words[2]" + +[[ "$fl" = -*d* ]] && compgen -n +[[ "$fl" = -*a* ]] && compgen -a +[[ "$fl" = -*f* ]] && compgen -F +[[ "$fl" != -* ]] && compgen -m diff --git a/Completion/Builtins/_unsetopt b/Completion/Builtins/_unsetopt index 90d642b51..a5c85b1ef 100644 --- a/Completion/Builtins/_unsetopt +++ b/Completion/Builtins/_unsetopt @@ -1,7 +1,8 @@ #defcomp unsetopt -local nm=$NMATCHES +local nm=$compstate[nmatches] -complist -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \ +compgen -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \ -s '$({ unsetopt kshoptionprint; setopt } 2>/dev/null)' -[[ -nmatches nm ]] && complist -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o +[[ compstate[nmatches] -eq nm ]] && + compgen -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o diff --git a/Completion/Builtins/_vars_eq b/Completion/Builtins/_vars_eq index fcbb0148c..9488cb7f9 100644 --- a/Completion/Builtins/_vars_eq +++ b/Completion/Builtins/_vars_eq @@ -1,3 +1,3 @@ #defcomp declare export integer local readonly typeset -complist -v -q -S '=' +compgen -v -q -S '=' diff --git a/Completion/Builtins/_wait b/Completion/Builtins/_wait index 29a7f6002..6e3a4c3c9 100644 --- a/Completion/Builtins/_wait +++ b/Completion/Builtins/_wait @@ -2,6 +2,6 @@ local list -complist -P '%' -j +compgen -P '%' -j list=("$(ps 2>/dev/null)") -complist -y '$list' -s '`ps 2>/dev/null | tail +2 | cut -c1-5`' +compgen -y '$list' -s '`ps 2>/dev/null | tail +2 | cut -c1-5`' diff --git a/Completion/Builtins/_which b/Completion/Builtins/_which index 324256e3d..9248f9c9f 100644 --- a/Completion/Builtins/_which +++ b/Completion/Builtins/_which @@ -1,3 +1,3 @@ #defcomp which whence where type -complist -caF +compgen -caF diff --git a/Completion/Builtins/_zftp b/Completion/Builtins/_zftp index 9be9c94db..e93021acf 100644 --- a/Completion/Builtins/_zftp +++ b/Completion/Builtins/_zftp @@ -9,28 +9,28 @@ _compskip=1 local subcom -if [[ $COMMAND = zftp ]]; then +if [[ $words[1] = zftp ]]; then if [[ $CURRENT -eq 1 ]]; then - compadd -m open params user login type ascii binary mode put \ + compadd open params user login type ascii binary mode put \ putat get getat append appendat ls dir local remote mkdir rmdir return fi - subcom=$1 + subcom=$words[2] else - subcom=$COMMAND + subcom=$words[1] fi case $subcom in *(cd|ls|dir)) # complete remote directories; we could be smarter about hiding prefixes zfcd_match $PREFIX $SUFFIX - (( $#reply )) && compadd -m -S/ -q $reply + (( $#reply )) && compadd -S/ -q - $reply ;; *(get(|at)|gcp|delete|remote)) # complete remote files zfget_match $PREFIX $SUFFIX - (( $#reply )) && compadd -F fignore -m $reply + (( $#reply )) && compadd -F fignore - $reply ;; *(put(|at)|pcp)) @@ -40,7 +40,7 @@ case $subcom in *(open|anon|params)) # complete hosts: should do cleverer stuff with user names - complist -k hosts + compgen -k hosts ;; *) diff --git a/Completion/Builtins/_zle b/Completion/Builtins/_zle index bb1102e74..0a9ad0a9e 100644 --- a/Completion/Builtins/_zle +++ b/Completion/Builtins/_zle @@ -1,7 +1,7 @@ #defcomp zle -if [[ -word 1 -N && -position 3 ]]; then - complist -F +if [[ "$words[2]" = -N && CURRENT -eq 3 ]]; then + compgen -F else - complist -b + compgen -b fi diff --git a/Completion/Builtins/_zmodload b/Completion/Builtins/_zmodload index 112acb57c..4259adf06 100644 --- a/Completion/Builtins/_zmodload +++ b/Completion/Builtins/_zmodload @@ -1,9 +1,11 @@ #defcomp zmodload -if [[ -mword 1 -*(a*u|u*a)* || -mword 1 -*a* && -position 3 -1 ]]; then - complist -B -elif [[ -mword 1 -*u* ]]; then - complist -s '$(zmodload)' +local fl="$words[2]" + +if [[ "$fl" = -*(a*u|u*a)* || "$fl" = -*a* && -position 4 -1 ]]; then + compgen -B +elif [[ "$fl" = -*u* ]]; then + compgen -s '$(zmodload)' else - complist -s '${^module_path}/*(N:t:r)' + compgen -s '${^module_path}/*(N:t:r)' fi diff --git a/Completion/Commands/_correct_filename b/Completion/Commands/_correct_filename index edf1c65c2..582555587 100644 --- a/Completion/Commands/_correct_filename +++ b/Completion/Commands/_correct_filename @@ -17,7 +17,8 @@ integer approx max_approx=6 if [[ -e "$file" ]]; then if [[ -n $WIDGET ]]; then - compadd "$file" + compadd -U -i "$IPREFIX" "$file" + [[ -n "$compstate[insert]" ]] && compstate[insert]=menu else print "$file" fi @@ -31,7 +32,8 @@ done (( $#trylist )) || return 1 if [[ -n $WIDGET ]]; then - compadd -U "${trylist[@]}" + compadd -U -i "$IPREFIX" -U "${trylist[@]}" + [[ -n "$compstate[insert]" ]] && compstate[insert]=menu else print "${trylist[@]}" fi diff --git a/Completion/Commands/_most_recent_file b/Completion/Commands/_most_recent_file index ff5645de5..df35ecba7 100644 --- a/Completion/Commands/_most_recent_file +++ b/Completion/Commands/_most_recent_file @@ -1,4 +1,22 @@ #defkeycomp complete-word \C-xm -local file -file=($~PREFIX*$~SUFFIX(om[1]N)) -(( $#file )) && compadd -f $file + +# 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 +# file ending in .txt +# +# With a prefix argument, select the Nth most recent matching file; +# negative arguments work in the opposite direction, so for example +# `Esc - \C-x m' gets you the oldest file. +# +# (`Most recent' means most recently modified.) + +local file tilde etilde +if [[ $PREFIX = \~*/* ]]; then + tilde=${PREFIX%%/*} + etilde=${~tilde} + file=($~PREFIX*$~SUFFIX(om[$NUMERIC]N)) + file=(${file/#$etilde/$tilde}) +else + file=($~PREFIX*$~SUFFIX(om[$NUMERIC]N)) +fi +(( $#file )) && compadd -U -f -Q $file diff --git a/Completion/Core/_comp_parts b/Completion/Core/_comp_parts index 7c24fd19d..d58669f29 100644 --- a/Completion/Core/_comp_parts +++ b/Completion/Core/_comp_parts @@ -21,11 +21,11 @@ # `_match_test' and `_match_pattern' for this. local str arr sep test testarr tmparr prefix suffixes matchers autosuffix -local matchflags opt group expl +local matchflags opt group expl nm=$compstate[nmatches] # Test if we should use this function for the global matcher in use. -_match_test _comp_parts || return +_match_test _comp_parts || return 1 # Get the options. @@ -42,6 +42,7 @@ shift OPTIND-1 # Get the string from the line. str="$PREFIX$SUFFIX" +[[ -o globcomplete ]] && str="$str:q" prefix="" # Walk through the arguments to find the longest unambiguous prefix. @@ -63,12 +64,14 @@ while [[ $# -gt 1 ]]; do test="${str%%${sep}*}" matchflags="" _match_pattern _comp_parts test matchflags + [[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)" test="${matchflags}${test}" testarr=( "${(@M)${(@P)arr}:#${~test}*}" ) + testarr=( "${(@)testarr:#}" ) # If there are no matches we give up. If there is more than one # match, this is the part we will complete. - (( $#testarr )) || return + (( $#testarr )) || return 1 [[ $#testarr -gt 1 ]] && break # Only one match, add it to the prefix and skip over it in `str', @@ -89,11 +92,13 @@ if [[ $# -le 1 || "$str" != *${2}* ]]; then matchflags="" test="$str" _match_pattern _comp_parts test matchflags + [[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)" test="${matchflags}${test}" testarr=( "${(@M)${(@P)arr}:#${~test}*}" ) + testarr=( "${(@)testarr:#}" ) fi -[[ $#testarr -eq 0 || ${#testarr[1]} -eq 0 ]] && return +[[ $#testarr -eq 0 || ${#testarr[1]} -eq 0 ]] && return 1 # Now we build the suffixes to give to the completion code. shift @@ -114,6 +119,7 @@ while [[ $# -gt 0 && "$str" == *${1}* ]]; do fi matchflags="" _match_pattern _comp_parts test matchflags + [[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)" test="${matchflags}${test}" # We incrementally add suffixes by appending to them the seperators @@ -124,7 +130,9 @@ while [[ $# -gt 0 && "$str" == *${1}* ]]; do tmparr=( ${=arr[2,-2]} ) arr=tmparr fi - suffixes=("${^suffixes[@]}${1}${(@M)^${(@P)arr}:#${~test}*}") + tmparr=( "${(@M)${(@P)arr}:#${~test}*}" ) + tmparr=( "${(@)testarr:#}" ) + 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 @@ -143,5 +151,10 @@ done # Add the matches for each of the suffixes. for i in "$suffixes[@]"; do - compadd "$group[@]" "$expl[@]" "$matchers[@]" "$autosuffix[@]" -p "$prefix" -s "$i" - "$testarr[@]" + compadd -U "$group[@]" "$expl[@]" "$matchers[@]" "$autosuffix[@]" \ + -i "$IPREFIX" -p "$prefix" -s "$i" - "$testarr[@]" done + +# This sets the return value to indicate that we added matches (or not). + +[[ nm -ne compstate[nmatches] ]] diff --git a/Completion/Core/_compalso b/Completion/Core/_compalso index 23a40e2d0..6ff6cf0bf 100644 --- a/Completion/Core/_compalso +++ b/Completion/Core/_compalso @@ -4,10 +4,10 @@ # 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. +# `_compalso -math-' to get the completions that would be generated for a +# mathematical context. local tmp tmp="$_comps[$1]" -[[ -z "$tmp" ]] || "$tmp" "$@" +[[ -z "$tmp" ]] || "$tmp" diff --git a/Completion/Core/_files b/Completion/Core/_files index d2cce35e7..471824bfe 100644 --- a/Completion/Core/_files +++ b/Completion/Core/_files @@ -3,11 +3,12 @@ # Utility function for completing files of a given type or any file. # In many cases you will want to call this one instead of _path_files(). -local nm=$NMATCHES +local nm=$compstate[nmatches] ret _path_files "$@" +ret=$? -if [[ $# -ne 0 && -nmatches nm ]]; then +if [[ $# -ne 0 && compstate[nmatches] -eq nm ]]; then local opt opts # We didn't get any matches for those types of files described by @@ -23,4 +24,6 @@ if [[ $# -ne 0 && -nmatches nm ]]; then done _path_files "$opts[@]" +else + return $ret fi diff --git a/Completion/Core/_main_complete b/Completion/Core/_main_complete index c7f5a5a96..34c5a3d3c 100644 --- a/Completion/Core/_main_complete +++ b/Completion/Core/_main_complete @@ -2,47 +2,198 @@ # The main loop of the completion code. This is what is called when # completion is attempted from the command line. -# The completion code gives us the special variables and the arguments -# from the command line are given as positional parameters. +# +# This code will automatically try to correct the string on the +# line based on the strings generated for the context if the +# parameter `COMPCORRECT' is set and normal completion didn't yield +# any matches. These corrected strings will be shown in a list and +# one can cycle through them as in a menucompletion. To use this +# feature, `COMPCORRECT' should be set to a number, specifying the +# maximum number of errors that should be accepted. If the string also +# contains a `n' or `N', the code will use the numeric argument as the +# maximum number of errors if a numeric argument was given. If no +# numeric argument was given, the number from the value of +# `COMPCORRECT' will be used. E.g. with `COMPCORRECT=2n' two errors +# will be accepted, but if the user gives another number with the +# numeric argument, this will be prefered. Also, with `COMPCORRECT=0n', +# normally no automatic correction will be tried, but if a numeric +# argument is given, automatic correction will be used. Once the +# number of errors to accept is determined, the code will repeatedly +# try to generate matches by allowing one error, two errors, and so +# on. +# If the parameter `CCORIG' is set (independent of the value), the +# line will first be left unchanged and consecutive TABs cycle through +# the list. +# When using automatic correction, one can also set the parameter +# `CCPROMPT' to a string that will be shown when multiple +# correction results are displayed and the code starts cycling +# through them (this string is used with the `-X' option and thus may +# contain the control sequences `%n', `%B',...). -local comp name +local comp name _comp_correct comax setopt localoptions nullglob rcexpandparam globdots -unsetopt markdirs globsubst shwordsplit nounset - -# An entry for `-first-' is the replacement for `compctl -T' -# Completion functions may set `_compskip' to any value to make the -# main loops stop calling other completion functions. - -comp="$_comps[-first-]" -if [[ ! -z "$comp" ]]; then - "$comp" "$@" - if (( $+_compskip )); then - unset _compskip - return - fi +unsetopt markdirs globsubst shwordsplit nounset ksharrays + +# Special completion contexts after `~' and `='. + +if [[ -iprefix '=' ]]; then + compstate[context]=equal +elif [[ "$PREFIX$SUFFIX" != */* && -iprefix '~' ]]; then + compstate[context]=tilde fi -# For arguments we use the `_normal function. +# This is not an endless loop. -if [[ $CONTEXT == argument || $CONTEXT == command ]]; then - _normal "$@" -else - # Let's see if we have a special completion definition for the other - # possible contexts. +while true; do - comp='' + # An entry for `-first-' is the replacement for `compctl -T' + # Completion functions may set `_compskip' to any value to make the + # main loops stop calling other completion functions. - case $CONTEXT in - redirect) comp="$_comps[-redirect-]";; - math) comp="$_comps[-math-]";; - subscript) comp="$_comps[-subscript-]";; - value) comp="$_comps[-value-]";; - condition) comp="$_comps[-condition-]";; - esac + comp="$_comps[-first-]" + if [[ ! -z "$comp" ]]; then + "$comp" + if (( $+_compskip )); then + unset _compskip + return + fi + fi - # If not, we use default completion, if any. + # For arguments and command names we use the `_normal' function. - [[ -z "$comp" ]] && comp="$_comps[-default-]" - [[ -z "$comp" ]] || "$comp" "$@" -fi + if [[ "$compstate[context]" = command ]]; then + _normal + else + # Let's see if we have a special completion definition for the other + # possible contexts. + + comp='' + + case $compstate[context] in + equal) comp="$_comps[-equal-]";; + tilde) comp="$_comps[-tilde-]";; + redirect) comp="$_comps[-redirect-]";; + math) comp="$_comps[-math-]";; + subscript) comp="$_comps[-subscript-]";; + value) comp="$_comps[-value-]";; + array_value) comp="$_comps[-array-value-]";; + condition) comp="$_comps[-condition-]";; + parameter) comp="$_comps[-parameter-]";; + brace_parameter) comp="$_comps[-brace-parameter-]";; + esac + + # If not, we use default completion, if any. + + [[ -z "$comp" ]] && comp="$_comps[-default-]" + [[ -z "$comp" ]] || "$comp" + fi + + # Use automatic correction? + + if (( $+COMPCORRECT )); then + + # Do we have matches? + if (( compstate[nmatches] )); then + + # Yes, were they added using correction? (More than one match?) + + if [[ -n "$_comp_correct" && compstate[nmatches] -gt 1 ]]; then + + # If we got more than one string from correction, we add the + # original string as a possible match, let it not be shown in + # the list, and probably display the `CCPROMPT'. + + (( $+CCORIG )) && builtin compadd -nQ - "$PREFIX$SUFFIX" + + # If you always want to see the list of possible corrections, + # set `compstate[list]=list' here. + fi + # Since we have matches, we don't want to try again. + break + fi + + # No matches, so let's see if we already tried correction. + + if [[ -n "$_comp_correct" ]]; then + + # Yes, give up if we reached the maximum number of tries, + # otherwise increment our counter. + + [[ _comp_correct -eq comax ]] && break + (( _comp_correct++ )) + + elif [[ compstate[matcher] -eq compstate[total_matchers] ]]; then + + # No matches and no correction tried yet, but we just tried the + # last global match specification, so let's see if we should use + # correction now. First, get the maximum number of errors. + + if [[ "$COMPCORRECT" = *[nN]* && NUMERIC -ne 1 ]]; then + # Prefer the numeric argument if that has a sensible value. + comax="$NUMERIC" + else + comax="${COMPCORRECT//[^0-9]}" + fi + # If the number of errors to accept is to small, give up. + + [[ "$comax" -lt 1 ]] && break + + # Otherwise temporarily define functions to use instead of + # the builtins that add matches. This is used to be able + # to stick the `(#a...)' into the right place (after an + # ignored prefix). + + compadd() { + if [[ "$PREFIX" = \~*/* ]]; then + PREFIX="${PREFIX%%/*}/(#a${_comp_correct})${PREFIX#*/}" + else + PREFIX="(#a${_comp_correct})$PREFIX" + fi + if (( $+CCPROMPT )); then + builtin compadd -X "$CCPROMPT" -J _correct "$@" + else + builtin compadd -J _correct "$@" + fi + } + compgen() { + if [[ "$PREFIX" = \~*/* ]]; then + PREFIX="${PREFIX%%/*}/(#a${_comp_correct})${PREFIX#*/}" + else + PREFIX="(#a${_comp_correct})$PREFIX" + fi + if (( $+CCPROMPT )); then + builtin compgen "$@" -X "$CCPROMPT" -J _correct + else + builtin compgen "$@" -J _correct + fi + } + # Now initialise our counter. We also set `compstate[matcher]' + # to `-1'. This allows completion functions to use the simple + # `[[ compstate[matcher] -gt 1 ]] && return' to avoid being + # called for multiple global match specs and still be called + # again when correction is done. Also, this makes it easy to + # test if correction is attempted since `compstate[matcher]' + # will never be set to a negative value by the completion code. + + _comp_correct=1 + compstate[matcher]=-1 + + # We also need to set `extendedglob' and to make the completion + # code behave as if globcomplete were set. + + setopt extendedglob + compstate[pattern_match]=yes + else + # We are still trying global match specifications... + break + fi + else + # No automatic correction to try, just give up. + break + fi +done + +# If we added wrapper functions, remove them. + +[[ -n "$_comp_correct" ]] && unfunction compadd compgen diff --git a/Completion/Core/_multi_parts b/Completion/Core/_multi_parts new file mode 100644 index 000000000..1f51d2f6d --- /dev/null +++ b/Completion/Core/_multi_parts @@ -0,0 +1,201 @@ +#autoload + +# This gets two arguments, a separator (which should be only one +# character) and an array. As usual, the array may be given by it's +# name or literal as in `(foo bar baz)' (words separated by spaces in +# parentheses). +# 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 + +_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] + +# Get the options. + +group=() +expl=() +while getopts "J:V:X:" opt; do + case "$opt" in + [JV]) group=("-$opt" "$OPTARG");; + X) expl=(-X "$OPTARG");; + esac +done +shift OPTIND-1 + +# Get the arguments, first the separator, then the array. The array is +# stored in `matches'. Further on this array will always contain those +# words from the original array that still match everything we have +# tried to match while we walk through the string from the line. + +sep="$1" +if [[ "${2[1]}" = '(' ]]; then + matches=( ${2[2,-2]} ) +else + matches=( "${(@P)2}" ) +fi + +# Now build the pattern from what we have on the line. We also save +# the original string in `orig'. The `eval' is used to replace our +# separator character by `*'. + +if [[ -o globcomplete ]]; then + patstr="${PREFIX}*${SUFFIX}*" +else + patstr="${PREFIX:q}*${SUFFIX:q}*" +fi +orig="${PREFIX}${SUFFIX}" + +matchflags="" +_match_pattern _path_files patstr matchflags +[[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)" + +patstr="${${patstr//$sep/*$sep}//\*##/*}" +#eval patstr\="\$patstr:gs-${sep}-\*${sep}-:gs/\*\*/\*/" + +# 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. + +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'. + + pat="${${${patstr#*${sep}}%${sep}*}//\*/[^${sep}]#}${patstr##*${sep}}" + tmp1=( "${(@M)matches:#${~matchflags}${orig%%${sep}*}${sep}${~pat}}" ) + + # If there are no words matching the exact substring, stop. + + (( $#tmp1 )) || break + + # Otherwise add the part to the prefix, remove it from the matches + # (which will also remove all words not matching the string at all), + # and set `patstr' and `orig' to the next component. + + pref="$pref${orig%%${sep}*}${sep}" + matches=( "${(@)${(@)matches#${orig%%${sep}*}${sep}}:#}" ) + 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 +tmp1=( "${(@M)matches:#${~matchflags}${~pat}}" ) + +if (( $#tmp1 )); then + + # There are words that are matched, put them int `matches' and then + # move all unambiguous components from the beginning into `pref'. + + matches=( "$tmp1[@]" ) + while [[ "$matches[1]" = *${sep}* ]]; do + + # 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="${matches[1]%%${sep}*}${sep}" + tmp2=( "${(@)matches:#${tmp1}*}" ) + (( $#tmp2 )) && break + + # All matches have the same prefix, but it into `pref' and remove + # it from the matches. + + pref="$pref$tmp1" + matches=( "${(@)${(@)matches#$tmp1}:#}" ) + + if [[ "$orig" = *${sep}* ]]; then + orig="${orig#*${sep}}" + else + orig='' + fi + done + + # 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" -S '' - "${pref}${orig}" + elif [[ $compstate[insert] = *menu ]]; then + for i in "$matches[@]" ; do + if [[ "$i" = *${sep}* ]]; then + compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" \ + -p "$pref" -qS "$sep" - "${i%%${sep}*}" + else + compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" \ + -p "$pref" - "${i%%${sep}*}" + fi + done + else + for i in "$matches[@]" ; do + if [[ "$i" = *${sep}* ]]; then + compadd -U -i "$IPREFIX" -p "$pref" -s "${sep}${i#*${sep}}" \ + "$group[@]" "$expl[@]" -M "r:|${sep}=*" - "${i%%${sep}*}" + else + compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -p "$pref" - "$i" + 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. + + tmp1=( "${(@M)matches:#${~matchflags}${~patstr%%${sep}*}${sep}*}" ) + (( $#tmp1 )) || break + + # Then we check if there are words that have a different prefix. + + tmp2=( "${(@)tmp1:#${tmp1[1]%%${sep}*}${sep}*}" ) + if (( $#tmp2 )); then + + # 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" -p "$pref" \ + -s "${sep}${orig#*${sep}}" - "${(@)matches%%${sep}*}" + return 0 + fi + + # All words have the same prefix, so add it to `pref' again and + # try the next component. + + pref="$pref${tmp1[1]%%${sep}*}${sep}" + matches=( "${(@)matches#${tmp1[1]%%${sep}*}${sep}}" ) + orig="${orig#*${sep}}" + patstr="${patstr#*${sep}}" + done + + # Finally, add the unambiguous prefix and the rest of the string + # from the line. + + compadd -U "$group[@]" "$expl[@]" -S '' -i "$IPREFIX" -p "$pref" - "$orig" +fi + +# This sets the return value to indicate that we added matches (or not). + +[[ nm -ne compstate[nmatches] ]] diff --git a/Completion/Core/_normal b/Completion/Core/_normal index 19da6d79b..f56849194 100644 --- a/Completion/Core/_normal +++ b/Completion/Core/_normal @@ -1,24 +1,25 @@ #autoload -local comp cmd1 cmd2 pat val name +local comp command cmd1 cmd2 pat val name i ret # Completing in command position? If not we set up `cmd1' and `cmd2' as # two strings we have search in the completion definition arrays (e.g. # a path and the last path name component). -if [[ $CONTEXT == command ]]; then +command="$words[1]" +if [[ CURRENT -eq 1 ]]; then comp="$_comps[-command-]" - [[ -z "$comp" ]] || "$comp" "$@" + [[ -z "$comp" ]] || "$comp" return -elif [[ "$COMMAND[1]" == '=' ]]; then - eval cmd1\=$COMMAND - cmd2="$COMMAND[2,-1]" -elif [[ "$COMMAND" == */* ]]; then - cmd1="$COMMAND" - cmd2="${COMMAND:t}" +elif [[ "$command[1]" == '=' ]]; then + eval cmd1\=$command + cmd2="$command[2,-1]" +elif [[ "$command" == */* ]]; then + cmd1="$command" + cmd2="${command:t}" else - cmd1="$COMMAND" - eval cmd2=$(whence -p $COMMAND) + cmd1="$command" + eval cmd2=$(whence -p $command) fi # See if there are any matching pattern completions. @@ -27,10 +28,11 @@ for i in "$_patcomps[@]"; do pat="${i% *}" val="${i#* }" if [[ "$cmd1" == $~pat || "$cmd2" == $~pat ]]; then - "$val" "$@" + "$val" + ret=$? if (( $+_compskip )); then unset _compskip - return + return $ret fi fi done @@ -51,4 +53,4 @@ if [[ -z "$comp" ]]; then name=-default- comp="$_comps[-default-]" fi -[[ -z "$comp" ]] || "$comp" "$@" +[[ -z "$comp" ]] || "$comp" diff --git a/Completion/Core/_path_files b/Completion/Core/_path_files index 83b6e8a09..3c03c0c61 100644 --- a/Completion/Core/_path_files +++ b/Completion/Core/_path_files @@ -3,7 +3,7 @@ # Utility function for in-path completion. # Supported arguments are: `-f', `-/', `-g ', `-J ', # `-V ', `-W paths', `-X explanation', and `-F '. All but -# the last have the same syntax and meaning as for `complist'. The +# the last have the same syntax and meaning as for `compgen'. 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 @@ -14,13 +14,13 @@ # First see if we should generate matches for the global matcher in use. -_match_test _path_files || return +_match_test _path_files || return 1 # Yes, so... local nm prepaths 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 +local addpfx addsfx expl orig ostr nm=$compstate[nmatches] setopt localoptions nullglob rcexpandparam globdots extendedglob unsetopt markdirs globsubst shwordsplit nounset @@ -91,14 +91,14 @@ fi # str holds the whole string from the command line with a `*' between # the prefix and the suffix. -str="${PREFIX:q}*${SUFFIX:q}" - -# If the string began with a `~', the quoting turned this into `\~', -# remove the slash. - -[[ "$str" = \\\~* ]] && str="$str[2,-1]" +if [[ -o globcomplete ]]; then + str="${PREFIX}*${SUFFIX}" +else + str="${PREFIX:q}*${SUFFIX:q}" +fi +orig="${PREFIX}${SUFFIX}" -# We will first try normal completion called with `complist', but only if we +# We will first try normal completion called with `compgen', but only if we # weren't given a `-F' option. if (( ! $#ignore )); then @@ -112,18 +112,18 @@ if (( ! $#ignore )); then tmp1=(-W "( $prepaths )") fi - # Now call complist. + # Now call compgen. - nm=$NMATCHES + nm=$compstate[nmatches] if [[ -z "$gopt" ]]; then - complist "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" "$tmp1[@]" $sopt + compgen "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" "$tmp1[@]" $sopt else - complist "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" "$tmp1[@]" $sopt -g "$pats" + compgen "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" "$tmp1[@]" $sopt -g "$pats" fi # If this generated any matches, we don't want to do in-path completion. - [[ -nmatches nm ]] || return + [[ compstate[nmatches] -eq nm ]] || return 0 # No `-F' option, so we want to use `fignore'. @@ -142,14 +142,16 @@ if [[ "$str[1]" = \~ ]]; then linepath="${str%%/*}/" eval realpath\=$linepath + [[ "$realpath" = "$linepath" ]] && return 1 str="${str#*/}" + orig="${orig#*/}" donepath='' prepaths=( '' ) else # If the string does not start with a `~' we don't remove a prefix from the # string. - liniepath='' + linepath='' realpath='' if [[ "$str[1]" = / ]]; then @@ -158,6 +160,7 @@ else # Also, we don't use the paths from `-W'. str="$str[2,-1]" + orig="$orig[2,-1]" donepath='/' prepaths=( '' ) else @@ -169,28 +172,31 @@ else fi 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 `str' and added -# to `donepath'. - -while [[ "$str" = */* ]] do - [[ -e "$realpath$donepath${str%%/*}" ]] || break - donepath="$donepath${str%%/*}/" - str="${str#*/}" -done - # Now build the glob pattern by calling `_match_pattern'. patstr="$str" matchflags="" _match_pattern _path_files patstr 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/**/*/" +patstr="$patstr:gs-/-*/-:gs/*.*./../:gs-/*.-/.-:gs/**/*/:gs-.*/-./-" + +# 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'. + +while [[ "$orig" = */* ]] do + tmp1=( ${~matchflags}$realpath$donepath${orig%%/*}/${~patstr#*/}$^pats ) + [[ $#tmp1 -gt 0 && -e "$realpath$donepath${orig%%/*}" ]] || break + donepath="$donepath${orig%%/*}/" + orig="${orig#*/}" + patstr="${patstr#*/}" +done # 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' @@ -199,6 +205,9 @@ patstr="$patstr:gs-/-*/-:gs/*.*.//:gs-/*.-/.-:gs/**/*/" for prepath in "$prepaths[@]"; do str="$patstr" testpath="$donepath" + ostr="$orig" + + [[ -z "$prepath" || "$prepath[-1]" = / ]] || prepath="${prepath}/" # The second loop tests the components of the path in `str' to get the # possible matches. @@ -235,16 +244,20 @@ for prepath in "$prepaths[@]"; do # the suffixes we just built are used to produce possible matches # via globbing. - for i in $tmp1; do + for i in "$tmp1[@]" ; do tmp2=( ${~i}/${~matchflags}${~suffixes} ) [[ $#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 give up and - # continue with the next `-W' path. + # 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 + compadd -QU "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" \ + -i "$IPREFIX" -p "${linepath:q}${testpath:q}" -S "/${ostr#*/}" \ + -W "$tmp1" -f "$ignore[@]" - "${(@)tmp1:q}" continue 2 elif [[ $#collect -ne 1 ]]; then # If we have more than one possible match, this means that the @@ -269,9 +282,17 @@ for prepath in "$prepaths[@]"; do # these are file names and that `fignore' should be used as usual # (the `-f' and `-F' options). - for i in $collect; do - compadd "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" -p "$linepath$testpath" -W "$tmp1" -s "/${i#*/}" -f "$ignore[@]" - "${i%%/*}" - done + if [[ $compstate[insert] = *menu ]]; then + compadd -QU "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" \ + -i "$IPREFIX" -p "${linepath:q}${testpath:q}" -S "/${ostr#*/}" \ + -W "$tmp1" -f "$ignore[@]" - "${(@)${(@)collect%%/*}:q}" + else + for i in $collect; do + compadd -U "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" \ + -i "$IPREFIX" -p "$linepath$testpath" -s "/${i#*/}" \ + -M 'r:|/=*' -W "$tmp1" -f "$ignore[@]" - "${i%%/*}" + done + fi # We have just finished handling all the matches from above, so we # can continue with the next `-W' path. @@ -291,6 +312,7 @@ for prepath in "$prepaths[@]"; do tmp1="$tmp1[1]" testpath="$testpath${tmp1##*/}/" str="$rest" + ostr="${ostr#*/}" done # We are here if all pathname components except the last one (which is still @@ -302,10 +324,24 @@ for prepath in "$prepaths[@]"; do suffixes=( $str$^pats ) suffixes=( "${(@)suffixes:gs.**.*.}" ) tmp2=( ${~tmp1}${~matchflags}${~suffixes} ) - if [[ $#tmp2 -eq 0 && "$sopt" = */* ]]; then + if [[ $#tmp2 -eq 0 ]]; then + # No match, insert the expanded path and add the original tail. + [[ "$testpath[-1]" = / ]] && testpath="$testpath[1,-2]" - compadd "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" -f - "$linepath$testpath" + [[ -n "$ostr" && -n "$linepath$testpath" ]] && ostr="/$ostr" + + # But only if something changed. + [[ "$linepath$testpath$ostr" = "$PREFIX$SUFFIX" ]] && return 1 + + compadd -QU -S '' "$group[@]" "$expl[@]" \ + -i "$IPREFIX" -f - "${linepath:q}${testpath:q}$ostr" else - compadd "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" -p "$linepath$testpath" -W "$prepath$realpath$testpath" -f "$ignore[@]" - ${(@)tmp2#$tmp1} + compadd -U "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" \ + -i "$IPREFIX" -p "$linepath$testpath" -f "$ignore[@]" \ + -W "$prepath$realpath$testpath" - "${(@)tmp2#$tmp1}" fi done + +# This sets the return value to indicate that we added matches (or not). + +[[ nm -ne compstate[nmatches] ]] diff --git a/Completion/README b/Completion/README index ac2accfca..43ffcbcc2 100644 --- a/Completion/README +++ b/Completion/README @@ -11,14 +11,15 @@ loading much faster. For example, [[ -f ~/completion/compinit ]] && . ~/completion/compinit -d This will rebind any keys which do completion to use the new system. For more detailed instructions, including how to add new completions, see -the top of Core/compinit . +the top of Core/compinit. The subdirectories contain: Core: The basic functions and files to be sourced. You will certainly need - these, and will most likely not feel like altering them (or, in some - cases, even reading them, unless you are a shell wizard). The files are: + these, and will most likely not want to alter them --- if you do, it + would probably help to give your version a different name. The files + are: compinit As already described, this is not a function, but is sourced once (with the `source' or `.' commands) to set up the completion system. @@ -29,6 +30,9 @@ Core: _comp_parts Utility used for completing words with multiple separate parts, such as `@' + _multi_parts + Utility for completion parts of words given a separator character and + a list of words. _compalso Utility for calling a function to add additional completions to an already existing set. @@ -46,7 +50,7 @@ Core: it is wider than just command+argument.) _path_files The function usually called to complete filenames and directories. It - replaces the standard -f and -/ options for the basic completion + replaces the standard -f, -g and -/ options for the basic completion commands: it can do various extra tricks, such as expanding a whole path at once, e.g. F/C/C/_p -> Functions/Completion/Core/_path_files Base: @@ -65,22 +69,29 @@ Base: as you wish. _match_pattern _match_test - These are used by Base/_path_files (and hence also Base/_files) for - file completion with control over matching (whether to complete - case-insensitively, or to allow insertion before `.', etc.) See - _match_test for instructions. Note _path_files expects these files - to be present. + These are used by Base/_path_files (and hence also Base/_files) + and Base/_comp_parts for file completion with control over + matching (whether to complete case-insensitively, or to allow + insertion before `.', etc.) See _match_test for instructions. + Note _path_files expects these files to be present. _precommand Allows completion when the first word on the line has to be ignored, for example `noglob ...' should ignore the noglob and just complete as if it wasn't there. Add other such commands to the top line. _redirect - Completes after `<' or `<': this version calls _files. + Completes after `<' or `>': this version calls _files. _subscript For completion in subscripts of parameters, e.g $foo[...]. _vars Completion for commands which need variables (so this could also be in the Builtins directory), but also in math environments such as ((...)). + _tilde + Completion after `~', defaults to user names and named directories. + _equal + Completion after `=', normally command and alias names are used. + _parameter + _brace_parameter + For completion inside parameter expansions ($... and ${...). Builtins: Define completions for various shell builtins. The top line of each file says which builtins they apply to; in many cases you can guess from the diff --git a/Completion/User/_a2ps b/Completion/User/_a2ps index 9aa9d3d99..600b58872 100644 --- a/Completion/User/_a2ps +++ b/Completion/User/_a2ps @@ -1,22 +1,22 @@ #defcomp a2ps -if [[ -prefix -- ]]; then +if [[ "$PREFIX[1,2]" = -- ]]; then _comp_parts '(--borders --compact --truncate-lines --interpret --print-anyway --delegate)' '=' '(yes no)' _comp_parts '(--major)' '=' '(rows columns)' _comp_parts '(--end-of-line)' '=' '(r n nr rn any)' - complist -S= -k '(--medium --columns --rows --line-numbers + compgen -S= -k '(--medium --columns --rows --line-numbers --font-size --lines-per-page --chars-per-line --tabsize --non-printable-format --encoding --title --stdin --prologue --highlight-level --strip-level --output --version-control --suffix --printer --copies --sides --page-prefeed --no-page-prefeed)' - complist -qS= -k '(--margin --header --underlay --left-title + compgen -qS= -k '(--margin --header --underlay --left-title --right-title --left-footer --footer --right-footer --pages --pretty-print)' - complist -k '(--landscape --portrait --catman --no-header)' + compgen -k '(--landscape --portrait --catman --no-header)' else _files -F fignore -g "*~*.ps" fi diff --git a/Completion/User/_configure b/Completion/User/_configure index de8d5fba5..050701fac 100644 --- a/Completion/User/_configure +++ b/Completion/User/_configure @@ -1,12 +1,35 @@ #defcomp configure +setopt localoptions extendedglob + if [[ $PREFIX = *=* ]]; then # Complete filenames after e.g. --prefix= IPREFIX=${PREFIX%%=*}= PREFIX=${PREFIX#*=} - complist -f + compgen -f else # Generate a list of options from configure --help - complist -s '$($COMMAND --help | - sed -n -e '\''s/^ *\(--[-a-z0-9]*\)[ =,].*$/\1/p'\'')' + local -a pars + local i + pars=($($words[1] --help | awk '$1 ~ /--[a-z]*.*/ {print $1}')) + for i in $pars + do + case $i in + (--(((en|dis)able-FEATURE)|(with(out|)-PACKAGE))*) + : Skip standard help output + ;; + --enable) + : Skip standard help output + ;; + --*\[=* ) + compadd -M 'r:|-=* r:|=*' -q -S = -- ${i%%\[=*} + ;; + --*=* ) + compadd -M 'r:|-=* r:|=*' -S = -- ${i%%=*} + ;; + * ) + compadd -M 'r:|-=* r:|=*' -- $i + ;; + esac + done fi diff --git a/Completion/User/_dd b/Completion/User/_dd index 2458541ea..86a47b1ab 100644 --- a/Completion/User/_dd +++ b/Completion/User/_dd @@ -4,10 +4,10 @@ if [[ -iprefix conv= ]]; then # If there's a comma present, ignore up to the last one. The # test alone will have that effect. [[ -string , ]] - complist -S, -q \ + compgen -S, -q \ -k '(ascii ebcdic ibm block unblock lcase ucase swab noerror sync)' elif [[ -iprefix 'if=' || -iprefix 'of=' ]]; then _files else - complist -S '=' -k '(if of ibs obs bs cbs skip files seek count conv)' + compgen -S '=' -k '(if of ibs obs bs cbs skip files seek count conv)' fi diff --git a/Completion/User/_find b/Completion/User/_find index ca4f79908..8fcdafb83 100644 --- a/Completion/User/_find +++ b/Completion/User/_find @@ -1,21 +1,23 @@ #defcomp find +local prev="$words[CURRENT-1]" + if [[ -mbetween -(ok|exec) \\\; ]]; then - _normal "$@" + _normal elif [[ -iprefix - ]]; then - complist -s 'daystart {max,min,}depth follow noleaf version xdev \ + compgen -s 'daystart {max,min,}depth follow noleaf version xdev \ {a,c,}newer {a,c,m}{min,time} empty false {fs,x,}type gid inum links \ {i,}{l,}name {no,}{user,group} path perm regex size true uid used \ exec {f,}print{f,0,} ok prune ls' -elif [[ -position 1 ]]; then - complist -g '. ..' +elif [[ -position 2 ]]; then + compgen -g '. ..' _files -g '(-/)' -elif [[ -mcurrent -1 -((a|c|)newer|fprint(|0|f)) ]]; then +elif [[ "$prev" = -((a|c|)newer|fprint(|0|f)) ]]; then _files -elif [[ -current -1 -fstype ]]; then - complist -k '(ufs 4.2 4.3 nfs tmp mfs S51K S52K)' -elif [[ -current -1 -group ]]; then - complist -k groups -elif [[ -current -1 -user ]]; then - complist -u +elif [[ "$prev" = -fstype ]]; then + compgen -k '(ufs 4.2 4.3 nfs tmp mfs S51K S52K)' +elif [[ "$prev" = -group ]]; then + compgen -k groups +elif [[ "$prev" = -user ]]; then + compgen -u fi diff --git a/Completion/User/_hosts b/Completion/User/_hosts index 3acc327ac..eb418c5b3 100644 --- a/Completion/User/_hosts +++ b/Completion/User/_hosts @@ -1,3 +1,3 @@ #defcomp ftp ncftp ping rwho rup xping traceroute nslookup -complist -k hosts +compgen -k hosts diff --git a/Completion/User/_make b/Completion/User/_make index d576b0308..24d2cf3f5 100644 --- a/Completion/User/_make +++ b/Completion/User/_make @@ -1,3 +1,3 @@ #defcomp make gmake pmake -complist -s "\$(awk '/^[a-zA-Z0-9][^/ ]+:/ {print \$1}' FS=: [mM]akefile)" +compgen -s "\$(awk '/^[a-zA-Z0-9][^/ ]+:/ {print \$1}' FS=: [mM]akefile)" diff --git a/Completion/User/_man b/Completion/User/_man index 8204fba0b..67d59f24a 100644 --- a/Completion/User/_man +++ b/Completion/User/_man @@ -2,10 +2,10 @@ setopt localoptions rcexpandparam local rep -if [[ $2 = (<->*|ln) ]]; then - rep=( $manpath/(man|cat)$2/$PREFIX*$SUFFIX.<->*(N:t:r) ) +if [[ $words[2] = (<->*|ln) ]]; then + rep=( $manpath/(man|cat)${words[2]}/$PREFIX*$SUFFIX.<->*(N:t:r) ) else rep=( $manpath/(man|cat)*/$PREFIX*$SUFFIX.<->*(N:t:r) ) fi -(( $#rep )) && compadd -m $rep +(( $#rep )) && compadd - $rep diff --git a/Completion/User/_mh b/Completion/User/_mh index 67ce49fd2..7e8575123 100644 --- a/Completion/User/_mh +++ b/Completion/User/_mh @@ -1,4 +1,4 @@ -#defcomp folder comp inc mark refile repl scan show next prev rmm pick whom mhn mhpath mhpatch +#defcomp folder folders comp inc mark refile repl scan show next prev rmm pick whom mhn mhpath # Completion for all possible MH commands. # Alter the following two to your own mh directory and the directory @@ -7,6 +7,8 @@ local mymhdir=~/Mail local mhlib=/usr/lib/mh +local prev="$words[CURRENT-1]" + # To be on the safe side, check this exists and if not, get it anyway. [[ -d $mymhdir ]] || mymhdir=$(mhpath +) @@ -14,13 +16,13 @@ if [[ -iprefix - ]]; then # get list of options, which MH commands can generate themselves # awk is just too icky to use for this, sorry. send me one if # you come up with it. - compadd -m $($COMMAND -help | perl -ne 'if (/^\s*-\(?(\S+)/) { + compadd - $($words[1] -help | perl -ne 'if (/^\s*-\(?(\S+)/) { $n = $1; $n =~ s/\)//g; print $n =~ s/^\[([a-z]+)\]// ? "$n\n$1$n\n" : "$n\n"; }') return -elif [[ -iprefix '+' || -iprefix '@' || -current -1 -draftfolder ]]; then +elif [[ -iprefix '+' || -iprefix '@' || "$prev" = -draftfolder ]]; then # Complete folder names. local mhpath if [[ $IPREFIX != '@' ]]; then @@ -31,12 +33,12 @@ elif [[ -iprefix '+' || -iprefix '@' || -current -1 -draftfolder ]]; then fi # painless, or what? - complist -W mhpath -/ -elif [[ -mcurrent -1 -(editor|(whatnow|rmm|show|more)proc) ]]; then - complist -c -elif [[ -current -1 -file ]]; then - complist -f -elif [[ -mcurrent -1 -(form|audit|filter) ]]; then + _path_files -W mhpath -/ +elif [[ "$prev" = -(editor|(whatnow|rmm|show|more)proc) ]]; then + compgen -c +elif [[ "$prev" = -file ]]; then + compgen -f +elif [[ "$prev" = -(form|audit|filter) ]]; then # Need some MH template file, which may be in our own MH directory # or with the standard library. local mhfpath @@ -44,11 +46,11 @@ elif [[ -mcurrent -1 -(form|audit|filter) ]]; then [[ -d $mhlib ]] || { mhlib=$(mhparam mhlproc); mhlib=$mhlib:h; } mhfpath=($mymhdir $mhlib) - complist -W mhfpath -g '*(.)' -elif [[ -mcurrent -1 -(no|)cc ]]; then - compadd -m all to cc me -elif [[ -mcurrent -1 -[rw]cache ]]; then - compadd -m public private never ask + compgen -W mhfpath -g '*(.)' +elif [[ "$prev" = -(no|)cc ]]; then + compadd all to cc me +elif [[ "$prev" = -[rw]cache ]]; then + compadd public private never ask else # Generate sequences. local foldnam folddir f @@ -64,7 +66,7 @@ else # leaving foldnam empty works here fi - complist -s '$(mark $foldnam | awk -F: '\''{ print $1 }'\'')' - compadd -m reply next cur prev first last all unseen - complist -W folddir -g '<->' + compgen -s '$(mark $foldnam 2>/dev/null | awk -F: '\''{ print $1 }'\'')' + compadd reply next cur prev first last all unseen + compgen -W folddir -g '<->' fi diff --git a/Completion/User/_rcs b/Completion/User/_rcs index 537db6278..5a751605c 100644 --- a/Completion/User/_rcs +++ b/Completion/User/_rcs @@ -1,9 +1,11 @@ #defcomp co ci rcs -[[ $COMMAND = ci || $COMMAND = rcs ]] && _files +local nm=$compstate[nmatches] -if [[ $NMATCHES -eq 0 && -d RCS && $COMMAND != ci ]]; then +[[ $words[1] = ci || $words[1] = rcs ]] && _files + +if [[ $compstate[nmatches] -eq nm && -d RCS && $words[1] != ci ]]; then local rep rep=(RCS/$PREFIX*$SUFFIX,v(:t:s/\,v//)) - (( $#rep )) && compadd -m $rep + (( $#rep )) && compadd - $rep fi diff --git a/Completion/User/_rlogin b/Completion/User/_rlogin index e36554f23..5d6daef9b 100644 --- a/Completion/User/_rlogin +++ b/Completion/User/_rlogin @@ -1,9 +1,9 @@ #defcomp rlogin rsh ssh -if [[ -position 1 ]]; then - complist -k hosts -elif [[ -position 2 ]]; then - complist -k '(-l)' +if [[ CURRENT -eq 2 ]]; then + compgen -k hosts +elif [[ CURRENT -eq 3 ]]; then + compgen -k '(-l)' else - complist -u + compgen -u fi diff --git a/Completion/User/_stty b/Completion/User/_stty index 6b54b5007..d32d6bdff 100644 --- a/Completion/User/_stty +++ b/Completion/User/_stty @@ -1,12 +1,12 @@ #defcomp stty -if [[ -mcurrent -1 \ +if [[ "$words[CURRENT-1]" = \ (*erase|discard|status|dsusp|intr|kill|lnext|quit|reprint|start|s*p) ]] then - compadd -m -Q '^-' '^h' '^?' '^c' '^u' + compadd -Q '^-' '^h' '^?' '^c' '^u' else [[ -string '-' || -string '+' ]] - compadd -m rows columns intr quit erase kill eof eol \ + compadd rows columns intr quit erase kill eof eol \ eol2 start stop susp dsusp reprint discard werase lnext \ parenb parodd cs8 cstopb hupcl cread clocal parext \ ignbrk brkint ignpar parmrk inpck istrip inlcr igncr icrnl iuclc \ diff --git a/Completion/User/_tar b/Completion/User/_tar index 91767e44d..84c490f1e 100644 --- a/Completion/User/_tar +++ b/Completion/User/_tar @@ -1,11 +1,69 @@ #defcomp tar -local nm=$NMATCHES tf="$2" +# Tar completion. Features: +# - Assumes tar commands are in second position, tar archive is in third +# e.g. tar xvzf zsh-3.0.5.tar.gz ... +# Could search better. Send me the patch. +# - `tar' can be called anything, will use the correct name +# - Preferentially completes *.tar and *.TAR files in third position +# - unless z or Z appears in the commands, in which case prefer *.tar.gz +# and similar (GNU tar). +# - From fourth position on, if command is x or t, completes files inside +# archive. This is supposed to look pretty much as if the files are +# in an ordinary directory hierarchy. Handles extraction from compressed +# archives (GNU tar). +# - Anywhere -- appears, gets a list of long options to complete from +# tar itself (GNU tar); this needs perl. If you have GNU tar but not +# perl: your system manager is weird. +# - Things like --directory=... are also completed correctly. -if [[ ( -mword 1 *t*f* || -mword 1 *x*f* ) && -position 3 100000 ]]; then - complist -k "( $(tar tf $tf) )" -elif [[ -mword 1 *c*f* && -position 3 100000 ]]; then +emulate -LR zsh +setopt extendedglob + +local nm=$NMATCHES tcmd="$words[2]" tf="$words[3]" + +if [[ $PREFIX = *=* ]]; then + # For GNU tar arguments like --directory= + IPREFIX=${PREFIX%%\=*}= + PREFIX=${PREFIX#*=} + if [[ $IPREFIX = --directory* ]]; then + _path_files -/ + else + _files + fi +elif [[ $PREFIX = --* ]]; then + # gnu tar, generate completions from --help + # ones followed by = get that as a suffix + local -a ownlist eqlist + local comp + $words[1] --help | + perl -ne 'while (/--[^[\s,='\'']+=?/g) { print "$&\n"; }' | + while read comp; do + if [[ $comp = *= ]]; then + eqlist[$#eqlist+1]=${comp%=} + else + ownlist[$#ownlist+1]=$comp + fi + done + compgen -S '=' -k eqlist + compgen -k ownlist +elif [[ "$tcmd" = *[tx]*f* && $CURRENT -ge 4 ]] then + # Listing or extracting a particular file. We run `tar t...' + # on the file, keeping the list of filenames cached, plus the + # name of the tarfile so we know if it changes. + local largs=-tf + + [[ $words[2] = *z* ]] && largs=-tzf + [[ $words[2] = *Z* ]] && largs=-tZf + if [[ $tf != $tar_cache_name ]]; then + tar_cache_list=("${(@f)$($words[1] $largs $tf)}") + tar_cache_name=$tf + fi + _multi_parts / tar_cache_list +elif [[ "$tcmd" = *c*f* && $CURRENT -ge 4 ]] then _files -elif [[ -mcurrent -1 *f* && -position 2 ]]; then +elif [[ "$tcmd" = *[zZ]*f* && $CURRENT -eq 3 ]] then + _files -g '*.((tar|TAR).(gz|Z)|.tgz)' +elif [[ "$tcmd" = *f* && $CURRENT -eq 3 ]] then _files -g '*.(tar|TAR)' fi diff --git a/Completion/User/_x_options b/Completion/User/_x_options index cc469286d..3190ee377 100644 --- a/Completion/User/_x_options +++ b/Completion/User/_x_options @@ -2,4 +2,4 @@ # A simple pattern completion, just as an example. -complist -J options -k '(-display -name -xrm)' +compgen -J options -k '(-display -name -xrm)' -- cgit 1.4.1