From 04a89199d02a3ee6c4b3d89a6c782bdb0a4f1bc8 Mon Sep 17 00:00:00 2001 From: Tanaka Akira Date: Thu, 15 Apr 1999 18:20:19 +0000 Subject: zsh-3.1.5-pws-12 --- Completion/.distfiles | 3 + Completion/Base/.distfiles | 6 + Completion/Base/_command_names | 10 +- Completion/Base/_condition | 8 +- Completion/Base/_default | 2 +- Completion/Base/_long_options | 309 +++++++++++++++++++++++++++++++++++++++++ Completion/Base/_match_pattern | 6 + Completion/Base/_subscript | 9 +- Completion/Builtins/.distfiles | 7 + Completion/Builtins/_bindkey | 11 +- Completion/Builtins/_cd | 13 +- Completion/Builtins/_disable | 12 +- Completion/Builtins/_enable | 12 +- Completion/Builtins/_kill | 8 +- Completion/Builtins/_setopt | 9 +- Completion/Builtins/_unhash | 12 +- Completion/Builtins/_unsetopt | 9 +- Completion/Builtins/_wait | 8 +- Completion/Builtins/_zftp | 3 +- Completion/Commands/.distfiles | 3 + Completion/Core/.distfiles | 5 + Completion/Core/_compalso | 6 +- Completion/Core/_files | 11 +- Completion/Core/_main_complete | 118 ++++++++++------ Completion/Core/_normal | 16 ++- Completion/Core/_path_files | 141 ++++++++++++++----- Completion/Core/_sep_parts | 171 +++++++++++++++++++++++ Completion/Core/compdump | 2 +- Completion/Core/compinit | 48 +++++-- Completion/README | 14 +- Completion/User/.distfiles | 6 + Completion/User/_a2ps | 53 ++++--- Completion/User/_configure | 35 +---- Completion/User/_dd | 2 +- Completion/User/_find | 8 +- Completion/User/_man | 2 + Completion/User/_mh | 14 +- Completion/User/_rcs | 1 + Completion/User/_strip | 1 + Completion/User/_tar | 162 ++++++++++++++------- Completion/User/_tar_archive | 20 +++ 41 files changed, 1041 insertions(+), 255 deletions(-) create mode 100644 Completion/.distfiles create mode 100644 Completion/Base/.distfiles create mode 100644 Completion/Base/_long_options create mode 100644 Completion/Builtins/.distfiles create mode 100644 Completion/Commands/.distfiles create mode 100644 Completion/Core/.distfiles create mode 100644 Completion/Core/_sep_parts create mode 100644 Completion/User/.distfiles create mode 100644 Completion/User/_tar_archive (limited to 'Completion') diff --git a/Completion/.distfiles b/Completion/.distfiles new file mode 100644 index 000000000..c50107c61 --- /dev/null +++ b/Completion/.distfiles @@ -0,0 +1,3 @@ +DISTFILES_SRC=' + .distfiles README +' diff --git a/Completion/Base/.distfiles b/Completion/Base/.distfiles new file mode 100644 index 000000000..7e7635fa6 --- /dev/null +++ b/Completion/Base/.distfiles @@ -0,0 +1,6 @@ +DISTFILES_SRC=' + .distfiles + _brace_parameter _command_names _condition _default _equal + _long_options _match_pattern _match_pattern.orig _match_test _parameter + _precommand _redirect _subscript _tilde _vars +' diff --git a/Completion/Base/_command_names b/Completion/Base/_command_names index eab314dfa..f21af674c 100644 --- a/Completion/Base/_command_names +++ b/Completion/Base/_command_names @@ -1,7 +1,11 @@ #defcomp -command- -local nm=$compstate[nmatches] +local nm=$compstate[nmatches] ret=1 -compgen -c +compgen -c && ret=0 -[[ nm -eq compstate[nmatches] ]] && _path_files -/g "*(*)" +if [[ nm -eq compstate[nmatches] ]]; then + _path_files -/g "*(*)" +else + return ret +fi diff --git a/Completion/Base/_condition b/Completion/Base/_condition index fb6b98b1b..db1adfd9a 100644 --- a/Completion/Base/_condition +++ b/Completion/Base/_condition @@ -7,6 +7,10 @@ if [[ "$prev" = -o ]]; then elif [[ "$prev" = -([no]t|ef) ]]; then _files else - _files - compgen -v + local ret=1 + + _files && ret=0 + compgen -v && ret=0 + + return ret fi diff --git a/Completion/Base/_default b/Completion/Base/_default index 569bd6382..9ea1a09db 100644 --- a/Completion/Base/_default +++ b/Completion/Base/_default @@ -9,6 +9,6 @@ # and insert the line `[[ compstate[nmatches] -eq 0 ]] || return' after # `compcall'. -compcall || return +compcall || return 0 _files diff --git a/Completion/Base/_long_options b/Completion/Base/_long_options new file mode 100644 index 000000000..a5d92632c --- /dev/null +++ b/Completion/Base/_long_options @@ -0,0 +1,309 @@ +#autoload + +# This function tries to automatically complete long option names. For +# this it invokes the command from the line with the `--help' option +# and then parses the output to find possible option names. For +# options that get an argument after a `=', the function also tries to +# automatically find out what should be complete as the argument. +# The possible completions for option-arguments can be described with +# the arguments to this function. This is done by giving pairs of +# patterns and actions as consecutive arguments. The actions specify +# what should be done to complete arguemts of those options that match +# the pattern. The action may be a list of words in brackets or in +# parentheses, separated by spaces. A list in brackets denotes +# possible values for an optional argument, a list in parentheses +# gives words to complete for mandatory arguments. If the action does +# not start with a bracket or parentheses, it should be the name of a +# command (probably with arguments) that should be invoked to complete +# after the equal sign. E.g.: +# +# _long_options '*\*' '(yes no)' \ +# '*=FILE*' '_files' \ +# '*=DIR*' '_files -/' +# +# This makes `yes' and `no' be completed as the argument of options +# whose description ends in a star, file names for options that +# contain the substring `=FILE' in the description, and paths for +# options whose description contains `=DIR'. Note the last two +# patterns are not needed since this function always completes files +# 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 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. + +local opt expl group test i name action ret=1 tmp suffix + +setopt extendedglob + +# Get the options. + +group=() +expl=() +if [[ $1 = -*~--* ]]; then + while getopts "J:V:X:t" opt; do + case "$opt" in + [JV]) group=("-$opt" "$OPTARG");; + X) expl=(-X "$OPTARG");; + t) test=yes;; + esac + done + shift OPTIND-1 +fi + +# Test if we are completing after `--' if we were asked to do so. + +[[ -n "$test" && "$PREFIX" != --* ]] && return 1 + +# We cache the information about options and the command name, see if +# we can use the cache. + +if [[ "$words[1]" = (.|..)/* ]]; then + tmp="$PWD/$words[1]" +else + tmp="$words[1]" +fi + +if [[ "$tmp" != $_lo_cache_cmd ]]; then + + # No, store the new command name and clear the old parameters. + + _lo_cache_cmd="$tmp" + (( $+_lo_cache_actions )) && unset "$_lo_cache_names[@]" _lo_cache_actions _lo_cache_names + + local opts pattern anum=1 tmpo str + + # Now get the long option names by calling the command with `--help'. + # The parameter expansion trickery first gets the lines as separate + # array elements. Then we select all lines whose first non-blank + # character is a hyphen. Since some commands document more than one + # option per line, separated by commas, we convert commas int + # newlines and then split the result again at newlines after joining + # 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. + + opts=("--${(@)^${(@)${(@)${(@M)${(@ps:\n:j:\n:)${(@)${(@M)${(@f)$("$words[1]" --help)}:#[ ]#-*}//,/ +}}:#[ ]#--*}#*--}%%[, ]*}:#(*-[A-Z]*|)}") + + # The interpretation of the options is completely table driven. We + # use the positional parameters we were given and a few standard + # ones. Then we loop through this table. + + set -- "$@" '*=FILE*' '_files' '*=(DIR|PATH)*' '_files -/' '*' '' + + while [[ $# -gt 1 ]]; do + + # First, we get the pattern and the action to use and take them + # from the positional parameters. + + pattern="$1" + action="$2" + shift 2 + + # We get all options matching the pattern and take them from the + # list we have built. If no option matches the pattern, we + # continue with the next. + + tmp=("${(@M)opts:##$~pattern}") + opts=("${(@)opts:##$~pattern}") + + (( $#tmp )) || continue + + # Now we collect the options for the pattern in an array. We also + # check if the options take an argument after a `=', and if this + # argument is optional. The name of the array built contains + # `_arg_' for mandatory arguments, `_optarg_' for optional + # arguments, and `_simple_' for options that don't get an + # argument. In `_lo_cache_names' we save the names of these + # arrays and in `_lo_cache_actions' the associated actions. + + # If the action is a list of words in brackets, this denotes + # options that get an optional argument. If the action is a list + # of words in parentheses, the option has to get an argument. + # In both cases we just build the array name to use. + + if [[ "$action[1]" = '[' ]]; then + name="_lo_cache_optarg_$anum" + elif [[ "$action[1]" = '(' ]]; then + name="_lo_cache_arg_$anum" + else + + # If there are option strings with a `[=', we take make these + # get an optional argument... + + tmpo=("${(@M)tmp:#*\[\=*}") + if (( $#tmpo )); then + + # ...by removing them from the option list and storing them in + # an array. + + tmp=("${(@)tmp:#*\[\=*}") + tmpo=("${(@)${(@)tmpo%%\=*}//[^a-z0-9-]}") + _lo_cache_names[anum]="_lo_cache_optarg_$anum" + _lo_cache_actions[anum]="$action" + eval "_lo_cache_optarg_${anum}=(\"\$tmpo[@]\")" + (( anum++ )) + fi + + # Now we do the same for option strings containing `=', these + # are options getting an argument. + + tmpo=("${(@M)tmp:#*\=*}") + if (( $#tmpo )); then + tmp=("${(@)tmp:#*\=*}") + tmpo=("${(@)${(@)tmpo%%\=*}//[^a-z0-9-]}") + _lo_cache_names[anum]="_lo_cache_arg_$anum" + _lo_cache_actions[anum]="$action" + eval "_lo_cache_arg_${anum}=(\"\$tmpo[@]\")" + (( anum++ )) + fi + + # The name for the options without arguments, if any. + + name="_lo_cache_simple_$anum" + fi + # 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-]}") + if (( $#tmp )); then + _lo_cache_names[anum]="$name" + _lo_cache_actions[anum]="$action" + eval "${name}=(\"\$tmp[@]\")" + (( anum++ )) + fi + done +fi + +# We get the string from the line and and see if it already contains a +# equal sign. + +str="$PREFIX$SUFFIX" + +if [[ "$str" = *\=* ]]; then + + # It contains a `=', now we ignore anything up to it, but first save + # the old contents of the special parameters we change. + + local oipre opre osuf pre parto parta pat patflags anum=1 + + oipre="$IPREFIX" + opre="$PREFIX" + 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 + # with the name. If the action is a list of words, we just add them, + # otherwise we invoke the command or function named. + + for name in "$_lo_cache_names[@]"; do + action="$_lo_cache_actions[anum]" + if (( ${(@)${(@P)name}[(I)$pre]} )); then + if [[ "$action[1]" = (\[|\() ]]; then + compadd - ${=action[2,-2]} + elif (( $#action )); then + $=action + fi + + # We found the option string, return. + + return + fi + + # The array did not contain the full option string, see if it + # contains a string matching the string from the line. + # If there is one, we store the option string in `parto' and the + # 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}}") + if [[ $#tmp -eq 1 ]]; then + if [[ -z "$parto" ]]; then + parto="$tmp[1]" + parta="$action" + else + parto=- + fi + elif (( $#tmp )); then + parto=- + fi + (( anum++ )) + done + + # If we found only one matching option, we accept it and immediatly + # try to complete the string after the `='. + + if [[ -n "$parto" && "$parto" != - ]]; then + IPREFIX="${parto}=" + + if (( $#parta )); then + if [[ "$parta[1]" = (\[|\() ]]; then + compadd - ${=parta[2,-2]} + else + $=parta + fi + else + compadd -S '' - "$PREFIX" + fi + return + fi + + # The option string was not found, restore the special parameters. + + IPREFIX="$oipre" + PREFIX="$opre" + SUFFIX="$osuf" +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 +# matches, giving the string from the `=' on as a suffix. + +if [[ "$str" = *\=* ]]; then + str="=${str#*\=}" + PREFIX="${PREFIX%%\=*}" + suffix=() +else + str="" + suffix=('-S=') +fi + +anum=1 +for name in "$_lo_cache_names[@]"; do + action="$_lo_cache_actions[anum]" + + if [[ "$name" = *_optarg_* ]]; then + compadd -M 'r:|-=* r:|=*' -Qq "$suffix[@]" -s "$str" - \ + "${(@P)name}" && ret=0 + elif [[ "$name" = *_arg_* ]]; then + compadd -M 'r:|-=* r:|=*' -Q "$suffix[@]" -s "$str" - \ + "${(@P)name}" && ret=0 + elif [[ -z "$str" ]]; then + compadd -M 'r:|-=* r:|=*' -Q - \ + "${(@P)name}" && ret=0 + fi + (( anum++ )) +done + +return ret diff --git a/Completion/Base/_match_pattern b/Completion/Base/_match_pattern index 3df115d5b..91930a571 100644 --- a/Completion/Base/_match_pattern +++ b/Completion/Base/_match_pattern @@ -28,4 +28,10 @@ # like the `r:|[.-]=* r:|=*'. To make this work, the function `_match_test' # would have to be changed to `(( compstate[matcher] <= 2 ))' # +# When automatic correction is used (see the file `_main_complete'), you +# probably don't want to set matching flags here as that may make the +# results slightly unpredictable. For this, change the line above to: +# +# [[ compstate[matcher] -lt 0 ]] && eval "${3}='(#l)'" +# # The default implementation of this function is empty. diff --git a/Completion/Base/_subscript b/Completion/Base/_subscript index d50fd8335..670739a9a 100644 --- a/Completion/Base/_subscript +++ b/Completion/Base/_subscript @@ -1,5 +1,10 @@ #defcomp -subscript- -_compalso -math- +local ret=1 + +_compalso -math- && ret=0 + [[ ${(Pt)${compstate[parameter]}} = assoc* ]] && - compgen -k "( ${(kP)${compstate[parameter]}} )" + compgen -k "( ${(kP)${compstate[parameter]}} )" && ret=0 + +return ret diff --git a/Completion/Builtins/.distfiles b/Completion/Builtins/.distfiles new file mode 100644 index 000000000..97906e91f --- /dev/null +++ b/Completion/Builtins/.distfiles @@ -0,0 +1,7 @@ +DISTFILES_SRC=' + .distfiles + _aliases _arrays _autoload _bg_jobs _bindkey _builtin _cd _command + _dirs _disable _echotc _enable _fc _functions _hash _jobs _kill + _limits _sched _set _setopt _source _trap _unhash _unsetopt _vars_eq + _wait _which _zftp _zle _zmodload +' diff --git a/Completion/Builtins/_bindkey b/Completion/Builtins/_bindkey index d3d019492..6fca200ba 100644 --- a/Completion/Builtins/_bindkey +++ b/Completion/Builtins/_bindkey @@ -1,7 +1,14 @@ #defcomp bindkey -if [[ "$words[2]" = -*[DAN]* || "$words[CURRENT-1] = -*M ]]; then +# 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, +# so h-b-s-b will complete to history-beginning-search-backward. You +# can alter this by removing the -M ... from the second compgen. +# +# Where appropriate, will complete keymaps instead of widgets. + +if [[ "$words[2]" = -*[DAN]* || "$words[CURRENT-1]" = -*M ]]; then compgen -s '$(bindkey -l)' else - compgen -b + compgen -b -M 'r:|-=* r:|=*' fi diff --git a/Completion/Builtins/_cd b/Completion/Builtins/_cd index 65ce7f293..9a58effe0 100644 --- a/Completion/Builtins/_cd +++ b/Completion/Builtins/_cd @@ -24,7 +24,7 @@ if [[ -position 3 ]]; then 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 + (( ! $#rep )) || compadd $rep elif [[ $words[1] = pu* && $PREFIX = [-+]* ]]; then # pushd: just complete the numbers, but show the full directory list with # numbers. @@ -34,7 +34,8 @@ elif [[ $words[1] = pu* && $PREFIX = [-+]* ]]; then # lazy to type pushd. IPREFIX=$PREFIX[1] PREFIX=$PREFIX[2,-1] - local list lines + local list lines ret=1 + # get the list of directories with their canonical number lines="$(dirs -v)" # turn the lines into an array, removing the current directory @@ -52,9 +53,11 @@ elif [[ $words[1] = pu* && $PREFIX = [-+]* ]]; then 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 + compgen -y '$lines' -Q -k list && ret=0 + [[ -z $compstate[list] ]] && compstate[list]=list && ret=0 + [[ -n $compstate[insert] ]] && compstat[insert]=menu && ret=0 + + return ret elif [[ $PREFIX != (\~|/|./|../)* && $#cdpath -ne 0 ]]; then _path_files -W cdpath -/ else diff --git a/Completion/Builtins/_disable b/Completion/Builtins/_disable index e3edafe2b..27db5c18f 100644 --- a/Completion/Builtins/_disable +++ b/Completion/Builtins/_disable @@ -1,8 +1,10 @@ #defcomp disable -local prev="$words[CURRENT-1]" +local prev="$words[CURRENT-1]" ret=1 -[[ "$prev" = -*a* ]] && compgen -ea -[[ "$prev" = -*f* ]] && compgen -eF -[[ "$prev" = -*r* ]] && compgen -ew -[[ "$prev" != -* ]] && compgen -eB +[[ "$prev" = -*a* ]] && compgen -ea && ret=0 +[[ "$prev" = -*f* ]] && compgen -eF && ret=0 +[[ "$prev" = -*r* ]] && compgen -ew && ret=0 +[[ "$prev" != -* ]] && compgen -eB && ret=0 + +return ret diff --git a/Completion/Builtins/_enable b/Completion/Builtins/_enable index 111d1ae26..1baa09ed6 100644 --- a/Completion/Builtins/_enable +++ b/Completion/Builtins/_enable @@ -1,8 +1,10 @@ #defcomp enable -local prev="$words[CURRENT-1]" +local prev="$words[CURRENT-1]" ret=1 -[[ "$prev" = -*a* ]] && compgen -da -[[ "$prev" = -*f* ]] && compgen -dF -[[ "$prev" = -*r* ]] && compgen -dw -[[ "$prev" != -* ]] && compgen -dB +[[ "$prev" = -*a* ]] && compgen -da && ret=0 +[[ "$prev" = -*f* ]] && compgen -dF && ret=0 +[[ "$prev" = -*r* ]] && compgen -dw && ret=0 +[[ "$prev" != -* ]] && compgen -dB && ret=0 + +return ret diff --git a/Completion/Builtins/_kill b/Completion/Builtins/_kill index c1afa78cb..36a23ccb2 100644 --- a/Completion/Builtins/_kill +++ b/Completion/Builtins/_kill @@ -5,7 +5,11 @@ local list if [[ -iprefix '-' ]]; then compgen -k "($signals[1,-3])" else - compgen -P '%' -j + local ret=1 + + compgen -P '%' -j && ret=0 list=("$(ps 2>/dev/null)") - compgen -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`' && ret=0 + + return ret fi diff --git a/Completion/Builtins/_setopt b/Completion/Builtins/_setopt index 98800152f..b458cb2b0 100644 --- a/Completion/Builtins/_setopt +++ b/Completion/Builtins/_setopt @@ -1,8 +1,11 @@ #defcomp setopt -local nm=$compstate[nmatches] +local nm=$compstate[nmatches] ret=1 compgen -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \ - -s '$({ unsetopt kshoptionprint; unsetopt } 2>/dev/null)' + -s '$({ unsetopt kshoptionprint; unsetopt } 2>/dev/null)' && ret=0 + [[ compstate[nmatches] -eq nm ]] && - compgen -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o + compgen -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o && ret=0 + +return ret diff --git a/Completion/Builtins/_unhash b/Completion/Builtins/_unhash index 63d61c991..a9050cb49 100644 --- a/Completion/Builtins/_unhash +++ b/Completion/Builtins/_unhash @@ -1,8 +1,10 @@ #defcomp unhash -local fl="$words[2]" +local fl="$words[2]" ret=1 -[[ "$fl" = -*d* ]] && compgen -n -[[ "$fl" = -*a* ]] && compgen -a -[[ "$fl" = -*f* ]] && compgen -F -[[ "$fl" != -* ]] && compgen -m +[[ "$fl" = -*d* ]] && compgen -n && ret=0 +[[ "$fl" = -*a* ]] && compgen -a && ret=0 +[[ "$fl" = -*f* ]] && compgen -F && ret=0 +[[ "$fl" != -* ]] && compgen -m && ret=0 + +return ret diff --git a/Completion/Builtins/_unsetopt b/Completion/Builtins/_unsetopt index a5c85b1ef..1194e28a7 100644 --- a/Completion/Builtins/_unsetopt +++ b/Completion/Builtins/_unsetopt @@ -1,8 +1,11 @@ #defcomp unsetopt -local nm=$compstate[nmatches] +local nm=$compstate[nmatches] ret=1 compgen -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \ - -s '$({ unsetopt kshoptionprint; setopt } 2>/dev/null)' + -s '$({ unsetopt kshoptionprint; setopt } 2>/dev/null)' && ret=0 + [[ compstate[nmatches] -eq nm ]] && - compgen -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o + compgen -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o && ret=0 + +return ret diff --git a/Completion/Builtins/_wait b/Completion/Builtins/_wait index 6e3a4c3c9..9281a5cc2 100644 --- a/Completion/Builtins/_wait +++ b/Completion/Builtins/_wait @@ -1,7 +1,9 @@ #defcomp wait -local list +local list ret=1 -compgen -P '%' -j +compgen -P '%' -j && ret=0 list=("$(ps 2>/dev/null)") -compgen -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`' && ret=0 + +return ret diff --git a/Completion/Builtins/_zftp b/Completion/Builtins/_zftp index e93021acf..178d9d9e3 100644 --- a/Completion/Builtins/_zftp +++ b/Completion/Builtins/_zftp @@ -45,6 +45,7 @@ case $subcom in *) # dunno... try ordinary completion after all. - unset _compskip + unset _compskip + return 1 ;; esac diff --git a/Completion/Commands/.distfiles b/Completion/Commands/.distfiles new file mode 100644 index 000000000..f79d69704 --- /dev/null +++ b/Completion/Commands/.distfiles @@ -0,0 +1,3 @@ +DISTFILES_SRC=' + .distfiles _correct_filename _most_recent_file +' diff --git a/Completion/Core/.distfiles b/Completion/Core/.distfiles new file mode 100644 index 000000000..ddf2a707e --- /dev/null +++ b/Completion/Core/.distfiles @@ -0,0 +1,5 @@ +DISTFILES_SRC=' + .distfiles + _compalso _files _main_complete _multi_parts _normal _path_files + _sep_parts compdump compinit +' diff --git a/Completion/Core/_compalso b/Completion/Core/_compalso index 6ff6cf0bf..52fb08f05 100644 --- a/Completion/Core/_compalso +++ b/Completion/Core/_compalso @@ -7,7 +7,9 @@ # `_compalso -math-' to get the completions that would be generated for a # mathematical context. -local tmp +local tmp ret=1 tmp="$_comps[$1]" -[[ -z "$tmp" ]] || "$tmp" +[[ -z "$tmp" ]] || "$tmp" && ret=0 + +return ret diff --git a/Completion/Core/_files b/Completion/Core/_files index 471824bfe..506ddbc8e 100644 --- a/Completion/Core/_files +++ b/Completion/Core/_files @@ -3,10 +3,9 @@ # 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=$compstate[nmatches] ret +local nm=$compstate[nmatches] ret=1 -_path_files "$@" -ret=$? +_path_files "$@" && ret=0 if [[ $# -ne 0 && compstate[nmatches] -eq nm ]]; then local opt opts @@ -23,7 +22,7 @@ if [[ $# -ne 0 && compstate[nmatches] -eq nm ]]; then [[ "$opt" = [PSWFJVX] ]] && opts=("$opts[@]" "-$opt" "$OPTARG") done - _path_files "$opts[@]" -else - return $ret + _path_files "$opts[@]" && ret=0 fi + +return ret diff --git a/Completion/Core/_main_complete b/Completion/Core/_main_complete index 34c5a3d3c..3571b712c 100644 --- a/Completion/Core/_main_complete +++ b/Completion/Core/_main_complete @@ -3,36 +3,47 @@ # The main loop of the completion code. This is what is called when # completion is attempted from the command line. # -# 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 +# This code will automatically try to correct the string on the line +# based on the strings generated for the context if +# `compconfig[correct]' 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, +#`compconfig[correct]' 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 _comp_correct comax - -setopt localoptions nullglob rcexpandparam globdots +# `compconfig[correct]' will be used. E.g. with `compconfig[correct]=2n' +# two errors will be accepted, but if the user gives another number +# with the numeric argument, this will be prefered. Also, with +# `compconfig[correct]=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. Independent of the number of errors the user +# wants to accept, the code will allow only fewer errors than there +# are characters in the string from the line. +# The value of `compconfig[correct_orig]' is used to determine if the +# original string should be included in the list (and thus be +# presented to the user when cycling through the corrections). If it +# is set to any non-empty value, the original string will be +# offered. If it contains the sub-string `last', the original string +# will apear as the last string when cycling through the corrections, +# otherwise it will appear as the first one (so that the command line +# does not change immediatly). Also, if the value of +# `compconfig[correct_orig]' contains the sub-string `always', the +# original string will always be included, whereas normally it is +# included only if more than one possible correction was generated. +# Finally, `compconfig[correct_prompt]' may be set to a string that +# should be printed before the list of corrected strings when cycling +# through them. This string may contain the control sequences `%n', +# `%B', etc. known from the `-X' option of `compctl'. Also, the +# sequence `%e' will be replaced by the number of errors accepted to +# generate the corrected strings. + +local comp name _comp_correct _correct_prompt comax + +setopt localoptions nullglob rcexpandparam unsetopt markdirs globsubst shwordsplit nounset ksharrays # Special completion contexts after `~' and `='. @@ -91,25 +102,30 @@ while true; do # Use automatic correction? - if (( $+COMPCORRECT )); then + if (( $+compconfig[correct] )); 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 [[ -n "$_comp_correct" && + ( "$compconfig[correct_orig]" = *always* || + 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 [[ "$compconfig[correct_orig]" = *last* ]]; then + builtin compadd -V _correct_orig -nQ - "$PREFIX$SUFFIX" + elif [[ -n "$compconfig[correct_orig]" ]]; then + builtin compadd -nQ - "$PREFIX$SUFFIX" + fi # If you always want to see the list of possible corrections, # set `compstate[list]=list' here. + + compstate[force_list]=list fi # Since we have matches, we don't want to try again. + break fi @@ -117,25 +133,33 @@ while true; do if [[ -n "$_comp_correct" ]]; then - # Yes, give up if we reached the maximum number of tries, - # otherwise increment our counter. + # Yes, give up if we reached the maximum number of tries or the + # string from the line is too short, otherwise increment our + # counter. - [[ _comp_correct -eq comax ]] && break + [[ _comp_correct -eq comax || + "${#${:-$PREFIX$SUFFIX}}" -le _comp_correct+1 ]] && break (( _comp_correct++ )) + _correct_prompt="${compconfig[correct_prompt]//\%e/$_comp_correct}" + elif [[ compstate[matcher] -eq compstate[total_matchers] ]]; then + # We don't try correction if the string is too short. + + [[ "${#${:-$PREFIX$SUFFIX}}" -le 1 ]] && return + # 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 + if [[ "$compconfig[correct]" = *[nN]* && NUMERIC -ne 1 ]]; then # Prefer the numeric argument if that has a sensible value. comax="$NUMERIC" else - comax="${COMPCORRECT//[^0-9]}" + comax="${compconfig[correct]//[^0-9]}" fi - # If the number of errors to accept is to small, give up. + # If the number of errors to accept is too small, give up. [[ "$comax" -lt 1 ]] && break @@ -145,25 +169,31 @@ while true; do # ignored prefix). compadd() { + [[ "$*" != *-([a-zA-Z/]#|)U* && + "${#${:-$PREFIX$SUFFIX}}" -le _comp_correct ]] && return + 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 "$@" + if [[ -n "$_correct_prompt" ]]; then + builtin compadd -X "$_correct_prompt" -J _correct "$@" else builtin compadd -J _correct "$@" fi } compgen() { + [[ "$*" != *-([a-zA-Z/]#|)U* && + "${#${:-$PREFIX$SUFFIX}}" -le _comp_correct ]] && return + 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 + if [[ -n "$_correct_prompt" ]]; then + builtin compgen "$@" -X "$_correct_prompt" -J _correct else builtin compgen "$@" -J _correct fi @@ -179,6 +209,8 @@ while true; do _comp_correct=1 compstate[matcher]=-1 + _correct_prompt="${compconfig[correct_prompt]//\%e/$_comp_correct}" + # We also need to set `extendedglob' and to make the completion # code behave as if globcomplete were set. diff --git a/Completion/Core/_normal b/Completion/Core/_normal index f56849194..98337eae5 100644 --- a/Completion/Core/_normal +++ b/Completion/Core/_normal @@ -1,6 +1,6 @@ #autoload -local comp command cmd1 cmd2 pat val name i ret +local comp command cmd1 cmd2 pat val name i ret=1 # 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. @@ -9,8 +9,9 @@ local comp command cmd1 cmd2 pat val name i ret command="$words[1]" if [[ CURRENT -eq 1 ]]; then comp="$_comps[-command-]" - [[ -z "$comp" ]] || "$comp" - return + [[ -z "$comp" ]] || "$comp" && ret=0 + + return ret elif [[ "$command[1]" == '=' ]]; then eval cmd1\=$command cmd2="$command[2,-1]" @@ -28,11 +29,10 @@ for i in "$_patcomps[@]"; do pat="${i% *}" val="${i#* }" if [[ "$cmd1" == $~pat || "$cmd2" == $~pat ]]; then - "$val" - ret=$? + "$val" && ret=0 if (( $+_compskip )); then unset _compskip - return $ret + return ret fi fi done @@ -53,4 +53,6 @@ if [[ -z "$comp" ]]; then name=-default- comp="$_comps[-default-]" fi -[[ -z "$comp" ]] || "$comp" +[[ -z "$comp" ]] || "$comp" && ret=0 + +return ret diff --git a/Completion/Core/_path_files b/Completion/Core/_path_files index 3c03c0c61..535ba537c 100644 --- a/Completion/Core/_path_files +++ b/Completion/Core/_path_files @@ -2,13 +2,15 @@ # 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 `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 -# are treated like files with one of the suffixes in the `fignore' array -# in normal completion. +# `-V ', `-W paths', `-X explanation', `-P prefix', `-S suffix', +# `-q', `-r remove-chars', `-R remove-func', and `-F '. All but +# 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. # # This function uses the helper functions `_match_test' and `_match_pattern'. @@ -20,9 +22,10 @@ _match_test _path_files || return 1 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 orig ostr nm=$compstate[nmatches] +local addpfx addsfx expl orig ostr nm=$compstate[nmatches] menu remsfx patlast +local origflags mflags -setopt localoptions nullglob rcexpandparam globdots extendedglob +setopt localoptions nullglob rcexpandparam extendedglob unsetopt markdirs globsubst shwordsplit nounset prepaths=('') @@ -33,16 +36,21 @@ gopt='' pats=() addpfx=() addsfx=() +remsfx=() expl=() # Get the options. -while getopts "P:S:W:F:J:V:X:f/g:" opt; do +while getopts "P:S:qr:R:W:F:J:V:X:f/g:" opt; do case "$opt" in P) addpfx=(-P "$OPTARG") ;; S) addsfx=(-S "$OPTARG") ;; + q) tmp1=yes + ;; + [rR]) remsfx=("-$opt" "$OPTARG") + ;; W) tmp1="$OPTARG" if [[ "$tmp1[1]" = '(' ]]; then prepaths=( ${^=tmp1[2,-2]}/ ) @@ -76,6 +84,8 @@ while getopts "P:S:W:F:J:V:X:f/g:" opt; do esac done +[[ -n "$tmp1" && $#addsfx -ne 0 ]] && addsfx[1]=-qS + # If we were given no file selection option, we behave as if we were given # a `-f'. @@ -89,19 +99,25 @@ if [[ "$sopt" = - ]]; then fi # str holds the whole string from the command line with a `*' between -# the prefix and the suffix. +# the prefix and the suffix. Then we see if we will do menucompletion. -if [[ -o globcomplete ]]; then +if [[ $#compstate[pattern_match] -ne 0 ]]; then str="${PREFIX}*${SUFFIX}" else str="${PREFIX:q}*${SUFFIX:q}" + [[ "$str" = \\\~* ]] && str="$str[2,-1]" fi orig="${PREFIX}${SUFFIX}" +[[ $compstate[insert] = *menu || -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' option. +# weren't given a `-F', `-r', or `-R' option. -if (( ! $#ignore )); then +if [[ $#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. @@ -124,11 +140,11 @@ if (( ! $#ignore )); then # If this generated any matches, we don't want to do in-path completion. [[ compstate[nmatches] -eq nm ]] || return 0 +fi - # No `-F' option, so we want to use `fignore'. +# No `-F' option, so we want to use `fignore'. - ignore=(-F fignore) -fi +(( $#ignore )) || ignore=(-F fignore) # Now let's have a closer look at the string to complete. @@ -176,6 +192,7 @@ fi 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 @@ -185,13 +202,40 @@ _match_pattern _path_files patstr matchflags patstr="$patstr:gs-/-*/-: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##*/}//\*/[^/]#}" + else + patlast="*/${matchflags}${${patstr##*/}//\*/[^/]#}" + fi + patstr="${patstr%/*}/" +else + if [[ -n "$_comp_correct" && "$#orig" -le _comp_correct ]]; then + patlast="${origflags}${patstr//\*/[^/]#}" + else + patlast="${matchflags}${patstr//\*/[^/]#}" + 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'. while [[ "$orig" = */* ]] do - tmp1=( ${~matchflags}$realpath$donepath${orig%%/*}/${~patstr#*/}$^pats ) + tmp1=( $realpath$donepath${orig%%/*}/${~matchflags}${~patstr#*/}$^pats ) + tmp1=("${(@M)tmp1:#$~patlast}") [[ $#tmp1 -gt 0 && -e "$realpath$donepath${orig%%/*}" ]] || break donepath="$donepath${orig%%/*}/" orig="${orig#*/}" @@ -217,8 +261,13 @@ for prepath in "$prepaths[@]"; do # we get the globbing matches for the pathname component currently # handled. + if [[ -n "$_comp_correct" && "${#ostr%%/*}" -le _comp_correct ]]; then + mflags="$origflags" + else + mflags="$matchflags" + fi rest="${str#*/}" - tmp1="${prepath}${realpath}${testpath}${~matchflags}${str%%/*}(-/)" + tmp1="${prepath}${realpath}${testpath}${~mflags}${str%%/*}(-/)" tmp1=( $~tmp1 ) if [[ $#tmp1 -eq 0 ]]; then @@ -240,12 +289,19 @@ for prepath in "$prepaths[@]"; do suffixes=( $rest$^pats ) suffixes=( "${(@)suffixes:gs.**.*.}" ) + if [[ -n "$_comp_correct" && "${#ostr#*/}" -le _comp_correct ]]; then + mflags="$origflags" + else + mflags="$matchflags" + fi + # 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}/${~matchflags}${~suffixes} ) + tmp2=( ${~i}/${~mflags}${~suffixes} ) + tmp2=("${(@M)tmp2:#$~patlast}") [[ $#tmp2 -ne 0 ]] && collect=( $collect $i ) done @@ -255,9 +311,6 @@ for prepath in "$prepaths[@]"; do # 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 @@ -270,6 +323,7 @@ for prepath in "$prepaths[@]"; do # Now produce all matching pathnames in `collect'. collect=( ${~collect}/${~matchflags}${~suffixes} ) + collect=("${(@M)collect:#$~patlast}") # And then remove the common path prefix from all these matches. @@ -282,15 +336,16 @@ for prepath in "$prepaths[@]"; do # these are file names and that `fignore' should be used as usual # (the `-f' and `-F' options). - if [[ $compstate[insert] = *menu ]]; then + if [[ -n "$menu" ]]; then compadd -QU "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" \ - -i "$IPREFIX" -p "${linepath:q}${testpath:q}" -S "/${ostr#*/}" \ + -i "$IPREFIX" -p "$linepath${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%%/*}" + compadd -QU "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" \ + -i "$IPREFIX" -p "$linepath${testpath:q}" -s "/${${i#*/}:q}" \ + -M 'r:|/=*' -W "$tmp1" -f "$ignore[@]" - "${${i%%/*}:q}" done fi @@ -299,12 +354,27 @@ for prepath in "$prepaths[@]"; do continue 2 fi + # 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. tmp1=( "$collect[1]" ) + elif [[ -n "$_comp_correct" && "$mflags" = "$matchflags" ]]; then + + # If we got only one match with auto-correction and if we get none + # without correction, stop now. + + tmp2="${prepath}${realpath}${testpath}${~origflags}${str%%/*}(-/)" + tmp2=( $~tmp2 ) + + if [[ $#tmp1 -ne $#tmp2 ]]; then + compadd -QU "$addpfx[@]" -S '' "$group[@]" "$expl[@]" \ + -i "$IPREFIX" -p "$linepath${testpath:q}" -s "/${ostr#*/}" \ + - "${${tmp1#${prepath}${realpath}${testpath}}:q}" + continue 2 + fi 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. @@ -320,10 +390,17 @@ for prepath in "$prepaths[@]"; do # no path suffix, the `-W' we are currently handling, all the matches we # can produce in this directory, if any. + 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} ) + tmp2=("${(@M)tmp2:#$~patlast}") + if [[ $#tmp2 -eq 0 ]]; then # No match, insert the expanded path and add the original tail. @@ -334,11 +411,11 @@ for prepath in "$prepaths[@]"; do [[ "$linepath$testpath$ostr" = "$PREFIX$SUFFIX" ]] && return 1 compadd -QU -S '' "$group[@]" "$expl[@]" \ - -i "$IPREFIX" -f - "${linepath:q}${testpath:q}$ostr" + -i "$IPREFIX" -f - "$linepath${testpath:q}$ostr" else - compadd -U "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" \ - -i "$IPREFIX" -p "$linepath$testpath" -f "$ignore[@]" \ - -W "$prepath$realpath$testpath" - "${(@)tmp2#$tmp1}" + compadd -QU "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" "$group[@]" "$expl[@]" \ + -i "$IPREFIX" -p "$linepath${testpath:q}" -f "$ignore[@]" \ + -W "$prepath$realpath$testpath" - "${(@)${(@)tmp2#$tmp1}:q}" fi done diff --git a/Completion/Core/_sep_parts b/Completion/Core/_sep_parts new file mode 100644 index 000000000..c1cda2b9a --- /dev/null +++ b/Completion/Core/_sep_parts @@ -0,0 +1,171 @@ +#autoload + +# This function can be used to separately complete parts of strings +# where each part may be one of a set of matches and different parts +# have different sets. +# Arguments are alternatingly arrays and separator strings. Arrays may +# be given by name or literally as words separated by white space in +# parentheses, e.g.: +# +# _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 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=() +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 string from the line. + +str="$PREFIX$SUFFIX" +[[ $#compstate[pattern_match] -ne 0 ]] || str="$str:q" +prefix="" + +# Walk through the arguments to find the longest unambiguous prefix. + +while [[ $# -gt 1 ]]; do + # Get the next array and separator. + arr="$1" + sep="$2" + + if [[ "$arr[1]" == '(' ]]; then + 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. + + test="${str%%${sep}*}" + [[ -n "$_comp_correct" && $#test -le _comp_correct ]] && return 1 + + matchflags="" + _match_pattern _sep_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 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)" + + test="${matchflags}${test}" + testarr=( "${(@M)${(@P)arr}:#${~test}*}" ) + testarr=( "${(@)testarr:#}" ) +fi + +[[ $#testarr -eq 0 || ${#testarr[1]} -eq 0 ]] && return 1 + +# Now we build the suffixes to give to the completion code. +shift +matchers=() +suffixes=("") +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}*}" + else + test="$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)" + 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. + + arr="$2" + if [[ "$arr[1]" == '(' ]]; then + tmparr=( ${=arr[2,-2]} ) + arr=tmparr + fi + tmparr=( "${(@M)${(@P)arr}:#${~test}*}" ) + tmparr=( "${(@)tmparr:#}" ) + 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" -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/compdump b/Completion/Core/compdump index 8be096f50..5fdee8c7a 100644 --- a/Completion/Core/compdump +++ b/Completion/Core/compdump @@ -15,7 +15,7 @@ # Print the number of files used for completion. This is used in compinit # to see if auto-dump should re-dump the dump-file. -_d_file=${COMPDUMP-${0:h}/compinit.dump} +_d_file=${compconfig[dump_file]-${0:h}/compinit.dump} typeset -U _d_files _d_files=( ${^~fpath}/_*~*~(N:t) ) diff --git a/Completion/Core/compinit b/Completion/Core/compinit index ec5867838..31d011565 100644 --- a/Completion/Core/compinit +++ b/Completion/Core/compinit @@ -37,18 +37,24 @@ # Note that no white space is allowed between the `#' and the rest of # the string. # -# See the file `compdump' for how to speed up initialiation. +# Functions that are used to generate matches should return zero if they +# were able to add matches and non-zero otherwise. +# +# See the file `compdump' for how to speed up initialisation. # # If you are using global matching specifications with `compctl -M ...' # have a look at the files `_match_test' and `_match_pattern'. To make # all the example functions use matching as specified with `-M' these # need some editing. -# + # If we got the `-d'-flag, we will automatically dump the new state (at # the end). +# If we were given an argument, this will be taken as the name of the +# file in which to store the dump. if [[ "$1" = -d ]]; then _i_autodump=1 + shift else _i_autodump=0 fi @@ -59,6 +65,18 @@ fi typeset -A _comps _patcomps=() +# This is the associative array used for configuration. + +typeset -A compconfig + +# Standard initialisation for `compconfig'. + +(( $# )) && compconfig[dump_file]="$1" +[[ -z "$compconfig[dump_file]" ]] && compconfig[dump_file]="$0.dump" + +compconfig[correct_prompt]='correct to:' + + # This function is used to register or delete completion functions. For # registering completion functions, it is invoked with the name of the # function as it's first argument (after the options). The other @@ -197,11 +215,25 @@ compdef() { fi } -# Now we automatically make the definition files autoloaded. +# Functional interface to configuration. This takes its arguments +# and sets the according values in `compconfig'. +# Arguments may be `foo=bar' to set key `foo' to `bar' or `baz' to +# set key `baz' to the empty string. -# First we get the name of a dump file if this will be used. +compconf() { + local i name -: ${COMPDUMP:=$0.dump} + for i; do + if [[ "$i" = *\=* ]]; then + name="${i%%\=*}" + compconfig[$name]="${i#*\=}" + else + compconfig[$i]='' + fi + done +} + +# Now we automatically make the definition files autoloaded. if [[ ! -o extendedglob ]]; then _i_noextglob=yes @@ -215,10 +247,10 @@ _i_done='' # If we have a dump file, load it. -if [[ -f "$COMPDUMP" ]]; then - read -rA _i_line < "$COMPDUMP" +if [[ -f "$compconfig[dump_file]" ]]; then + read -rA _i_line < "$compconfig[dump_file]" if [[ _i_autodump -eq 1 && $_i_line[2] -eq $#_i_files ]]; then - builtin . "$COMPDUMP" + builtin . "$compconfig[dump_file]" _i_done=yes fi unset _i_line diff --git a/Completion/README b/Completion/README index 43ffcbcc2..f95e67699 100644 --- a/Completion/README +++ b/Completion/README @@ -9,9 +9,12 @@ Core/compinit. It is recommnded that you use the -d option, which outputs a file containing the necessary variables, bindkeys etc., making later loading much faster. For example, [[ -f ~/completion/compinit ]] && . ~/completion/compinit -d +The name of the file to use may be given as an extra argument. + 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. For information about how to configure the code, +see the comment at the top of Core/_main_complete. The subdirectories contain: @@ -27,7 +30,7 @@ Core: This dumps the completions status for faster initialisation. The easiest way of doing this is to use the -d option to compinit rather than calling compdump directly. - _comp_parts + _sep_parts Utility used for completing words with multiple separate parts, such as `@' _multi_parts @@ -67,10 +70,15 @@ Base: This handles completion of command arguments when no special function exists. Usually this means completing files, but you can modify this as you wish. + _long_options + This handles options beginning with `--', as in many GNU commands. + The command must accept the --help option to list the possible options. + __long_options can also take arguments to help it decide what to + complete as the value of the option. _match_pattern _match_test These are used by Base/_path_files (and hence also Base/_files) - and Base/_comp_parts for file completion with control over + and Base/_sep_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. diff --git a/Completion/User/.distfiles b/Completion/User/.distfiles new file mode 100644 index 000000000..ee0017035 --- /dev/null +++ b/Completion/User/.distfiles @@ -0,0 +1,6 @@ +DISTFILES_SRC=' + .distfiles + _a2ps _compress _configure _dd _dvi _find _gunzip _gzip _hosts + _make _man _mh _pdf _ps _rcs _rlogin _strip _stty _tar _tar_archive + _tex _uncompress _x_options _xfig +' diff --git a/Completion/User/_a2ps b/Completion/User/_a2ps index 600b58872..9923ae20d 100644 --- a/Completion/User/_a2ps +++ b/Completion/User/_a2ps @@ -1,22 +1,39 @@ #defcomp a2ps -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)' +# This is for the GNU version of a2ps. - 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)' - compgen -qS= -k '(--margin --header --underlay --left-title - --right-title --left-footer --footer --right-footer - --pages --pretty-print)' - compgen -k '(--landscape --portrait --catman --no-header)' -else - _files -F fignore -g "*~*.ps" +if [[ "$words[1]" != "$_a2ps_cache_cmd" ]]; then + local descr + + _a2ps_cache_cmd="$words[1]" + + descr=( "${(@)${(f@)$($words[1] --list=features)// + / }:#}" ) + + _a2ps_cache_values=( + "${descr[(r)Known style sheets*]#* }" + "${descr[(r)Known encodings*]#* }" + "${descr[(r)Known media*]#* }" + "${descr[(r)Known prologues*]#* }" + "${descr[(r)Known PostScript Printer Descriptions*]#* }" + "${descr[(r)Known output destination*]#* }" + "${descr[(r)Known user options*]#* }" + "${descr[(r)Known Variables*]#* }" + ) fi + +_long_options -t '*\*' '(yes no)' \ + '*=DIRECTION' '(rows columns)' \ + '*=TYPE' '(r n nr rn any)' \ + '--highlight-level*' '(none normal heavy)' \ + '--version-control*' '(none off t numbered nil + existing never simple)' \ + '--pretty-print*' "[${_a2ps_cache_values[1]}]" \ + '--encoding*' "(${_a2ps_cache_values[2]})" \ + '--medium*' "[${_a2ps_cache_values[3]}]" \ + '--prologue*' "[${_a2ps_cache_values[4]}]" \ + '--ppd*' "[${_a2ps_cache_values[5]}]" \ + '--printer*' "[${_a2ps_cache_values[6]}]" \ + '--user-option*' "[${_a2ps_cache_values[7]}]" \ + '--variable*' "[${_a2ps_cache_values[8]}]" || + _files -F fignore -g '*~*.(ps|PS|eps|EPS)' diff --git a/Completion/User/_configure b/Completion/User/_configure index 050701fac..7559852e8 100644 --- a/Completion/User/_configure +++ b/Completion/User/_configure @@ -1,35 +1,4 @@ #defcomp configure -setopt localoptions extendedglob - -if [[ $PREFIX = *=* ]]; then - # Complete filenames after e.g. --prefix= - IPREFIX=${PREFIX%%=*}= - PREFIX=${PREFIX#*=} - compgen -f -else - # Generate a list of options from configure --help - 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 +_long_options '*=(E|)PREFIX*' '_files -/' \ + '*=PROGRAM*' '_command_names' diff --git a/Completion/User/_dd b/Completion/User/_dd index 86a47b1ab..63ae40f50 100644 --- a/Completion/User/_dd +++ b/Completion/User/_dd @@ -5,7 +5,7 @@ if [[ -iprefix conv= ]]; then # test alone will have that effect. [[ -string , ]] compgen -S, -q \ - -k '(ascii ebcdic ibm block unblock lcase ucase swab noerror sync)' + -k '(ascii ebcdic ibm block unblock lcase ucase swab noerror sync)' elif [[ -iprefix 'if=' || -iprefix 'of=' ]]; then _files else diff --git a/Completion/User/_find b/Completion/User/_find index 8fcdafb83..cb637fc26 100644 --- a/Completion/User/_find +++ b/Completion/User/_find @@ -10,8 +10,12 @@ elif [[ -iprefix - ]]; then {i,}{l,}name {no,}{user,group} path perm regex size true uid used \ exec {f,}print{f,0,} ok prune ls' elif [[ -position 2 ]]; then - compgen -g '. ..' - _files -g '(-/)' + local ret=1 + + compgen -g '. ..' && ret=0 + _files -g '(-/)' && ret=0 + + return ret elif [[ "$prev" = -((a|c|)newer|fprint(|0|f)) ]]; then _files elif [[ "$prev" = -fstype ]]; then diff --git a/Completion/User/_man b/Completion/User/_man index 67d59f24a..cd1badc4d 100644 --- a/Completion/User/_man +++ b/Completion/User/_man @@ -1,7 +1,9 @@ #defcomp man + setopt localoptions rcexpandparam local rep + if [[ $words[2] = (<->*|ln) ]]; then rep=( $manpath/(man|cat)${words[2]}/$PREFIX*$SUFFIX.<->*(N:t:r) ) else diff --git a/Completion/User/_mh b/Completion/User/_mh index 7e8575123..c6c018220 100644 --- a/Completion/User/_mh +++ b/Completion/User/_mh @@ -4,6 +4,7 @@ # Alter the following two to your own mh directory and the directory # where standard mh library files live. (It works anyway, but this # will save a little time.) + local mymhdir=~/Mail local mhlib=/usr/lib/mh @@ -25,6 +26,7 @@ if [[ -iprefix - ]]; then elif [[ -iprefix '+' || -iprefix '@' || "$prev" = -draftfolder ]]; then # Complete folder names. local mhpath + if [[ $IPREFIX != '@' ]]; then [[ $IPREFIX = '+' ]] || IPREFIX=+ mhpath=$mymhdir @@ -53,7 +55,8 @@ elif [[ "$prev" = -[rw]cache ]]; then compadd public private never ask else # Generate sequences. - local foldnam folddir f + local foldnam folddir f ret + for f in $argv; do [[ $f = [@+]* ]] && foldnam=$f done @@ -66,7 +69,10 @@ else # leaving foldnam empty works here fi - compgen -s '$(mark $foldnam 2>/dev/null | awk -F: '\''{ print $1 }'\'')' - compadd reply next cur prev first last all unseen - compgen -W folddir -g '<->' + compgen -s '$(mark $foldnam 2>/dev/null | awk -F: '\''{ print $1 }'\'')' && + ret=0 + compadd reply next cur prev first last all unseen && ret=0 + compgen -W folddir -g '<->' && ret=0 + + return ret fi diff --git a/Completion/User/_rcs b/Completion/User/_rcs index 5a751605c..5e53cb4da 100644 --- a/Completion/User/_rcs +++ b/Completion/User/_rcs @@ -6,6 +6,7 @@ local nm=$compstate[nmatches] if [[ $compstate[nmatches] -eq nm && -d RCS && $words[1] != ci ]]; then local rep + rep=(RCS/$PREFIX*$SUFFIX,v(:t:s/\,v//)) (( $#rep )) && compadd - $rep fi diff --git a/Completion/User/_strip b/Completion/User/_strip index 6962ac455..541c901ad 100644 --- a/Completion/User/_strip +++ b/Completion/User/_strip @@ -1,2 +1,3 @@ #defcomp strip + _files -g '*(*)' diff --git a/Completion/User/_tar b/Completion/User/_tar index 84c490f1e..d11ee76c8 100644 --- a/Completion/User/_tar +++ b/Completion/User/_tar @@ -1,69 +1,125 @@ #defcomp tar # 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. +# - Tries to collect tar commands from second position, single letter +# option, and long options. # - `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). +# - Uses the function `_tar_archive' to complete archive files. +# - Tries to find out if compressed archives should be used. +# - 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. +# tar itself (GNU tar) # - Things like --directory=... are also completed correctly. emulate -LR zsh setopt extendedglob -local nm=$NMATCHES tcmd="$words[2]" tf="$words[3]" +local _tar_cmd tf tmp del -if [[ $PREFIX = *=* ]]; then - # For GNU tar arguments like --directory= - IPREFIX=${PREFIX%%\=*}= - PREFIX=${PREFIX#*=} - if [[ $IPREFIX = --directory* ]]; then - _path_files -/ - else - _files +# First we collect in `_tar_cmd' single letter options describing what +# should be done with the archive and if it is compressed. This +# collected from options arguments that start with only one hyphen, +# from some of the possible long options, and from the second word if +# that does not start with a hyphen. + +tmp=("${(@M)words:#-[^-]*}") +_tar_cmd="${(j::)tmp#-}" + +(( $words[(I)--(un|)gzip] )) && _tar_cmd="z$_tar_cmd" +(( $words[(I)--(un|)compress] )) && _tar_cmd="Z$_tar_cmd" +(( $words[(I)--list] )) && _tar_cmd="t$_tar_cmd" +(( $words[(I)--(extract|get)] )) && _tar_cmd="x$_tar_cmd" +(( $words[(I)--create] )) && _tar_cmd="c$_tar_cmd" + +# Other ways of finding out what we're doing: first +# look in the first argument if it's not an option +if [[ "$words[2]" = *[txcdruA]*~-* ]]; then + _tar_cmd="$words[2]$_tar_cmd" +elif [[ $_tar_cmd != *[txcdruA]* && CURRENT -gt 2 ]]; then + # look for more obscure long options: these aren't all handled. + (( $words[(I)--(diff|compare)] )) && _tar_cmd="d$_tar_cmd" + (( $words[(I)--append] )) && _tar_cmd="r$_tar_cmd" + (( $words[(I)--update] )) && _tar_cmd="u$_tar_cmd" + (( $words[(I)--(con|)catenate] )) && _tar_cmd="A$_tar_cmd" + (( $words[(I)--delete] )) && del=1 +fi + +# Next, we try to find the archive name and store it in `tf'. The name +# is searched after a `--file=' long option, in the third word if the +# second one didn't start with a hyphen but contained a `f', and after +# an option argument starting with only one hyphen and containing a `f'. + +tmp="$words[(I)--file=*]" +if (( tmp )); then + tf="${words[tmp][8,-1]}" + _tar_cmd="f$_tar_cmd" +elif [[ "$words[2]" != -* && "$words[2]" = *f* ]]; then + tf="$words[3]" + _tar_cmd="f$_tar_cmd" +else + tmp="${words[(I)-*f*~--*]}" + if (( tmp )); then + tf="$words[tmp+1]" + _tar_cmd="f$_tar_cmd" 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. +fi + +# Now we complete... + +if [[ "$PREFIX" = --* ]]; then + + # ...long options after `--'. + + _long_options '--owner*' "_tilde" \ + '*=(PROG|COMMAND)*' "_command_names" \ + '*=ARCHIVE*' "_tar_archive" \ + '*=CONTROL*' "[t numbered nil existing never simple]" + +elif [[ ( CURRENT -gt 2 && "$words[CURRENT-1]" = -*f* && + "$words[CURRENT-1]" != --* ) || + ( CURRENT -eq 3 && "$words[2]" = *f* && "$words[2]" != -* ) ]]; then + + # ...archive files if we think they are wanted here. + + _tar_archive + +elif [[ ( "$_tar_cmd" = *[xt]* || -n $del ) && -n "$tf" ]]; then + + # ...and files from the archive if we found an archive name and tar + # commands. 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 + if [[ $_tar_cmd = *z* ]]; then + largs=-tzf + elif [[ $_tar_cmd = *Z* ]]; then + largs=-tZf + else + # Some random compression program e.g. bzip2 + tmp="${words[(r)--use-comp*]}" + [[ -n $tmp ]] && largs=($tmp -tf) + fi + + if [[ $tf != $_tar_cache_name ]]; then + _tar_cache_list=("${(@f)$($words[1] $largs $tf)}") + _tar_cache_name=$tf + fi + + _multi_parts / _tar_cache_list +else + + # See if we should use a path prefix. We have to use eval as the dir can + # be any unevaluated thing which appears on the command line, including a + # parameter. + tmp=${words[(r)--dir[a-z]#=*]} + if [[ -n $tmp ]]; then + eval "tmp=(${tmp#*=})" + _path_files -W tmp + else + _files fi - _multi_parts / tar_cache_list -elif [[ "$tcmd" = *c*f* && $CURRENT -ge 4 ]] then - _files -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/_tar_archive b/Completion/User/_tar_archive new file mode 100644 index 000000000..58e436c4d --- /dev/null +++ b/Completion/User/_tar_archive @@ -0,0 +1,20 @@ +#autoload + +# This is used to generate filenames usable as a tar archive. This may +# get one argument, a collection of tar option characters that may be +# used to find out what kind of filename is needed. If no argument is +# given but the parameter `_tar_cmd' is set, that is used. +# If your version of `tar' supports this you may want to complete +# things like `host:file' or `user@host:file' here. + +[[ $# -eq 0 && $+_tar_cmd -ne 0 ]] && set "$_tar_cmd" + +if [[ "$1" = *[tx]* ]]; then + if [[ "$1" = *[zZ]* ]]; then + _files -g '*.((tar|TAR).(gz|GZ|Z)|.tgz)' + else + _files -g '*.(tar|TAR)' + fi +else + _files +fi -- cgit 1.4.1