summaryrefslogtreecommitdiff
path: root/Completion
diff options
context:
space:
mode:
Diffstat (limited to 'Completion')
-rw-r--r--Completion/Base/_arguments571
-rw-r--r--Completion/Base/_default30
-rw-r--r--Completion/Base/_describe164
-rw-r--r--Completion/Base/_jobs80
-rw-r--r--Completion/Base/_subscript58
-rw-r--r--Completion/Base/_tilde55
-rw-r--r--Completion/Base/_values383
-rw-r--r--Completion/Builtins/_autoload11
-rw-r--r--Completion/Builtins/_cd48
-rw-r--r--Completion/Builtins/_compdef54
-rw-r--r--Completion/Builtins/_disable12
-rw-r--r--Completion/Builtins/_emulate6
-rw-r--r--Completion/Builtins/_enable12
-rw-r--r--Completion/Builtins/_fc30
-rw-r--r--Completion/Builtins/_nothing2
-rw-r--r--Completion/Builtins/_pids26
-rw-r--r--Completion/Builtins/_popd55
-rw-r--r--Completion/Builtins/_sched24
-rw-r--r--Completion/Builtins/_signals12
-rw-r--r--Completion/Builtins/_stat20
-rw-r--r--Completion/Builtins/_zcompile22
-rw-r--r--Completion/Builtins/_zftp100
-rw-r--r--Completion/Builtins/_zpty10
-rw-r--r--Completion/Builtins/_zstyle145
-rw-r--r--Completion/Commands/_complete_help73
-rw-r--r--Completion/Commands/_history_complete_word107
-rw-r--r--Completion/Commands/_next_tags86
-rw-r--r--Completion/Core/_all_labels44
-rw-r--r--Completion/Core/_alternative45
-rw-r--r--Completion/Core/_approximate192
-rw-r--r--Completion/Core/_call2
-rw-r--r--Completion/Core/_complete58
-rw-r--r--Completion/Core/_correct4
-rw-r--r--Completion/Core/_description54
-rw-r--r--Completion/Core/_expand152
-rw-r--r--Completion/Core/_files59
-rw-r--r--Completion/Core/_ignored3
-rw-r--r--Completion/Core/_list43
-rw-r--r--Completion/Core/_main_complete221
-rw-r--r--Completion/Core/_match44
-rw-r--r--Completion/Core/_menu4
-rw-r--r--Completion/Core/_next_label24
-rw-r--r--Completion/Core/_oldlist53
-rw-r--r--Completion/Core/_path_files661
-rw-r--r--Completion/Core/_prefix4
-rw-r--r--Completion/Core/_requested21
-rw-r--r--Completion/Core/_setup68
-rw-r--r--Completion/Core/_tags144
-rw-r--r--Completion/Core/_wanted22
-rw-r--r--Completion/Core/compdump62
-rw-r--r--Completion/Core/compinit427
-rw-r--r--Completion/Core/compinstall431
-rw-r--r--Completion/Linux/_rpm101
-rw-r--r--Completion/User/_gdb52
-rw-r--r--Completion/User/_getconf37
-rw-r--r--Completion/User/_groups19
-rw-r--r--Completion/User/_lp76
-rw-r--r--Completion/User/_make33
-rw-r--r--Completion/User/_mh67
-rw-r--r--Completion/User/_nedit9
-rw-r--r--Completion/User/_netscape70
-rw-r--r--Completion/User/_tiff37
-rw-r--r--Completion/User/_urls180
-rw-r--r--Completion/User/_users12
-rw-r--r--Completion/User/_users_on8
-rw-r--r--Completion/X/_x_colormapid5
-rw-r--r--Completion/X/_x_extension10
-rw-r--r--Completion/X/_x_font15
-rw-r--r--Completion/X/_x_keysym6
-rw-r--r--Completion/X/_x_window13
-rw-r--r--Completion/X/_xmodmap20
-rw-r--r--Completion/X/_xutils42
-rw-r--r--Completion/X/_xwit8
73 files changed, 3647 insertions, 2211 deletions
diff --git a/Completion/Base/_arguments b/Completion/Base/_arguments
index 5170acb84..bf263d6e9 100644
--- a/Completion/Base/_arguments
+++ b/Completion/Base/_arguments
@@ -3,386 +3,345 @@
# Complete the arguments of the current command according to the
# descriptions given as arguments to this function.
-local long args rest ws cur nth def nm expl descr action opt arg tmp
+local long cmd="$words[1]" descr mesg subopts opt usecc autod
+local oldcontext="$curcontext" hasopts
-# Associative arrays used to collect information about the options.
+long=$argv[(I)--]
+if (( long )); then
+ local name tmp tmpargv
-typeset -A opts mopts dopts dmopts odopts odmopts
-
-# See if we support long options, too.
+ if [[ long -eq 1 ]]; then
+ tmpargv=()
+ else
+ tmpargv=( "${(@)argv[1,long-1]}" )
+ fi
-nth=$argv[(I)--]
-if (( nth )); then
- long=( "${(@)argv[nth+1,-1]}" )
- argv=("${(@)argv[1,nth-1]}")
-else
- long=()
-fi
+ name=${~words[1]}
+ [[ "$name" != /* ]] && tmp="$PWD/$name"
-# Now parse the arguments...
+ name="_args_cache_${name}"
+ name="${name//[^a-zA-Z0-9_]/_}"
-args=()
-nth=1
-while (( $# )); do
+ if (( ! ${(P)+name} )); then
+ local iopts sopts pattern tmpo cur cache
+ typeset -U lopts
- # This describes a one-shot option.
+ cache=()
- if [[ "$1" = [-+]* ]]; then
- if [[ "$1" = *:* ]]; then
+ # We have to build a new long-option cache, get the `-i' and
+ # `-s' options.
- # If the option name ends in a `-', the first argument comes
- # directly after the option, if it ends in a `+', the first
- # argument *may* come directly after the option, otherwise it
- # is in the next word.
+ set -- "${(@)argv[long+1,-1]}"
- if [[ "$1" = [^:]##-:* ]]; then
- dopts[${${1%%:*}[1,-2]}]="${1#*:}"
- elif [[ "$1" = [^:]##+:* ]]; then
- odopts[${${1%%:*}[1,-2]}]="${1#*:}"
+ iopts=()
+ sopts=()
+ while [[ "$1" = -[is]* ]]; do
+ if [[ "$1" = -??* ]]; then
+ tmp="${1[3,-1]}"
+ cur=1
else
- opts[${1%%:*}]="${1#*:}"
+ tmp="$2"
+ cur=2
fi
- else
- opts[$1]=''
- fi
- elif [[ "$1" = \*[-+]* ]]; then
-
- # The same for options that may appear more than once.
-
- if [[ "$1" = *:* ]]; then
- if [[ "$1" = [^:]##-:* ]]; then
- dmopts[${${1[2,-1]%%:*}[1,-2]}]="${1#*:}"
- elif [[ "$1" = [^:]##+:* ]]; then
- odmopts[${${1[2,-1]%%:*}[1,-2]}]="${1#*:}"
+ if [[ "$tmp[1]" = '(' ]]; then
+ tmp=( ${=tmp[2,-2]} )
else
- mopts[${1[2,-1]%%:*}]="${1#*:}"
+ tmp=( "${(@P)tmp}" )
fi
- else
- mopts[${1[2,-1]}]=''
- fi
- elif [[ "$1" = \*:* ]]; then
+ if [[ "$1" = -i* ]]; then
+ iopts=( "$iopts[@]" "$tmp[@]" )
+ else
+ sopts=( "$sopts[@]" "$tmp[@]" )
+ fi
+ shift cur
+ done
- # This is `*:...', describing `all other arguments'.
+ # 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.
- rest="${1[3,-1]}"
- elif [[ "$1" = :* ]]; then
+ lopts=("--${(@)^${(@)${(@)${(@M)${(@ps:\n:j:\n:)${(@)${(@M)${(@f)$(_call options ${~words[1]} --help 2>&1)//\[--/
+--}:#[ ]#-*}//,/
+}}:#[ ]#--*}#*--}%%[], ]*}:#}")
+ lopts=( "${(@)lopts:#--}" )
- # This is `:...', describing `the next argument'.
+ # Now remove all ignored options ...
- args[nth++]="${1#*:}"
- else
+ while (( $#iopts )); do
+ lopts=( ${lopts:#$~iopts[1]} )
+ shift iopts
+ done
- # And this is `n:...', describing the `n'th argument.
+ # ... and add "same" options
- args[${1%%:*}]="${1#*:}"
- nth=$(( ${1%%:*} + 1 ))
- fi
- shift
-done
+ while (( $#sopts )); do
+ lopts=( $lopts ${lopts/$sopts[1]/$sopts[2]} )
+ shift 2 sopts
+ done
-if [[ $#long -ne 0 && "$PREFIX" = --* ]]; then
+ # Then we walk through the descriptions plus a few builtin ones.
- # If the current words starts with `--' and we should use long
- # options, just call...
+ set -- "$@" '*=FILE*:file:_files' \
+ '*=(DIR|PATH)*:directory:_files -/' '*: :'
- _long_options "$long[@]"
-else
+ while (( $# )); do
- # Otherwise parse the command line...
+ # First, we get the pattern and the action to use and take them
+ # from the positional parameters.
- ws=( "${(@)words[2,-1]}" )
- cur=$(( CURRENT-2 ))
- nth=1
+ pattern="${${${(M)1#*[^\\]:}[1,-2]}//\\\\:/:}"
+ descr="${1#${pattern}}"
+ shift
- # ...until the current word is reached.
+ # 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.
- while [[ cur -gt 0 ]]; do
+ tmp=("${(@M)lopts:##$~pattern}")
+ lopts=("${(@)lopts:##$~pattern}")
- # `def' holds the description for the option we are currently after.
- # Check if the next argument for the option is optional.
+ (( $#tmp )) || continue
- if [[ "$def" = :* ]]; then
- opt=yes
- else
opt=''
- fi
- arg=''
-
- # Remove one description/action pair from `def' if that isn't empty.
- if [[ -n "$def" ]]; then
- if [[ "$def" = ?*:*:* ]]; then
- def="${def#?*:*:}"
- else
- def=''
- fi
- else
+ # If there are option strings with a `[=', we take these get an
+ # optional argument.
- # If it is empty, and the word starts with `--' and we should
- # complete long options, just ignore this word, otherwise make sure
- # we test for options below and handle normal arguments.
+ tmpo=("${(@M)tmp:#*\[\=*}")
+ if (( $#tmpo )); then
+ tmp=("${(@)tmp:#*\[\=*}")
+ tmpo=("${(@)${(@)tmpo%%\=*}//[^a-z0-9-]}")
- if [[ $#long -eq 0 || "$ws[1]" != --* ]]; then
- opt=yes
- arg=yes
- else
- def=''
+ if [[ "$descr" = ::* ]]; then
+ cache=( "$cache[@]" "${(@)^tmpo}=${descr}" )
+ else
+ cache=( "$cache[@]" "${(@)^tmpo}=:${descr}" )
+ fi
fi
- fi
-
- if [[ -n "$opt" ]]; then
-
- # `opt' was set above if we have to test if the word is an option.
- # We first test for the simple options -- those without arguments or
- # those whose arguments have to be given as separate words.
-
- if (( $+opts[$ws[1]] )); then
-
- # Options that may only be given once are removed from the
- # associative array so that we are not offered them again.
- def="$opts[$ws[1]]"
- unset "opts[$ws[1]]"
- elif (( $+mopts[$ws[1]] )); then
- def="$mopts[$ws[1]]"
- else
+ # Descriptions with `=': mandatory argument.
- # If the word is none of the simple options, test for those
- # whose first argument has to or may come directly after the
- # option. This is done in four loops looking very much alike.
+ tmpo=("${(@M)tmp:#*\=*}")
+ if (( $#tmpo )); then
+ tmp=("${(@)tmp:#*\=*}")
+ tmpo=("${(@)${(@)tmpo%%\=*}//[^a-z0-9-]}")
- if (( $#dopts )); then
+ cache=( "$cache[@]" "${(@)^tmpo}=${descr}" )
+ fi
- # First we get the option names.
+ # Everything else is just added as a option without arguments.
- tmp=( "${(@k)dopts}" )
+ if (( $#tmp )); then
+ tmp=("${(@)tmp//[^a-zA-Z0-9-]}")
+ cache=( "$cache[@]" "$tmp[@]" )
+ fi
+ done
+ eval "${name}=( \"\${(@)cache:# #}\" )"
+ fi
+ set -- "$tmpargv[@]" "${(@P)name}"
+fi
- # Then we loop over them and see if the current word begins
- # with one of the option names.
+subopts=()
+while [[ "$1" = -(O*|C) ]]; do
+ case "$1" in
+ -C) usecc=yes; shift ;;
+ -O) subopts=( "${(@P)2}" ); shift 2 ;;
+ *) subopts=( "${(@P)1[3,-1]}" ); shift ;;
+ esac
+done
- while (( $#tmp )); do
- [[ "$ws[1]" = ${tmp[1]}* ]] && break
- shift 1 tmp
- done
+zstyle -s ":completion:${curcontext}:options" auto-description autod
- if (( $#tmp )); then
+if (( $# )) && comparguments -i "$autod" "$@"; then
+ local nm="$compstate[nmatches]" action noargs aret expl local
+ local next direct odirect equal single match matched ws tmp1 tmp2 tmp3
+ local opts subc prefix suffix
+ local origpre="$PREFIX" origipre="$IPREFIX"
- # It does. So use the description for it, but only from
- # the second argument on, because we are searching the
- # description for the next command line argument.
+ if comparguments -D descr action; then
+ comparguments -C subc
+ curcontext="${oldcontext%:*}:$subc"
- opt=''
- def="$dopts[$tmp[1]]"
- unset "dopts[$tmp[1]]"
- if [[ "$def" = ?*:*:* ]]; then
- def="${def#?*:*:}"
- else
- def=''
- fi
- fi
- fi
- if [[ -n "$opt" && $#dmopts -ne 0 ]]; then
- tmp=( "${(@k)dmopts}" )
- while (( $#tmp )); do
- [[ "$ws[1]" = ${tmp[1]}* ]] && break
- shift 1 tmp
- done
-
- if (( $#tmp )); then
- opt=''
- def="$dmopts[$tmp[1]]"
- if [[ "$def" = ?*:*:* ]]; then
- def="${def#?*:*:}"
- else
- def=''
- fi
- fi
- fi
- if [[ -n "$opt" && $#odopts -ne 0 ]]; then
- tmp=( "${(@k)odopts}" )
- while (( $#tmp )); do
- [[ "$ws[1]" = ${tmp[1]}* ]] && break
- shift 1 tmp
- done
-
- if (( $#tmp )); then
- opt=''
- def="$odopts[$tmp[1]]"
- unset "odopts[$tmp[1]]"
-
- # For options whose first argument *may* come after the
- # option, we skip over the first description only if there
- # is something after the option name on the line.
-
- if [[ "$ws[1]" != "$tmp[1]" ]]; then
- if [[ "$def" = ?*:*:* ]]; then
- def="${def#?*:*:}"
- else
- def=''
- fi
- fi
- fi
- fi
- if [[ -n "$opt" && $#odmopts -ne 0 ]]; then
- tmp=( "${(@k)odmopts}" )
- while (( $#tmp )); do
- [[ "$ws[1]" = ${tmp[1]}* ]] && break
- shift 1 tmp
- done
-
- if (( $#tmp )); then
- opt=''
- def="$odmopts[$tmp[1]]"
- if [[ "$ws[1]" != "$tmp[1]" ]]; then
- if [[ "$def" = ?*:*:* ]]; then
- def="${def#?*:*:}"
- else
- def=''
- fi
- fi
- fi
- fi
-
- # If we didn't find a matching option description and we were
- # told to use normal argument descriptions, just increase
- # our counter `nth'.
-
- if [[ -n "$opt" && -n "$arg" ]]; then
- def=''
- (( nth++ ))
- fi
- fi
+ if comparguments -O next direct odirect equal; then
+ opts=yes
+ _tags arguments options
+ else
+ _tags arguments
+ fi
+ else
+ if comparguments -a; then
+ noargs='no more arguments'
+ else
+ noargs='no arguments'
fi
+ comparguments -O next direct odirect equal || return 1
- shift 1 ws
- (( cur-- ))
- done
+ opts=yes
+ _tags options
+ fi
- # Now generate the matches.
+ while true; do
+ while _tags; do
+ if [[ -n "$matched" ]] || _requested arguments; then
+ _description arguments expl "$descr"
+
+ if [[ "$action" = -\>* ]]; then
+ comparguments -W line opt_args
+ state="${${action[3,-1]##[ ]#}%%[ ]#}"
+ if [[ -n "$usecc" ]]; then
+ curcontext="${oldcontext%:*}:$subc"
+ else
+ context="$subc"
+ fi
+ compstate[restore]=''
+ aret=yes
+ else
+ if [[ -z "$local" ]]; then
+ local line
+ typeset -A opt_args
+ local=yes
+ fi
- nm="$compstate[nmatches]"
+ comparguments -W line opt_args
- if [[ -z "$def" || "$def" = :* ]]; then
+ if [[ "$action" = \ # ]]; then
- # We either don't have a description for an argument of an option
- # or we have a description for a optional argument.
+ # An empty action means that we should just display a message.
- if [[ -z "$def" ]]; then
+ [[ -n "$matched" ]] && compadd -n -Q -S '' -s "$SUFFIX" - "$PREFIX"
+ mesg="$descr"
- # If we have none at all, use the one for this argument position.
+ elif [[ "$action" = \(\(*\)\) ]]; then
- def="$args[nth]"
- [[ -z "$def" ]] && def="$rest"
- fi
+ # ((...)) contains literal strings with descriptions.
- # In any case, we have to complete option names here, but we may
- # be in a string that starts with an option names and continues with
- # the first argument, test that (again, four loops).
+ eval ws\=\( "${action[3,-3]}" \)
- opt=yes
- if (( $#dopts )); then
+ _describe "$descr" ws -M "$match" "$subopts[@]"
- # Get the option names.
+ elif [[ "$action" = \(*\) ]]; then
- tmp=( "${(@k)dopts}" )
- while (( $#tmp )); do
- if compset -P "$tmp[1]"; then
+ # Anything inside `(...)' is added directly.
- # The current string starts with the option name, so ignore
- # that and complete the rest of the string.
+ _all_labels arguments expl "$descr" \
+ compadd "$subopts[@]" - ${=action[2,-2]}
+ elif [[ "$action" = \{*\} ]]; then
- def="$dopts[$tmp[1]]"
- opt=''
- break
- fi
- shift 1 tmp
- done
- fi
- if [[ -n "$opt" && $#dmopts -ne 0 ]]; then
- tmp=( "${(@k)dmopts}" )
- while (( $#tmp )); do
- if compset -P "$tmp[1]"; then
- def="$dmopts[$tmp[1]]"
- opt=''
- break
- fi
- shift 1 tmp
- done
- fi
- if [[ -n "$opt" && $#odopts -ne 0 ]]; then
- tmp=( "${(@k)odopts}" )
- while (( $#tmp )); do
- if compset -P "$tmp[1]"; then
- def="$odopts[$tmp[1]]"
- opt=''
- break
- fi
- shift 1 tmp
- done
- fi
- if [[ -n "$opt" && $#odmopts -ne 0 ]]; then
- tmp=( "${(@k)odmopts}" )
- while (( $#tmp )); do
- if compset -P "$tmp[1]"; then
- def="$odmopts[$tmp[1]]"
- opt=''
- break
- fi
- shift 1 tmp
- done
- fi
- if [[ -n "$opt" ]]; then
-
- # We aren't in an argument directly after a option name, so
- # all option names are possible matches.
-
- _description expl option
- compadd "$expl[@]" - "${(@k)opts}" "${(@k)mopts}" \
- "${(@k)dopts}" "${(@k)dmopts}" \
- "${(@k)odopts}" "${(@k)odmopts}"
- fi
- fi
+ # A string in braces is evaluated.
- # Now add the matches from the description, if any.
+ while _next_label arguments expl "$descr"; do
+ eval "$action[2,-2]"
+ done
+ elif [[ "$action" = \ * ]]; then
- if [[ -n "$def" ]]; then
+ # If the action starts with a space, we just call it.
- # Ignore the leading colon describing optional arguments.
+ eval "action=( $action )"
+ while _next_label arguments expl "$descr"; do
+ "$action[@]"
+ done
+ else
- [[ "$def" = :* ]] && def="$def[2,-1]"
+ # Otherwise we call it with the description-arguments.
- # Get the description and the action.
+ eval "action=( $action )"
+ _all_labels arguments expl "$descr" \
+ "$action[1]" "$subopts[@]" "${(@)action[2,-1]}"
+ fi
+ fi
+ fi
- descr="${def%%:*}"
- action="${${def#*:}%%:*}"
+ if [[ -z "$matched$hasopts" ]] && _requested options &&
+ { ! zstyle -T ":completion:${curcontext}:options" prefix-needed ||
+ [[ "$origpre" = [-+]* ||
+ ( -z "$aret$mesg" && nm -eq compstate[nmatches] ) ]] } ; then
+ local prevpre="$PREFIX" previpre="$IPREFIX"
+
+ hasopts=yes
+
+ PREFIX="$origpre"
+ IPREFIX="$origipre"
+
+ comparguments -M match
+
+ if comparguments -s single; then
+
+ _description options expl option
+
+ if [[ "$single" = direct ]]; then
+ compadd "$expl[@]" -QS '' - "${PREFIX}${SUFFIX}"
+ elif [[ "$single" = next ]]; then
+ compadd "$expl[@]" -Q - "${PREFIX}${SUFFIX}"
+ elif [[ "$single" = equal ]]; then
+ compadd "$expl[@]" -QqS= - "${PREFIX}${SUFFIX}"
+ else
+ tmp1=( "$next[@]" "$direct[@]" "$odirect[@]" "$equal[@]" )
+ tmp3=( "${(M@)tmp1:#[-+]?[^:]*}" )
+ tmp1=( "${(M@)tmp1:#[-+]?(|:*)}" )
+ tmp2=( "${PREFIX}${(@M)^${(@)${(@)tmp1%%:*}#[-+]}:#?}" )
+
+ _describe -o option \
+ tmp1 tmp2 -Q -S '' -- \
+ tmp3 -Q
+ fi
+ single=yes
+ else
+ next=( "$next[@]" "$odirect[@]" )
+ _describe -o option \
+ next -Q -M "$match" -- \
+ direct -QS '' -M "$match" -- \
+ equal -QqS= -M "$match"
+ fi
+ PREFIX="$prevpre"
+ IPREFIX="$previpre"
+ fi
+ done
+ if [[ -n "$opts" && -z "$aret$matched$mesg" &&
+ nm -eq compstate[nmatches] ]]; then
- _description expl "$descr"
+ PREFIX="$origpre"
+ IPREFIX="$origipre"
- if [[ -z "$action" ]]; then
+ prefix="${PREFIX#*\=}"
+ suffix="$SUFFIX"
+ PREFIX="${PREFIX%%\=*}"
+ SUFFIX=''
+ compadd -M "$match" -D equal - "${(@)equal%%:*}"
- # An empty action means that we should just display a message.
- _message "$descr"
- return 1
- elif [[ "$action[1]" = \( ]]; then
+ if [[ $#equal -eq 1 ]]; then
+ PREFIX="$prefix"
+ SUFFIX="$suffix"
+ IPREFIX="${IPREFIX}${equal[1]%%:*}="
+ matched=yes
- # Anything inside `(...)' is added directly.
+ comparguments -L "${equal[1]%%:*}" descr action subc
+ curcontext="${oldcontext%:*}:$subc"
- compadd "$expl[@]" - ${=action[2,-2]}
- elif [[ "$action" = \ * ]]; then
+ _tags arguments
- # If the action starts with a space, we just call it.
+ continue
+ fi
+ fi
+ break
+ done
- $=action
- else
+ [[ -z "$aret" || -z "$usecc" ]] && curcontext="$oldcontext"
- # Otherwise we call it with the description-arguments built above.
+ [[ -n "$aret" ]] && return 300
- action=( $=action )
- "$action[1]" "$expl[@]" "${(@)action[2,-1]}"
- fi
- fi
+ [[ -n "$mesg" ]] && _message "$mesg"
+ [[ -n "$noargs" ]] && _message "$noargs"
# Set the return value.
- [[ nm -ne "$compstate[nmatches]" ]]
+ [[ nm -ne "$compstate[nmatches]" ]]
+else
+ return 1
fi
diff --git a/Completion/Base/_default b/Completion/Base/_default
index 8bcf14f6a..fd5869e2e 100644
--- a/Completion/Base/_default
+++ b/Completion/Base/_default
@@ -1,13 +1,23 @@
-#defcomp -default-
+#compdef -default-
-# We first try the `compctl's. This is without first (-T) and default (-D)
-# completion. If you want them add `-T' and/or `-D' to this command.
-# If there is a `compctl' for the command we are working on, we return
-# 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'.
+local ctl
-compcall || return
+if { zstyle -s ":completion:${curcontext}:" use-compctl ctl ||
+ zmodload -e zsh/compctl } && [[ "$ctl" != (no|false|0|off) ]]; then
+ local opt
-_files
+ opt=()
+ [[ "$ctl" = *first* ]] && opt=(-T)
+ [[ "$ctl" = *default* ]] && opt=("$opt[@]" -D)
+ compcall "$opt[@]" || return 0
+fi
+
+_wanted files || return 1
+
+_files && return 0
+
+# magicequalsubst allows arguments like <any-old-stuff>=~/foo to do
+# file name expansion after the =. In that case, it's natural to
+# allow completion to handle file names after any equals sign.
+
+[[ -o magicequalsubst ]] && compset -P 1 '*=' && _files
diff --git a/Completion/Base/_describe b/Completion/Base/_describe
index e01c77509..6e6f4f4a9 100644
--- a/Completion/Base/_describe
+++ b/Completion/Base/_describe
@@ -2,154 +2,52 @@
# This can be used to add options or values with descriptions as matches.
-setopt localoptions extendedglob
+local _opt _expl _tmps _tmpd _tmpmd _tmpms _ret=1 _showd _nm _hide _args
+local _type=values _descr
-local gdescr isopt cmd opt nsets tmp descr match descrs matches adescr i
-local disps disp expl tmps tmpd tmpmd tmpms name ret=1 showd _nm
+# Get the option.
-cmd="$words[1]"
-
-# Get the options.
-
-while getopts 'oc:' opt; do
- if [[ "$opt" = o ]]; then
- isopt=yes
- else
- cmd="$OPTARG"
- fi
-done
-shift OPTIND-1
+if [[ "$1" = -o ]]; then
+ _type=options
+ shift
+fi
# Do the tests. `showd' is set if the descriptions should be shown.
-if [[ -n "$isopt" ]]; then
-
- # We take the value to test the number of patches from a non-local
- # parameter `nm' if that exists and contains only digits. It's a hack.
-
- if [[ "$nm" = [0-9]## ]]; then
- _nm="$nm"
- else
- _nm=0
- fi
- [[ -n "$compconfig[option_prefix]" &&
- "$compconfig[option_prefix]" != *\!${cmd}* &&
- "$PREFIX" != [-+]* &&
- ( "$compconfig[option_prefix]" = *nodefault* ||
- _nm -ne compstate[nmatches] ) ]] && return 1
+_wanted "$_type" || return 1
- [[ -n "$compconfig[describe_options]" &&
- "$compconfig[describe_options]" != *\!${cmd}* ]] && showd=yes
-else
- [[ -n "$compconfig[describe_values]" &&
- "$compconfig[describe_values]" != *\!${cmd}* ]] && showd=yes
-fi
+zstyle -T ":completion:${curcontext}:$_type" verbose && _showd=yes
-gdescr="$1"
+_descr="$1"
shift
-# Now interpret the arguments.
+[[ "$_type" = options ]] &&
+ zstyle -t ":completion:${curcontext}:options" prefix-hidden && _hide=yes
-nsets=0
-adescr=()
-descrs=()
-matches=()
-while (( $# )); do
- (( nsets++ ))
- descr="$1"
- [[ -n "$showd" ]] && adescr=( "$adescr[@]" "${(@PM)^descr:#*:?*},$nsets" )
- if [[ "$2" = -* ]]; then
- match=''
- shift
- else
- match="$2"
- shift 2
- fi
- tmp=$argv[(i)--]
- if [[ tmp -eq 1 ]]; then
- opt=()
- else
- opt=( "${(@)argv[1,tmp-1]}" )
- fi
- if [[ tmp -gt $# ]]; then
- argv=()
+while _next_label "$_type" _expl "$_descr"; do
+
+ if [[ -n "$_showd" ]]; then
+ compdescribe -I ' -- ' "$@"
else
- shift tmp
+ compdescribe -i "$@"
fi
- # `descr' and `matches' collect the names of the arrays containing the
- # possible matches with descriptions and the matches to add.
- # The options to give to `compadd' are stored in local arrays.
+ while compdescribe -g _args _tmpd _tmpmd _tmps _tmpms; do
- descrs[nsets]="$descr"
- matches[nsets]="$match"
- typeset -a _descr_opts_$nsets
- eval "_descr_opts_${nsets}=( \"\$opt[@]\" )"
-done
-
-(( nsets )) || return 1
-
-# Build the display strings if needed.
-
-[[ -n "$showd" ]] && _display disps "$adescr[@]"
-_description expl "$gdescr"
+ # See if we should remove the option prefix characters.
-# Loop through the array/option sets we have.
-
-i=0
-while [[ ++i -le nsets ]]; do
- name=_descr_opts_$i
- [[ -n "$showd" ]] && disp=( "${(@)${(@M)disps:#*,${i}}%,*}" )
- descr=( "${(@P)descrs[i]}" )
-
- # We collect the strings to display in `tmpd' (one string per line)
- # and `tmps' (in columns) and the matches to add in `tmpmd' and `tmpms'.
-
- tmpd=()
- tmps=()
- tmpmd=()
- tmpms=()
- if [[ -n "$matches[i]" ]]; then
- match=( "${(@P)matches[i]}" )
- while (( $#match )); do
- if [[ -n "$showd" && "$descr[1]" = *:?* ]]; then
- tmpd=( "$tmpd[@]" "$disp[1]" )
- tmpmd=( "$tmpmd[@]" "$match[1]" )
- shift 1 disp
- else
- tmps=( "$tmps[@]" "${descr[1]%%:*}" )
- tmpms=( "$tmpms[@]" "$match[1]" )
+ if [[ -n "$_hide" ]]; then
+ if [[ "$PREFIX" = --* ]]; then
+ _tmpd=( "${(@)_tmpd#--}" )
+ _tmps=( "${(@)_tmps#--}" )
+ elif [[ "$PREFIX" = [-+]* ]]; then
+ _tmpd=( "${(@)_tmpd#[-+]}" )
+ _tmps=( "${(@)_tmps#[-+]}" )
fi
- shift 1 match
- shift 1 descr
- done
- else
- while (( $#descr )); do
- if [[ -n "$showd" && "$descr[1]" = *:?* ]]; then
- tmpd=( "$tmpd[@]" "$disp[1]" )
- tmpmd=( "$tmpmd[@]" "${descr[1]%%:*}" )
- shift 1 disp
- else
- tmps=( "$tmps[@]" "${descr[1]%%:*}" )
- tmpms=( "$tmpms[@]" "${descr[1]%%:*}" )
- fi
- shift 1 descr
- done
- fi
-
- # See if we should remove the option prefix characters.
-
- if [[ -n "$isopt" && "$compconfig[option_prefix]" = hide* ]]; then
- if [[ "$PREFIX" = --* ]]; then
- tmpd=( "${(@)tmpd#--}" )
- tmps=( "${(@)tmps#--}" )
- elif [[ "$PREFIX" = [-+]* ]]; then
- tmpd=( "${(@)tmpd#[-+]}" )
- tmps=( "${(@)tmps#[-+]}" )
fi
- fi
- compadd "${(@P)name}" "$expl[@]" -ld tmpd - "$tmpmd[@]" && ret=0
- compadd "${(@P)name}" "$expl[@]" -d tmps - "$tmpms[@]" && ret=0
-done
-return ret
+ compadd "$_args[@]" "$_expl[@]" -ld _tmpd - "$_tmpmd[@]" && _ret=0
+ compadd "$_args[@]" "$_expl[@]" -d _tmps - "$_tmpms[@]" && _ret=0
+ done
+done
+return _ret
diff --git a/Completion/Base/_jobs b/Completion/Base/_jobs
index 869aeeb8a..45983ad16 100644
--- a/Completion/Base/_jobs
+++ b/Completion/Base/_jobs
@@ -1,27 +1,85 @@
#autoload
-local expl disp jobs job jids
+local expl disp jobs job jids pfx='%' desc how expls
+
+_wanted jobs || return 1
+
+if [[ "$1" = -t ]]; then
+ zstyle -T ":completion:${curcontext}:jobs" prefix-needed &&
+ [[ "$PREFIX" != %* && compstate[nmatches] -ne 0 ]] && return 1
+ shift
+fi
+zstyle -t ":completion:${curcontext}:jobs" prefix-hidden && pfx=''
+zstyle -T ":completion:${curcontext}:jobs" verbose && desc=yes
if [[ "$1" = -r ]]; then
jids=( "${(@k)jobstates[(R)running*]}" )
shift
- _description expl 'running job'
+ expls='running job'
elif [[ "$1" = -s ]]; then
jids=( "${(@k)jobstates[(R)running*]}" )
shift
- _description expl 'suspended job'
+ expls='suspended job'
else
[[ "$1" = - ]] && shift
jids=( "${(@k)jobtexts}" )
- _description expl job
+ expls=job
fi
-disp=()
-jobs=()
-for job in "$jids[@]"; do
- disp=( "$disp[@]" "${(l:3:: ::%:)job} -- ${jobtexts[$job]}" )
- jobs=( "$jobs[@]" "$job" )
-done
+if [[ -n "$desc" ]]; then
+ disp=()
+ for job in "$jids[@]"; do
+ [[ -n "$desc" ]] &&
+ disp=( "$disp[@]" "${pfx}${(r:2:: :)job} -- ${(r:COLUMNS-8:: :)jobtexts[$job]}" )
+ done
+fi
+
+zstyle -s ":completion:${curcontext}:jobs" numbers how
+
+if [[ "$how" = (yes|true|on|1) ]]; then
+ jobs=( "$jids[@]" )
+else
+ local texts i text str tmp num max=0
-compadd "$@" "$expl[@]" -ld disp - "%$^jobs[@]"
+ # Find shortest unambiguous strings.
+ texts=( "$jobtexts[@]" )
+ jobs=()
+ for i in "$jids[@]"; do
+ text="$jobtexts[$i]"
+ str="${text%% *}"
+ if [[ "$text" = *\ * ]]; then
+ text="${text#* }"
+ else
+ text=""
+ fi
+ tmp=( "${(@M)texts:#${str}*}" )
+ num=1
+ while [[ -n "$text" && $#tmp -ge 2 ]]; do
+ str="${str} ${text%% *}"
+ if [[ "$text" = *\ * ]]; then
+ text="${text#* }"
+ else
+ text=""
+ fi
+ tmp=( "${(@M)texts:#${str}*}" )
+ (( num++ ))
+ done
+
+ [[ num -gt max ]] && max="$num"
+
+ jobs=( "$jobs[@]" "$str" )
+ done
+
+ if [[ "$how" = [0-9]## && max -gt how ]]; then
+ jobs=( "$jids[@]" )
+ else
+ [[ -z "$pfx" && -n "$desc" ]] && disp=( "${(@)disp#%}" )
+ fi
+fi
+
+if [[ -n "$desc" ]]; then
+ _all_labels jobs expl "$expls" compadd "$@" -ld disp - "%$^jobs[@]"
+else
+ _all_labels jobs expl "$expls" compadd "$@" - "%$^jobs[@]"
+fi
diff --git a/Completion/Base/_subscript b/Completion/Base/_subscript
index 2b827a117..60d45370b 100644
--- a/Completion/Base/_subscript
+++ b/Completion/Base/_subscript
@@ -1,4 +1,56 @@
-#defcomp -subscript-
+#compdef -subscript-
-_compalso -math- "$@"
-[[ ${(Pt)${COMMAND}} = assoc* ]] && complist -k "( ${(kP)${COMMAND}} )"
+local expl
+
+if [[ "$PREFIX" = :* ]]; then
+ _wanted characters expl 'character class' \
+ compadd -p: -S ':]' alnum alpha blank cntrl digit graph \
+ lower print punct space upper xdigit
+elif [[ ${(Pt)${compstate[parameter]}} = assoc* ]]; then
+ local suf
+
+ [[ "$RBUFFER" != \]* ]] && suf=']'
+
+ _wanted association-keys expl 'association key' \
+ compadd -S "$suf" - "${(@kP)${compstate[parameter]}}"
+elif [[ ${(Pt)${compstate[parameter]}} = array* ]]; then
+ local list i j ret=1 disp
+
+ _tags indexes parameters
+
+ while _tags; do
+ if _requested indexes; then
+ ind=( {1..${#${(P)${compstate[parameter]}}}} )
+ if zstyle -T ":completion:${curcontext}:indexes" verbose; then
+ list=()
+ for i in "$ind[@]"; do
+ if [[ "$i" = ${PREFIX}*${SUFFIX} ]]; then
+ list=( "$list[@]"
+ "${i}:$(print -D ${(P)${compstate[parameter]}[$i]})" )
+ else
+ list=( "$list[@]" '' )
+ fi
+ done
+ zformat -a list ' -- ' "$list[@]"
+ disp=( -d list)
+ else
+ disp=()
+ fi
+
+ if [[ "$RBUFFER" = \]* ]]; then
+ _all_labels -V indexes expl 'array index' \
+ compadd -S '' "$disp[@]" - "$ind[@]" && ret=0
+ else
+ _all_labels -V indexes expl 'array index' \
+ compadd -S ']' "$disp[@]" - "$ind[@]" && ret=0
+ fi
+ fi
+ _requested parameters && _parameters && ret=0
+
+ (( ret )) || return 0
+ done
+
+ return 1
+else
+ _compalso -math-
+fi
diff --git a/Completion/Base/_tilde b/Completion/Base/_tilde
index aef575e19..7ab058e01 100644
--- a/Completion/Base/_tilde
+++ b/Completion/Base/_tilde
@@ -1,10 +1,53 @@
-#defcomp -tilde-
+#compdef -tilde-
# We use all named directories and user names here. If this is too slow
# for you or if there are too many of them, you may want to use
-# `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.
+# `compadd -qS/ - "$friends[@]"' or something like that.
-compgen -nu -qS/
+local expl suf dirs list lines revlines i ret disp nm="$compstate[nmatches]"
+
+if [[ "$SUFFIX" = */* ]]; then
+ ISUFFIX="/${SUFFIX#*/}$ISUFFIX"
+ SUFFIX="${SUFFIX%%/*}"
+ suf=(-S '')
+else
+ suf=(-qS/)
+fi
+
+_tags users named-directories directory-stack
+
+while _tags; do
+ _requested users && _users "$suf[@]" "$@" && ret=0
+ _requested named-directories expl 'named directory' \
+ compadd "$suf[@]" "$@" - "${(@k)nameddirs}"
+
+ if _requested directory-stack &&
+ { ! zstyle -T ":completion:${curcontext}:directory-stack" prefix-needed ||
+ [[ "$PREFIX" = [-+]* || nm -eq compstate[nmatches] ]] }; then
+ if zstyle -T ":completion:${curcontext}:directory-stack" verbose; then
+ integer i
+
+ lines=("${PWD}" "${dirstack[@]}")
+
+ if [[ ( -prefix - && ! -o pushdminus ) ||
+ ( -prefix + && -o pushdminus ) ]]; then
+ revlines=( $lines )
+ for (( i = 1; i <= $#lines; i++ )); do
+ lines[$i]="$((i-1)) -- ${revlines[-$i]}"
+ done
+ else
+ for (( i = 1; i <= $#lines; i++ )); do
+ lines[$i]="$((i-1)) -- ${lines[$i]}"
+ done
+ fi
+ list=( ${PREFIX[1]}${^lines%% *} )
+ disp=( -ld lines )
+ else
+ list=( ${PREFIX[1]}{0..${#dirstack}} )
+ disp=()
+ fi
+ _all_labels -V directory-stack expl 'directory stack' \
+ compadd "$suf[@]" "$disp[@]" -Q - "$list[@]" && ret=0
+ fi
+ (( ret )) || return 0
+done
diff --git a/Completion/Base/_values b/Completion/Base/_values
index 4be3e8203..62cf0e409 100644
--- a/Completion/Base/_values
+++ b/Completion/Base/_values
@@ -1,322 +1,103 @@
#autoload
-setopt localoptions extendedglob
+local subopts opt usecc
-local name arg def descr xor str tmp ret=1 expl nm="$compstate[nmatches]"
-local snames odescr gdescr sep
-typeset -A names onames xors _values
+subopts=()
+while [[ "$1" = -(O*|C) ]]; do
+ case "$1" in
+ -C) usecc=yes; shift ;;
+ -O) subopts=( "${(@P)2}" ); shift 2 ;;
+ *) subopts=( "${(@P)1[3,-1]}" ); shift ;;
+ esac
+done
-# Probably fill our cache.
+if compvalues -i "$@"; then
-if [[ "$*" != "$_vals_cache_args" ]]; then
- _vals_cache_args="$*"
+ local noargs args opts descr action expl sep subc
+ local oldcontext="$curcontext"
- unset _vals_cache_{sep,descr,names,onames,snames,xors,odescr}
+ if ! compvalues -D descr action; then
- typeset -gA _vals_cache_{names,onames,xors}
- _vals_cache_snames=()
- _vals_cache_odescr=()
+ _wanted values || return 1
- # Get the separator, if any.
+ curcontext="${oldcontext%:*}:values"
- if [[ "$1" = -s ]]; then
- _vals_cache_sep="$2"
- shift 2
- fi
-
- # This is the description string for the values.
-
- _vals_cache_descr="$1"
- shift
-
- # Now parse the descriptions.
-
- while (( $# )); do
-
- # Get the `name', anything before an unquoted colon.
-
- if [[ "$1" = *[^\\]:* ]]; then
- name="${${${(M)1#*[^\\]:}[1,-2]}//\\\\:/:}"
- else
- name="$1"
- fi
-
- descr=''
- xor=''
-
- # Get a description, if any.
-
- if [[ "$name" = *\[*\] ]]; then
- descr="${${name#*\[}[1,-2]}"
- name="${name%%\[*}"
- fi
-
- # Get the names of other values that are mutually exclusive with
- # this one.
-
- if [[ "$name" = \(*\)* ]]; then
- xor="${${name[2,-1]}%%\)*}"
- name="${name#*\)}"
- fi
-
- # Finally see if this value may appear more than once.
-
- if [[ "$name" = \** ]]; then
- name="$name[2,-1]"
- else
- xor="$xor $name"
- fi
-
- # Store the information in the cache.
-
- _vals_cache_odescr=( "$_vals_cache_odescr[@]" "${name}:$descr" )
- [[ -n "$xor" ]] && _vals_cache_xors[$name]="${${xor##[ ]#}%%[ ]#}"
-
- # Get the description and store that.
-
- if [[ "$1" = *[^\\]:* ]]; then
- descr=":${1#*[^\\]:}"
- else
- descr=''
- fi
-
- if [[ "$descr" = ::* ]]; then
+ compvalues -V noargs args opts
- # Optional argument.
-
- _vals_cache_onames[$name]="$descr[3,-1]"
- elif [[ "$descr" = :* ]]; then
-
- # Mandatory argument.
-
- _vals_cache_names[$name]="$descr[2,-1]"
- else
-
- # No argument.
-
- _vals_cache_snames=( "$_vals_cache_snames[@]" "$name" )
- fi
- shift
- done
-fi
-
-snames=( "$_vals_cache_snames[@]" )
-names=( "${(@kv)_vals_cache_names}" )
-onames=( "${(@kv)_vals_cache_onames}" )
-xors=( "${(@kv)_vals_cache_xors}" )
-odescr=( "$_vals_cache_odescr[@]" )
-gdescr="$_vals_cache_descr"
-sep="$_vals_cache_sep"
-
-if [[ -n "$sep" ]]; then
-
- # We have a separator character. We parse the PREFIX and SUFFIX to
- # see if any of the values that must not appear more than once are
- # already on the line.
-
- while [[ "$PREFIX" = *${sep}* ]]; do
-
- # Get one part, remove it from PREFIX and put it into IPREFIX.
-
- tmp="${PREFIX%%${sep}*}"
- PREFIX="${PREFIX#*${sep}}"
- IPREFIX="${IPREFIX}${tmp}${sep}"
-
- # Get the value `name'.
-
- name="${tmp%%\=*}"
-
- if [[ "$tmp" = *\=* ]]; then
- _values[$name]="${tmp#*\=}"
- else
- _values[$name]=''
- fi
-
- # And remove the descriptions for the values this one makes
- # superfluous.
-
- if [[ -n "$xors[$name]" ]]; then
- snames=( "${(@)snames:#(${(j:|:)~${=xors[$name]}})}" )
- odescr=( "${(@)odescr:#(${(j:|:)~${=xors[$name]}}):*}" )
- unset {names,onames,xors}\[${^=tmp}\]
- fi
- done
- if [[ "$SUFFIX" = *${sep}* ]]; then
-
- # The same for the suffix.
+ if [[ "$PREFIX" = *\=* ]]; then
+ local name
- str="${SUFFIX%%${sep}*}"
- SUFFIX="${SUFFIX#*${sep}}"
- while [[ -n "$SUFFIX" ]]; do
- tmp="${PREFIX%%${sep}*}"
- if [[ "$SUFFIX" = *${sep}* ]]; then
- SUFFIX="${SUFFIX#*${sep}}"
+ name="${PREFIX%%\=*}"
+ if compvalues -L "$name" descr action; then
+ IPREFIX="${IPREFIX}${name}="
+ PREFIX="${PREFIX#*\=}"
else
- SUFFIX=''
+ local prefix suffix
+
+ prefix="${PREFIX#*\=}"
+ suffix="$SUFFIX"
+ PREFIX="$name"
+ SUFFIX=''
+ args=( "$args[@]" "$opts[@]" )
+ compadd -M 'r:|[_-]=* r:|=*' -D args - "${(@)args[@]%%:*}"
+
+ [[ $#args -ne 1 ]] && return 1
+
+ PREFIX="$prefix"
+ SUFFIX="$suffix"
+ IPREFIX="${IPREFIX}${args[1]%%:*}="
+ compvalues -L "${args[1]%%:*}" descr action subc
+ curcontext="${oldcontext%:*}:$subc"
fi
- PREFIX="${PREFIX#*${sep}}"
- IPREFIX="${IPREFIX}${tmp}${sep}"
-
- name="${tmp%%\=*}"
-
- if [[ "$tmp" = *\=* ]]; then
- _values[$name]="${tmp#*\=}"
+ else
+ compvalues -d descr
+ if [[ ${#noargs}+${#args}+${#opts} -ne 1 ]] && compvalues -s sep; then
+ sep=( "-qQS" "$sep" )
else
- _values[$name]=''
+ sep=()
fi
- if [[ -n "$xors[$name]" ]]; then
- snames=( "${(@)snames:#(${(j:|:)~${=xors[$name]}})}" )
- odescr=( "${(@)odescr:#(${(j:|:)~${=xors[$name]}}):*}" )
- unset {names,onames,xors}\[${^=tmp}\]
- fi
- done
- SUFFIX="$str"
- fi
-fi
-
-descr=''
-str="$PREFIX$SUFFIX"
-
-if [[ "$str" = *\=* ]]; then
-
- # The string from the line contains a `=', so we get the stuff before
- # it and after it and see what we can do here...
-
- name="${str%%\=*}"
- arg="${str#*\=}"
-
- if (( $snames[(I)${name}] )); then
-
- # According to our information, the value doesn't get an argument,
- # so give up.
-
- _message "\`${name}' gets no value"
- return 1
- elif (( $+names[$name] )); then
-
- # It has to get an argument, we skip over the name and complete
- # the argument (below).
-
- def="$names[$name]"
- if ! compset -P '*\='; then
- IPREFIX="${IPREFIX}${name}="
- PREFIX="$arg"
- SUFFIX=''
- fi
- elif (( $+onames[$name] )); then
+ _describe "$descr" \
+ noargs "$sep[@]" -M 'r:|[_-]=* r:|=*' -- \
+ args -S= -M 'r:|[_-]=* r:|=*' -- \
+ opts -qS= -M 'r:|[_-]=* r:|=*'
- # Gets an optional argument, same as previous case.
+ curcontext="$oldcontext"
- def="$onames[$name]"
- if ! compset -P '*\='; then
- IPREFIX="${IPREFIX}${name}="
- PREFIX="$arg"
- SUFFIX=''
+ return
fi
else
- local pre="$PREFIX" suf="$SUFFIX"
-
- # The part before the `=' isn't a known value name, so we see if
- # it matches only one of the known names.
-
- if [[ "$PREFIX" = *\=* ]]; then
- PREFIX="${PREFIX%%\=*}"
- pre="${pre#*\=}"
- SUFFIX=''
- else
- SUFFIX="${SUFFIX%%\=*}"
- pre="${suf#*\=}"
- suf=''
- fi
-
- tmp=( "${(@k)names}" "${(@k)onames}" )
- compadd -M 'r:|[-_]=* r:|=*' -D tmp - "$tmp[@]"
-
- if [[ $#tmp -eq 1 ]]; then
-
- # It does, so we use that name and immediatly start completing
- # the argument for it.
-
- IPREFIX="${IPREFIX}${tmp[1]}="
- PREFIX="$pre"
- SUFFIX="$suf"
-
- def="$names[$tmp[1]]"
- [[ -z "$def" ]] && def="$onames[$tmp[1]]"
- elif (( $#tmp )); then
- _message "ambiguous option \`${PREFIX}${SUFFIX}'"
- return 1
- else
- _message "unknown option \`${PREFIX}${SUFFIX}'"
- return 1
- fi
+ compvalues -C subc
+ curcontext="${oldcontext%:*}:$subc"
fi
-else
-
- # No `=', just complete value names.
-
- _description expl "$gdescr"
- [[ -n "$sep" && ${#snames}+${#names}+${#onames} -ne 1 ]] &&
- expl=( "-qS$sep" "$expl[@]" )
-
- tmp=''
- if [[ -n "$compconfig[describe_values]" &&
- "$compconfig[describe_values]" != *\!${words[1]}* ]]; then
- if _display tmp odescr -M 'r:|[_-]=* r:|=*'; then
- if (( $#snames )); then
- compadd "$expl[@]" -y tmp -M 'r:|[_-]=* r:|=*' - \
- "$snames[@]" && ret=0
- compadd -n -S= -J "_$gdescr" -M 'r:|[_-]=* r:|=*' - \
- "${(@k)names}" && ret=0
- compadd -n -qS= -J "_$gdescr" -M 'r:|[_-]=* r:|=*' - \
- "${(@k)onames}" && ret=0
- elif (( $#names )); then
- compadd -n -S= "$expl[@]" -y tmp -M 'r:|[_-]=* r:|=*' - \
- "${(@k)names}" && ret=0
- compadd -n -qS= -J "_$gdescr" -M 'r:|[_-]=* r:|=*' - \
- "${(@k)onames}" && ret=0
- else
- compadd -n -qS= "$expl[@]" -y tmp -M 'r:|[_-]=* r:|=*' - \
- "${(@k)onames}" && ret=0
- fi
- fi
- fi
- if [[ -z "$tmp" ]]; then
- compadd "$expl[@]" -M 'r:|[_-]=* r:|=*' - "$snames[@]" && ret=0
- compadd -S= "$expl[@]" -M 'r:|[_-]=* r:|=*' - "${(@k)names}" && ret=0
- compadd -qS= "$expl[@]" -M 'r:|[_-]=* r:|=*' - "${(@k)onames}" && ret=0
+ if ! _tags arguments; then
+ curcontext="$oldcontext"
+ return 1
fi
- return ret
-fi
-
-if [[ -z "$def" ]]; then
- _message 'no value'
- return 1
-else
- local action
-
- descr="${${${(M)def#*[^\\]:}[1,-2]}//\\\\:/:}"
- action="${${def#*[^\\]:}//\\\\:/:}"
- _description expl "$descr"
+ _description arguments expl "$descr"
# We add the separator character as a autoremovable suffix unless
# we have only one possible value left.
- [[ -n "$sep" && ${#snames}+${#names}+${#onames} -ne 1 ]] &&
+ [[ ${#snames}+${#names}+${#onames} -ne 1 ]] && compvalues -s sep &&
expl=( "-qS$sep" "$expl[@]" )
if [[ "$action" = -\>* ]]; then
- values=( "${(@kv)_values}" )
+ compvalues -v val_args
state="${${action[3,-1]##[ ]#}%%[ ]#}"
+ if [[ -n "$usecc" ]]; then
+ curcontext="${oldcontext%:*}:$subc"
+ else
+ context="$subc"
+ fi
compstate[restore]=''
return 1
else
- typeset -A values
+ typeset -A val_args
- values=( "${(@kv)_values}" )
+ compvalues -v val_args
if [[ "$action" = \ # ]]; then
@@ -332,36 +113,44 @@ else
eval ws\=\( "${action[3,-3]}" \)
- if _display tmp ws; then
- compadd "$expl[@]" -y tmp - "${(@)ws%%:*}"
- else
- _message "$descr"
- return 1
- fi
+ _describe "$descr" ws -M 'r:|[_-]=* r:|=*' "$subopts[@]"
+
elif [[ "$action" = \(*\) ]]; then
# Anything inside `(...)' is added directly.
- compadd "$expl[@]" - ${=action[2,-2]}
+ _all_labels arguments expl "$descr" \
+ compadd "$subopts[@]" - ${=action[2,-2]}
elif [[ "$action" = \{*\} ]]; then
# A string in braces is evaluated.
- eval "$action[2,-2]"
-
+ while _next_label arguments expl "$descr"; do
+ eval "$action[2,-2]"
+ done
elif [[ "$action" = \ * ]]; then
# If the action starts with a space, we just call it.
- ${(e)=~action}
+ eval "action=( $action )"
+ while _next_label arguments expl "$descr"; do
+ "$action[@]"
+ done
else
# Otherwise we call it with the description-arguments built above.
- action=( $=action )
- ${(e)action[1]} "$expl[@]" ${(e)~action[2,-1]}
+ eval "action=( $action )"
+ _all_labels arguments expl "$descr" \
+ "$action[1]" "$subopts[@]" "${(@)action[2,-1]}"
fi
fi
-fi
-[[ nm -ne "$compstate[nmatches]" ]]
+ curcontext="$oldcontext"
+
+ [[ nm -ne "$compstate[nmatches]" ]]
+else
+ curcontext="$oldcontext"
+
+ return 1;
+fi
diff --git a/Completion/Builtins/_autoload b/Completion/Builtins/_autoload
index 4f506baeb..238b79e95 100644
--- a/Completion/Builtins/_autoload
+++ b/Completion/Builtins/_autoload
@@ -1,3 +1,10 @@
-#defcomp autoload
+#compdef autoload
-complist -s '${^fpath}/*(N:t)'
+local expl
+
+if (( $words[(I)[-+]*w*] )); then
+ _description files expl 'zwc file'
+ _files "$expl[@]" -g '*.zwc'
+else
+ _wanted functions expl 'shell function' compadd - ${^fpath}/*(N:t)
+fi
diff --git a/Completion/Builtins/_cd b/Completion/Builtins/_cd
index f3ce67ec7..803bcbda5 100644
--- a/Completion/Builtins/_cd
+++ b/Completion/Builtins/_cd
@@ -1,3 +1,47 @@
-#defcomp cd
+#compdef cd chdir 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 - or +, 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.
+
+setopt localoptions nonomatch
+
+local expl
+
+if [[ CURRENT -eq 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 )) && _wanted -C replacement strings expl replacement compadd $rep
+elif _popd || [[ $PREFIX != (\~|/|./|../)* && $#cdpath -ne 0 ]]; then
+ local tdir tdir2
+
+ # With cdablevars, we can convert foo/bar/... to ~foo/bar/... if
+ # there is no directory foo. In that case we could also complete
+ # variable names, but it hardly seems worth it.
+ # Note we need a tilde because cdablevars also allows user home
+ # directories, hence we also need nonomatch to suppress error messages.
+ if [[ -o cdablevars && -n "$PREFIX" && ! -d ${tdir::=${PREFIX%%/*}} &&
+ -d ${~tdir2::="~$tdir"} ]]; then
+ PREFIX="~$PREFIX"
+ _wanted directories expl directory _path_files -/
+ else
+ local tmpcdpath
+ tmpcdpath=(${${(@)cdpath:#.}:#$PWD})
+ _alternative \
+ 'local-directories:local directories:_path_files -/' \
+ "path-directories:directories in cdpath:_path_files -W tmpcdpath -/"
+ fi
+else
+ _wanted directories expl directory _path_files -/
+fi
diff --git a/Completion/Builtins/_compdef b/Completion/Builtins/_compdef
index 1df5758b3..d47a560c9 100644
--- a/Completion/Builtins/_compdef
+++ b/Completion/Builtins/_compdef
@@ -1,22 +1,40 @@
#compdef compdef
-local func base=2
+local state line expl list disp
-while [[ $words[base] = -* ]]; do
- case $words[base] in
- -d) delete=yes ;;
- -p) type=pattern ;;
- -k) type=key ;;
- esac
- (( base++ ))
-done
+_arguments -C -s \
+ '(-d)-a[make function autoloadable]' \
+ '(-d -p -P)-n[leave existing definitions intact]' \
+ '(-a -n -p -P -k -K)-d[delete]:*:completed command:->ccom' \
+ '(-n -d -P -k -K)-p[completion for command matching pattern]:completion function:->cfun:pattern' \
+ '(-n -d -p -k -K)-P[as -p for commands without own completion]:completion function:->cfun:pattern' \
+ '(-d -p -P -K)-k[define widget and key binding]:completion function:->cfun:widget name::style:->style:*:key' \
+ '(-d -p -P -k)-K[define multiple widgets based on function]:completion function:->cfun:widget name::style:->style:*:key' \
+ '1:completion function:->cfun' \
+ '2:commands:_command_names'
+
-if [ "$delete" ]; then
- compadd ${(k)_comps}
-else
- if [[ CURRENT -eq base ]]; then
- for func in ${^~fpath:/.}/_(|*[^~])(N:t); compadd -P_ - ${func#_}
- else
- compgen -c
- fi
-fi
+case $state in
+ ccom)
+ _wanted commands expl 'completed command' compadd - ${(k)_comps}
+ ;;
+ cfun)
+ if _wanted functions; then
+ list=( ${^fpath:/.}/_(|*[^~])(N:t) )
+ if zstyle -T ":completion:${curcontext}:functions" prefix-hidden; then
+ disp=( ${list[@]#_} )
+ _all_labels functions expl 'completion function' \
+ compadd -d disp - "$list[@]"
+ else
+ _all_labels functions expl 'completion function' compadd - "$list[@]"
+ fi
+ fi
+ ;;
+ style)
+ _wanted widgetstyle expl 'widget style' \
+ compadd -M 'r:|-=* r:|=*' \
+ complete-word delete-char-or-list expand-or-complete \
+ expand-or-complete-prefix list-choices menu-complete \
+ menu-expand-or-complete reverse-menu-complete
+ ;;
+esac
diff --git a/Completion/Builtins/_disable b/Completion/Builtins/_disable
index 063b65a7d..b3c2632ed 100644
--- a/Completion/Builtins/_disable
+++ b/Completion/Builtins/_disable
@@ -1,6 +1,8 @@
-#defcomp disable
+#compdef disable
-[[ -mcurrent -1 -*a* ]] && complist -ea
-[[ -mcurrent -1 -*f* ]] && complist -eF
-[[ -mcurrent -1 -*r* ]] && complist -ew
-[[ ! -mcurrent -1 -* ]] && complist -eB
+_arguments -C -s \
+ "(-f -r)-a[act on aliases]:*:aliases:(${(k)aliases} ${(k)galiases})" \
+ "(-a -r)-f[act on functions]:*:functions:(${(k)functions})" \
+ "(-a -f)-r[act on reserved words]:*:reserved-words:(${(k)reswords})" \
+ '-m[treat arguments as patterns]' \
+ "*:builtin command:(${(k)builtins})"
diff --git a/Completion/Builtins/_emulate b/Completion/Builtins/_emulate
new file mode 100644
index 000000000..82096a77e
--- /dev/null
+++ b/Completion/Builtins/_emulate
@@ -0,0 +1,6 @@
+#compdef emulate
+
+_arguments -C -s \
+ '-L[set local_options and local_traps as well]' \
+ '-R[reset all options instead of only those needed for script portability]' \
+ '1::shell to emulate:(zsh sh ksh csh)'
diff --git a/Completion/Builtins/_enable b/Completion/Builtins/_enable
index 22ff53ee7..991286276 100644
--- a/Completion/Builtins/_enable
+++ b/Completion/Builtins/_enable
@@ -1,6 +1,8 @@
-#defcomp enable
+#compdef enable
-[[ -mcurrent -1 -*a* ]] && complist -da
-[[ -mcurrent -1 -*f* ]] && complist -dF
-[[ -mcurrent -1 -*r* ]] && complist -dw
-[[ ! -mcurrent -1 -* ]] && complist -dB
+_arguments -C -s \
+ "(-f -r)-a[act on aliases]:*:aliases:(${(k)dis_aliases})" \
+ "(-a -r)-f[act on functions]:*:functions:(${(k)dis_functions})" \
+ "(-a -f)-r[act on reserved words]:*:reserved-words:(${(k)dis_reswords})" \
+ '-m[treat arguments as patterns]' \
+ "*:builtin command:(${(@k)dis_builtins})"
diff --git a/Completion/Builtins/_fc b/Completion/Builtins/_fc
index f0d2c03fd..e97492604 100644
--- a/Completion/Builtins/_fc
+++ b/Completion/Builtins/_fc
@@ -1,7 +1,27 @@
-#defcomp fc
+#compdef fc history
-if [[ -mcurrent -1 -*e ]]; then
- complist -c
-elif [[ -mcurrent -1 -[ARWI]## ]]; then
- _files
+local fc_common
+
+fc_common=( \
+ '(-A -R -W -I)-m[treat first argument as a pattern]' \
+ '(-A -R -W -I)-r[reverse order of the commands]' \
+ '(-A -R -W -I -e)-n[suppress line numbers]' \
+ '(-A -R -W -I -e -f -E -i)-d[print time-stamps]' \
+ '(-A -R -W -I -e -d -E -i)-f[mm/dd/yyyy format time-stamps]' \
+ '(-A -R -W -I -e -d -f -i)-E[dd.mm.yyyy format time-stamps]' \
+ '(-A -R -W -I -e -d -f -E)-i[yyyy-mm-dd format time-stamps]' \
+ '(-A -R -W -I -e)-D[print elapsed times]' \
+ '(-A -R -W -I)*::commands:_command_names -e' )
+
+if [[ $words[1] = *history ]]; then
+ _arguments -C -s "$fc_common[@]"
+else
+ _arguments -C -s \
+ '(-A -R -W -I -e)-l[list resulting commands on stdout]' \
+ '(-A -R -W -I -l -n -d -f -E -i -D)-e[specify editor to invoke]:editor to invoke:_command_names -e' \
+ '(-l -m -e -r -n -d -f -E -i -D -A -W *)-R[read history from file]:history file:_files' \
+ '(-l -m -e -r -n -d -f -E -i -D -R -W *)-A[append history to file]:history file:_files' \
+ '(-l -m -e -r -n -d -f -E -i -D -R -A *)-W[write history to file]:history file:_files' \
+ '(-l -m -e -r -n -d -f -E -i -D -A -W *)-I[read/write new events only]:history file:_files' \
+ "$fc_common[@]"
fi
diff --git a/Completion/Builtins/_nothing b/Completion/Builtins/_nothing
index 35a2558cc..38f6bee77 100644
--- a/Completion/Builtins/_nothing
+++ b/Completion/Builtins/_nothing
@@ -1,3 +1,3 @@
-#compdef true false
+#compdef true false log times whoami
_message 'no argument or option'
diff --git a/Completion/Builtins/_pids b/Completion/Builtins/_pids
index 0ffda900b..7dec90e7d 100644
--- a/Completion/Builtins/_pids
+++ b/Completion/Builtins/_pids
@@ -3,16 +3,32 @@
# If given the `-m <pattern>' option, this tries to complete only pids
# of processes whose command line match the `<pattern>'.
-local list expl match
+local out list expl match desc listargs args
+
+_wanted processes || return 1
if [[ "$1" = -m ]]; then
match="${2}*"
shift 2
fi
-_description expl 'process ID'
+zstyle -s ":completion:${curcontext}:pids" command args
+
+out="$(_call pids ps 2>/dev/null)"
-list=("${(@Mr:COLUMNS-1:)${(f@)$(ps ${=compconfig[ps_listargs]:-$=compconfig[ps_args]} 2>/dev/null)}[2,-1]:#[ ]#${PREFIX}[0-9]#${SUFFIX}[ ]*${~match}}")
+if zstyle -T ":completion:${curcontext}:processes" verbose; then
+ zstyle -s ":completion:${curcontext}:pids-list" command listargs
+ (( $#listargs )) || listargs=( "$args[@]" )
+ if [[ "$listargs" = "$args" ]]; then
+ list=("${(@Mr:COLUMNS-1:)${(f@)out}[2,-1]:#[ ]#${PREFIX}[0-9]#${SUFFIX}[ ]*${~match}}")
+ else
+ list=("${(@Mr:COLUMNS-1:)${(f@)$(_call pids-list ps 2>/dev/null)}[2,-1]:#[ ]#${PREFIX}[0-9]#${SUFFIX}[ ]*${~match}}")
+ fi
+ desc=(-ld list)
+else
+ desc=()
+fi
-compadd "$expl[@]" "$@" -ld list - \
- ${${${(M)${(f)"$(ps $=compconfig[ps_args] 2>/dev/null)"}[2,-1]:#*${~match}}## #}%% *}
+_all_labels processes expl 'process ID' \
+ compadd "$@" "$desc[@]" - \
+ ${${${(M)${(f)"${out}"}[2,-1]:#[ ]#${PREFIX}[0-9]#${SUFFIX}[ ]#*${~match}}## #}%% *}
diff --git a/Completion/Builtins/_popd b/Completion/Builtins/_popd
index 9054befb7..2a3413253 100644
--- a/Completion/Builtins/_popd
+++ b/Completion/Builtins/_popd
@@ -5,36 +5,39 @@
# way round if pushdminus is set). Note that this function is also called
# from _cd for cd and pushd.
-emulate -L zsh
setopt extendedglob nonomatch
-[[ $PREFIX = [-+]* ]] || return 1
+local expl list lines revlines disp
-local expl list lines revlines ret=1 i
+! zstyle -T ":completion:${curcontext}:directory-stack" prefix-needed ||
+ [[ $PREFIX = [-+]* ]] || return 1
-IPREFIX=$PREFIX[1]
-PREFIX=$PREFIX[2,-1]
+_wanted directory-stack || return 1
-# get the list of directories with their canonical number
-# and turn the lines into an array, removing the current directory
-lines=( ${${(f)"$(dirs -v)"}##0*} )
-if [[ ( $IPREFIX = - && ! -o pushdminus ) ||
- ( $IPREFIX = + && -o pushdminus ) ]]; then
- integer i
- revlines=( $lines )
- for (( i = 1; i <= $#lines; i++ )); do
- lines[$i]="$((i-1)) -- ${revlines[-$i]##[0-9]#[ ]#}"
- done
+if zstyle -T ":completion:${curcontext}:directory-stack" verbose; then
+ # get the list of directories with their canonical number
+ # and turn the lines into an array, removing the current directory
+ lines=("${dirstack[@]}")
+
+ if [[ ( $PREFIX[1] = - && ! -o pushdminus ) ||
+ ( $PREFIX[1] = + && -o pushdminus ) ]]; then
+ integer i
+ revlines=( $lines )
+ for (( i = 1; i <= $#lines; i++ )); do
+ lines[$i]="$((i-1)) -- ${revlines[-$i]##[0-9]#[ ]#}"
+ done
+ else
+ for (( i = 1; i <= $#lines; i++ )); do
+ lines[$i]="$i -- ${lines[$i]##[0-9]#[ ]#}"
+ done
+ fi
+ # get the array of numbers only
+ list=( ${PREFIX[1]}${^lines%% *} )
+ disp=( -ld lines )
else
- for (( i = 1; i <= $#lines; i++ )); do
- lines[$i]="$i -- ${lines[$i]##[0-9]#[ ]#}"
- done
+ list=( ${PREFIX[1]}{0..${#dirstack}} )
+ disp=()
fi
-# get the array of numbers only
-list=(${lines%% *})
-_description expl 'directory stack index'
-compadd "$expl[@]" -ld lines -V dirs -Q - "$list[@]" && ret=0
-[[ -z $compstate[list] ]] && compstate[list]=list && ret=0
-[[ -n $compstate[insert] ]] && compstate[insert]=menu && ret=0
-
-return ret
+
+_all_labels -V directory-stack expl 'directory stack' \
+ compadd "$@" "$disp[@]" -Q - "$list[@]"
diff --git a/Completion/Builtins/_sched b/Completion/Builtins/_sched
index 1e8ae3445..98ecb3642 100644
--- a/Completion/Builtins/_sched
+++ b/Completion/Builtins/_sched
@@ -1,3 +1,23 @@
-#defcomp sched
+#compdef sched
-[[ -position 2 -1 ]] && _normal "$@"
+local expl lines disp
+
+if [[ CURRENT -eq 2 ]]; then
+ if compset -P -; then
+ _wanted -C - jobs || return 1
+
+ lines=(${(f)"$(sched)"})
+ if zstyle -T ":completion:${curcontext}:jobs" verbose; then
+ disp=( -ld lines )
+ else
+ disp=()
+ fi
+ [[ -z $lines ]] || _all_labels jobs expl 'scheduled jobs' \
+ compadd "$disp[@]" - {1..$#lines}
+ return
+ else
+ _message 'time specification'
+ return 1
+ fi
+fi
+compset -n 3 && _normal
diff --git a/Completion/Builtins/_signals b/Completion/Builtins/_signals
index c79350044..aa95a8499 100644
--- a/Completion/Builtins/_signals
+++ b/Completion/Builtins/_signals
@@ -20,17 +20,19 @@ done
[[ "$1" = -(|-) ]] && shift
-if _wanted signals expl signal &&
- { [[ -z "$minus" ]] || ! _style signals prefix-needed ||
+if _wanted signals &&
+ { [[ -z "$minus" ]] ||
+ ! zstyle -T ":completion:${curcontext}:signals" prefix-needed ||
[[ "$PREFIX" = -* ]] } ; then
local disp tmp
- if _style signals prefix-hidden; then
+ if zstyle -t ":completion:${curcontext}:signals" prefix-hidden; then
tmp=( "${(@)signals[1,last]}" )
disp=(-d tmp)
else
disp=()
fi
- compadd "$@" "$expl[@]" "$disp[@]" -M 'm:{a-z}=${A-Z}' - \
- "${minus}${(@)^signals[1,last]}"
+ _all_labels signals expl signal \
+ compadd "$@" "$disp[@]" -M 'm:{a-z}={A-Z}' - \
+ "${minus}${(@)^signals[1,last]}"
fi
diff --git a/Completion/Builtins/_stat b/Completion/Builtins/_stat
index 3cdbb2618..5ba06388b 100644
--- a/Completion/Builtins/_stat
+++ b/Completion/Builtins/_stat
@@ -1,10 +1,20 @@
#compdef stat
+local expl ret=1
+
if [[ "$words[CURRENT-1]" = -[AH] ]]; then
- compgen -A
+ _arrays
else
- [[ "$PREFIX[1]" = + ]] &&
- compadd - +device +inode +mode +nlink +uid +gid +rdev +size \
- +atime +mtime +ctime +blksize +block +link
- _files
+ _tags files options || return 1
+
+ while _tags; do
+ _requested files && _files && ret=0
+ _requested options &&
+ { ! zstyle -T ":completion:${curcontext}:options" prefix-needed ||
+ [[ "$PREFIX[1]" = + || ret -eq 1 ]] } &&
+ _all_labels options expl 'inode element' \
+ compadd - +device +inode +mode +nlink +uid +gid +rdev \
+ +size +atime +mtime +ctime +blksize +block +link
+ (( ret )) || return 0
+ done
fi
diff --git a/Completion/Builtins/_zcompile b/Completion/Builtins/_zcompile
new file mode 100644
index 000000000..5ec6f96ce
--- /dev/null
+++ b/Completion/Builtins/_zcompile
@@ -0,0 +1,22 @@
+#compdef zcompile
+
+local context state line expl
+typeset -A opt_args
+
+_arguments -s \
+ '(-c -m -a)-U[don'\''t expand aliases]' \
+ '(-M)-R[mark as read]' \
+ '(-R)-M[mark as mapped]' \
+ '(-c -z -m -a)-k[ksh-style autoloading]' \
+ '(-c -k -m -a)-z[zsh-style autoloading]' \
+ '(-U -z -k)-c[currently defined functions]' \
+ '(-U -z -k)-m[use names as patterns]' \
+ '(-U -z -k)-a[write autoload functions]' \
+ ':zwc file:_files' \
+ '*:function:->function' && return 0
+
+if (( $+opt_args[-c] )); then
+ _wanted functions expl 'function to write' compadd - ${(k)functions}
+else
+ _wanted file expl 'zsh source file' _files
+fi
diff --git a/Completion/Builtins/_zftp b/Completion/Builtins/_zftp
index 9be9c94db..0d6530dfc 100644
--- a/Completion/Builtins/_zftp
+++ b/Completion/Builtins/_zftp
@@ -1,50 +1,92 @@
-#defpatcomp zf*
-
-# Don't try any more completion after this.
-_compskip=1
+#compdef -p zf*
# Completion for zftp builtin and zf* functions. The functions
-# zfcd_match and zfget_match (used for old-style completion)
+# zfcd_match and zfget_match (also used for old-style completion)
# need to be installed for remote file and directory completion to work.
-local subcom
+# emulate -L zsh
+
+# Don't try any more completion after this.
+_compskip=all
+
+local subcom expl curcontext="${curcontext}"
-if [[ $COMMAND = zftp ]]; then
- if [[ $CURRENT -eq 1 ]]; then
- compadd -m open params user login type ascii binary mode put \
- putat get getat append appendat ls dir local remote mkdir rmdir
+if [[ $words[1] = zftp ]]; then
+ if [[ $CURRENT -eq 2 ]]; then
+ _wanted commands expl sub-command \
+ compadd open params user login type ascii binary mode put \
+ putat get getat append appendat ls dir local remote mkdir rmdir \
+ session rmsession
return
fi
- subcom=$1
+ subcom=$words[2]
+ curcontext="${curcontext/:zftp:/:zftp-${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
- ;;
+ # complete remote directories
+ _wanted directories && zfcd_match $PREFIX $SUFFIX
+ ;;
*(get(|at)|gcp|delete|remote))
- # complete remote files
- zfget_match $PREFIX $SUFFIX
- (( $#reply )) && compadd -F fignore -m $reply
- ;;
+ # complete remote files
+ _wanted files && zfget_match $PREFIX $SUFFIX
+ ;;
*(put(|at)|pcp))
- # complete local files
- _files
- ;;
+ # complete local files
+ _wanted files && _files
+ ;;
*(open|anon|params))
- # complete hosts: should do cleverer stuff with user names
- complist -k hosts
- ;;
+ # complete hosts: should do cleverer stuff with user names
+ _wanted hosts && _hosts
+ ;;
+
+ *(goto|mark))
+ # complete bookmarks. First decide if ncftp mode is go.
+ _wanted bookmarks || return 1
+ if [[ $words[2] = -*n* ]]; then
+ if [[ -f ~/.ncftp/bookmarks ]]; then
+ _all_labels bookmarks expl bookmark \
+ compadd - $(awk -F, 'NR > 2 { print $1 }' ~/.ncftp/bookmarks)
+ fi
+ else
+ if [[ -f ${ZFTP_BMFILE:=${ZDOTDIR:-$HOME}/.zfbkmarks} ]]; then
+ _all_labels bookmarks expl bookmark \
+ compadd - $(awk '{print $1}' $ZFTP_BMFILE)
+ fi
+ fi
+ ;;
+
+ *session)
+ # complete sessions, excluding the current one.
+ _wanted sessions expl 'another FTP session' \
+ compadd - ${$(zftp session):#$ZFTP_SESSION}
+ ;;
+
+ *transfer)
+ # complete arguments like sess1:file1 sess2:file2
+ if [[ $PREFIX = *:* ]]; then
+ # complete file in the given session
+ _wanted files || return 1
+ local sess=${PREFIX%%:*} oldsess=$ZFTP_SESSION
+ compset -p $(( $#sess + 1 ))
+ [[ -n $sess ]] && zftp session $sess
+ zfget_match $PREFIX $SUFFIX
+ [[ -n $sess && -n $oldsess ]] && zftp session $oldsess
+ else
+ # note here we can complete the current session
+ _wanted sessions expl 'FTP session' compadd -S : - $(zftp session)
+ fi
+ ;;
*)
- # dunno... try ordinary completion after all.
- unset _compskip
- ;;
+ # dunno... try ordinary completion after all.
+ _compskip=''
+ return 1
+ ;;
esac
diff --git a/Completion/Builtins/_zpty b/Completion/Builtins/_zpty
index b197b4128..d8c77ff2e 100644
--- a/Completion/Builtins/_zpty
+++ b/Completion/Builtins/_zpty
@@ -7,17 +7,17 @@ _arguments -C -s \
'(-d -w -r -L)-b[io to pseudo-terminal blocking]' \
'(-e -b -w -r -L)-d[delete command]:*:name:->name' \
'(-e -b -d -r -L)-w[send string to command]:name:->name:*:strings to write' \
- '(-e -b -d -w -L)-r[read string from command]:name:->name:param:_parameters:*:nothing:_nothing' \
+ '(-e -b -d -w -L *)-r[read string from command]:name:->name:param:_parameters' \
'(-e -b -d -w -r)-L[list defined commands as calls]' \
- '*::args:_normal'
+ '(-r)*::args:_normal'
-if [[ $state = name ]] && _wanted zptynames expl 'zpty command names'; then
+if [[ $state = name ]] && _wanted names; then
list=( ${${(f)"$(zpty)"}#*\) } )
names=( ${list%%:*} )
if zstyle -T ":completion:${curcontext}" verbose; then
zformat -a list ' --' ${${(f)"$(zpty)"}#*\) }
- compadd "$expl[@]" -d list - "$names[@]"
+ _all_labels names expl 'zpty command names' compadd -d list - "$names[@]"
else
- compadd "$expl[@]" - "$names[@]"
+ _all_labels names expl 'zpty command names' compadd - "$names[@]"
fi
fi
diff --git a/Completion/Builtins/_zstyle b/Completion/Builtins/_zstyle
index f072f79ae..cd470598a 100644
--- a/Completion/Builtins/_zstyle
+++ b/Completion/Builtins/_zstyle
@@ -1,7 +1,8 @@
#compdef zstyle
-local curcontext="$curcontext" state ostate line expl ctop
-local nm=$compstat[nmatches]
+local curcontext="$curcontext" state context ostate line expl ctop
+local nm=$compstate[nmatches] mesg
+typeset -A opt_args
typeset -A styles
# Assoc array of styles; the values give the possible top-level
@@ -9,15 +10,18 @@ typeset -A styles
# followed by a colon, followed by a state to enter, empty if none.
styles=(
accept-exact c:bool
+ add-space c:bool
arguments c:
auto-description c:
- cache-path 'c:_path_files -/'
+ break c:
completer c:completer
completions c:
condition c:
- cursor c:bool
+ cursor c:cursor
disable-stat c:bool
+ domains c:
expand c:
+ file-patterns c:filepat
format c:
glob c:
group-name c:
@@ -26,8 +30,9 @@ styles=(
hidden c:bool
hosts c:_hosts
hosts-ports c:host-port
- hosts-ports-users c:host-port-user
- ignored-suffixes c:
+ users-hosts-ports c:user-host-port
+ ignore-parents c:ignorepar
+ ignored-patterns c:
insert-unambiguous c:bool
last-prompt c:bool
list c:listwhen
@@ -36,21 +41,26 @@ styles=(
list-packed c:bool
list-rows-first c:bool
local c:
+ matcher-list c:
max-errors c:
menu c:boolauto
numbers c:bool
original c:bool
- path 'c:_path_files -/'
+ packageset c:packageset
+ path 'c:_wanted directories expl directory _path_files -/'
ports c:_ports
prefix-hidden c:bool
prefix-needed c:bool
prompt c:
remove-all-dups c:bool
+ single-ignored c:single-ignored
sort c:bool
- tag-order c:tag
special-dirs c:sdirs
+ squeeze-slashes c:bool
stop c:stop
+ subst-glob-only c:
substitute c:
+ tag-order c:tag
users c:_users
users-hosts c:user-host
verbose c:bool
@@ -83,9 +93,20 @@ while [[ -n $state ]]; do
case "$ostate" in
contexts)
- if [[ $PREFIX != :*: ]]; then
- _wanted contexts expl context &&
- compadd -P : -S : "$expl[@]" completion zftp
+ if _wanted contexts; then
+ if [[ $PREFIX != :*: ]]; then
+ _all_labels contexts expl context compadd -P : -S : completion zftp
+ elif [[ $PREFIX = :completion:* ]]; then
+ mesg=''
+ case "$PREFIX" in
+ :completion:[^:]#) mesg=function ;;
+ :completion:[^:]#:[^:]#) mesg=completer ;;
+ :completion:[^:]#:[^:]#:[^:]#) mesg='command or context' ;;
+ :completion:[^:]#:[^:]#:[^:]#:[^:]#) mesg=argument ;;
+ :completion:[^:]#:[^:]#:[^:]#:[^:]#:[^:]#) mesg=tag ;;
+ esac
+ [[ -n "$mesg" ]] && _message "$mesg"
+ fi
fi
;;
@@ -96,8 +117,8 @@ while [[ -n $state ]]; do
else
ctop=cz
fi
- _wanted styles expl style &&
- compadd "$expl[@]" - ${(k)styles[(R)[^:]#[$ctop][^:]#:*]}
+ _wanted styles expl style \
+ compadd -M 'r:|-=* r:|=*' - ${(k)styles[(R)[^:]#[$ctop][^:]#:*]}
;;
style-arg)
@@ -105,66 +126,116 @@ while [[ -n $state ]]; do
;;
bool)
- _wanted values expl boolean &&
- compadd "$expl[@]" true false
+ _wanted values expl boolean compadd true false
;;
boolauto)
- _wanted values expl boolean &&
- compadd "$expl[@]" true false auto select
+ _wanted values expl boolean compadd true false auto select
+ ;;
+
+ cursor)
+ if [[ "$words[2]" = *:completion:inc* ]]; then
+ _wanted values expl 'cursor positioning' compadd complete key default
+ elif [[ "$words[2]" = *:completion::* ]]; then
+ _wanted values expl 'cursor positioning' compadd true false
+ else
+ _wanted values expl 'cursor positioning' \
+ compadd complete key default true false
+ fi
;;
completer)
- _wanted values expl completer &&
- compadd "$expl[@]" _complete _approximate _correct _match \
- _expand _list _menu _oldlist
+ _wanted values expl completer \
+ compadd _complete _approximate _correct _match \
+ _expand _list _menu _oldlist _next_tags
;;
- host-port*)
+ user-host-port)
+ if [[ $PREFIX != *[@:]* ]]; then
+ _users -S @
+ elif [[ $PREFIX = *[@:]*[[@:]* ]]; then
+ compset -P 2 '*[:@]'
+ _ports
+ else
+ compset -P 1 '*[:@]'
+ _hosts -S :
+ fi
+ ;;
+
+ host-port)
if [[ $PREFIX != *:* ]]; then
_hosts -S :
- elif [[ $ostate != *user || $PREFIX != *:*:* ]]; then
+ else
compset -P 1 '*:'
_ports
- else
- compset -P 2 '*:'
- _users
fi
;;
listwhen)
- _wanted values expl 'when to list completions' &&
- compadd "$expl[@]" always never sometimes
+ _wanted values expl 'when to list completions' \
+ compadd always never sometimes
+ ;;
+
+ packageset)
+ _wanted values expl 'default package set' \
+ compadd available installed uninstalled
;;
progress)
- _wanted values expl 'progress meter style' &&
- compadd "$expl[@]" none bar percent
+ _wanted values expl 'progress meter style' \
+ compadd none bar percent
;;
sdirs)
- _wanted values expl 'whether to complete . or ..' &&
- compadd "$expl[@]" true false ..
+ _wanted values expl 'whether to complete . or ..' \
+ compadd true false ..
;;
stop)
- _wanted values expl 'when to insert matches' &&
- compadd "$expl[@]" true false verbose
+ _wanted values expl 'when to insert matches' \
+ compadd true false verbose
;;
tag)
- _wanted tags expl tag && compadd "$expl[@]" - $taglist
+ compset -q
+ if compset -P '*:*:'; then
+ _message description
+ elif compset -P '*:'; then
+ _message 'tag alias'
+ else
+ _wanted tags expl tag compadd - $taglist
+ fi
+ ;;
+
+ filepat)
+ if compset -P '*:*:'; then
+ _message description
+ elif compset -P '*:'; then
+ _message tag
+ else
+ _message 'glob patterns'
+ fi
;;
user-host)
- if [[ $PREFIX = *:* ]]; then
- compset -P '*:'
+ if [[ $PREFIX = *[@:]* ]]; then
+ compset -P '*[@:]'
_hosts
else
- _users
+ _users -S @
fi
;;
+ ignorepar)
+ _wanted values expl 'which parents to ignore' \
+ compadd parent pwd .. directory
+ ;;
+
+ single-ignored)
+ _wanted values expl 'how to handle a single ignored match' \
+ compadd - show menu
+ ;;
+
_*)
${=ostate}
;;
diff --git a/Completion/Commands/_complete_help b/Completion/Commands/_complete_help
index cfefdcf90..cfc922df5 100644
--- a/Completion/Commands/_complete_help
+++ b/Completion/Commands/_complete_help
@@ -1,35 +1,80 @@
#compdef -k complete-word \C-xh
_complete_help() {
- local _sort_tags=_help_sort_tags text i
- typeset -A help_tags
- typeset -U help_contexts
-
- help_contexts=()
+ local _sort_tags=_help_sort_tags text i j k
+ typeset -A help_funcs help_tags help_sfuncs help_styles
compadd() { return 1 }
+ zstyle() {
+ local _f="${${(@)${(@)funcstack[2,(i)_(main_complete|complete|approximate|normal)]}:#_(wanted|requested|loop|try)}% *}"
+
+ [[ -z "$_f" ]] && _f="${${(@)funcstack[2,(i)_(main_complete|complete|approximate|normal)]}:#_(wanted|requested|loop|try)}"
+
+ if [[ "$help_sfuncs[$2]" != *${_f}* ||
+ "$help_styles[${2}${_f}]" != *${3}* ]]; then
+ [[ "$help_sfuncs[$2]" != *${_f}* ]] &&
+ help_sfuncs[$2]="${help_sfuncs[$2]}:${_f}"
+ local _t
+
+ case "$1" in
+ -s) _t='[string] ';;
+ -a) _t='[array] ';;
+ -h) _t='[assoc] ';;
+ *) _t='[boolean]';;
+ esac
+ help_styles[${2}${_f}]="${help_styles[${2}${_f}]},${_t} ${3}:${_f}"
+ fi
+ builtin zstyle "$@"
+ }
_main_complete
- unfunction compadd
+ unfunction compadd zstyle
- for i in "$help_contexts[@]"; do
+ for i in "${(@ok)help_funcs}"; do
text="${text}
-tags in context \`${i}': ${help_tags[$i]}"
+tags in context :completion:${i}:"
+ tmp=()
+ for j in "${(@s.:.)help_funcs[$i][2,-1]}"; do
+ tmp=( "$tmp[@]" "${(@s.,.)help_tags[${i}${j}][2,-1]}" )
+ done
+ zformat -a tmp ' (' "$tmp[@]"
+ tmp=( '
+ '${^tmp}')' )
+ text="${text}${tmp}"
done
- compstate[list]=list
- compstate[force_list]=yes
+ text="$text
+"
+ for i in "${(@ok)help_sfuncs}"; do
+ text="${text}
+styles in context ${i}"
+ tmp=()
+ for j in "${(@s.:.)help_sfuncs[$i][2,-1]}"; do
+ tmp=( "$tmp[@]" "${(@s.,.)help_styles[${i}${j}][2,-1]}" )
+ done
+ zformat -a tmp ' (' "$tmp[@]"
+ tmp=( '
+ '${^tmp}')' )
+ text="${text}${tmp}"
+ done
+
+ compstate[list]='list force'
compstate[insert]=''
compadd -UX "$text[2,-1]" -n ''
}
_help_sort_tags() {
- help_contexts=( "$help_contexts[@]" "$curcontext" )
- help_tags[$curcontext]="${help_tags[$curcontext]}
- ${argv}"
- comptry "$@"
+ local f="${${(@)${(@)funcstack[3,(i)_(main_complete|complete|approximate|normal)]}:#_(wanted|requested|loop|try)}% *}"
+
+ if [[ "$help_funcs[$curcontext]" != *${f}* ||
+ "$help_tags[${curcontext}${f}]" != *(${(j:|:)~argv})* ]]; then
+ [[ "$help_funcs[$curcontext]" != *${f}* ]] &&
+ help_funcs[$curcontext]="${help_funcs[$curcontext]}:${f}"
+ help_tags[${curcontext}${f}]="${help_tags[${curcontext}${f}]},${argv}:${f}"
+ comptry "$@"
+ fi
}
_complete_help "$@"
diff --git a/Completion/Commands/_history_complete_word b/Completion/Commands/_history_complete_word
index fc67c0f14..d904e01f1 100644
--- a/Completion/Commands/_history_complete_word
+++ b/Completion/Commands/_history_complete_word
@@ -1,2 +1,105 @@
-#compdef -k complete-word \e/
-compgen -Q -H 0 ''
+#compdef -K _history-complete-older complete-word \e/ _history-complete-newer complete-word \e,
+#
+# Complete words from the history
+#
+# by Adam Spiers, with help gratefully received from
+# Sven Wischnowsky and Bart Schaefer
+#
+# Available styles:
+#
+# :history-words:list -- display lists of available matches
+# :history-words:stop -- prevent looping at beginning and end of matches
+# during menu-completion
+# :history-words:sort -- sort matches lexically (default is to sort by age)
+# :history-words:remove-all-dups --
+# remove /all/ duplicate matches rather than just
+# consecutives
+#
+
+_history_complete_word () {
+ local expl direction stop
+
+ if [[ $WIDGET = *newer ]]; then
+ direction=newer
+ else
+ direction=older
+ fi
+
+ zstyle -s ":completion:${curcontext}:history-words" stop stop
+
+ zstyle -t ":completion:${curcontext}:history-words" list || compstate[list]=''
+
+ if [[ -n "$compstate[old_list]" &&
+ ( -n "$stop" || "$compstate[insert]" = menu ) ]] ; then
+ # array of matches is newest -> oldest (reverse of history order)
+ if [[ "$direction" == 'older' ]]; then
+ if [[ compstate[old_insert] -eq $_hist_menu_length ||
+ "$_hist_stop" == 'oldest' ]]; then
+ _hist_stop='oldest'
+ [[ "$stop" = verbose ]] &&
+ _message 'beginning of history reached'
+ elif [[ "$_hist_stop" == 'newest' ]]; then
+ zle -Rc
+ _history_complete_word_gen_matches
+ else
+ compstate[old_list]=keep
+ (( compstate[insert] = compstate[old_insert] + 1 ))
+ fi
+ elif [[ "$direction" == 'newer' ]]; then
+ if [[ compstate[old_insert] -eq 1 || "$_hist_stop" == 'newest' ]]; then
+ _hist_stop='newest'
+ [[ "$stop" = verbose ]] && _message 'end of history reached'
+ elif [[ "$_hist_stop" == 'oldest' ]]; then
+ zle -Rc
+ _history_complete_word_gen_matches
+ else
+ compstate[old_list]=keep
+ (( compstate[insert] = compstate[old_insert] - 1 ))
+ fi
+ fi
+ else
+ _hist_stop=''
+ _hist_old_prefix="$PREFIX"
+ _history_complete_word_gen_matches
+ fi
+
+ [[ -n "$compstate[nmatches]" ]]
+}
+
+_history_complete_word_gen_matches () {
+ local opt
+
+ [[ -n "$_hist_stop" ]] && PREFIX="$_hist_old_prefix"
+
+ if zstyle -t ":completion:${curcontext}:history-words" remove-all-dups; then
+ opt=-
+ else
+ opt=-1
+ fi
+ if zstyle -t ":completion:${curcontext}:history-words" sort; then
+ opt="${opt}J"
+ else
+ opt="${opt}V"
+ fi
+
+ _wanted "$opt" history-words expl 'history word' \
+ compadd -Q - "$historywords[@]"
+
+ zstyle -t ":completion:${curcontext}:history-words" list ||
+ compstate[list]=
+
+ _hist_menu_length="$compstate[nmatches]"
+
+ case "$direction" in
+ newer) compstate[insert]=$_hist_menu_length
+ [[ -n "$_hist_stop" ]] && (( compstate[insert]-- ))
+ ;;
+ older) compstate[insert]=1
+ [[ -n "$_hist_stop" ]] && (( compstate[insert]++ ))
+ ;;
+ esac
+
+ [[ -n "$_hist_stop" ]] && _hist_stop=''
+}
+
+_history_complete_word "$@"
diff --git a/Completion/Commands/_next_tags b/Completion/Commands/_next_tags
index 8bd3f5921..4861d1adf 100644
--- a/Completion/Commands/_next_tags
+++ b/Completion/Commands/_next_tags
@@ -1,70 +1,92 @@
#compdef -k complete-word \C-xn
-# Main widget/completer.
+# Main widget.
_next_tags() {
+ local comp
- if [[ $#funcstack -gt 1 ]]; then
+ if [[ -z $compstate[old_list] ]]; then
+ comp=()
+ else
+ comp=(_complete)
+ fi
- # Called as completer, probably `remove' our helper function. A better
- # test would be nice, but I think one should still be able to edit the
- # current word between attempts to complete it.
+ (( $+_sort_tags )) || _next_tags_not=
- [[ $_next_tags_pre != ${LBUFFER%${PREFIX}} ]] && unset _sort_tags
+ _sort_tags=_next_tags_sort
+ _next_tags_pre="${LBUFFER%${PREFIX}}"
+ _next_tags_not="$_next_tags_not $_lastcomp[tags]"
- return 1
- else
- local comp
+ _main_complete "$comp[@]"
- if [[ -z $compstate[old_list] ]]; then
- comp=()
- else
- comp=(_next_tags _complete)
- fi
+ [[ $compstate[insert] = automenu ]] &&
+ compstate[insert]=automenu-unambiguous
+
+ compstate[insert]=''
+ compstate[list]='list force'
- (( $+_sort_tags )) || _next_tags_not=
+ compprefuncs=( "$compprefuncs[@]" _next_tags_pre )
+}
- _sort_tags=_next_tags_sort
- _next_tags_pre="${LBUFFER%${PREFIX}}"
- _next_tags_not="$_next_tags_not $_lastcomp[tags]"
+# Pre-completion function.
- _main_complete "$comp[@]"
+_next_tags_pre() {
- [[ $compstate[insert] = automenu ]] &&
- compstate[insert]=automenu-unambiguous
+ # Probably `remove' our sort function. A better test would be nice, but
+ # I think one should still be able to edit the current word between
+ # attempts to complete it.
- compstate[insert]=''
- compstate[list]='list force'
+ if [[ $_next_tags_pre != ${LBUFFER%${PREFIX}} ]]; then
+ unset _sort_tags
+ else
+ compprefuncs=( "$compprefuncs[@]" _next_tags_pre )
fi
}
# Helper function for sorting tags. Most of this is copied from _tags.
_next_tags_sort() {
- local order tags tag nodef
+ local order tags tag nodef tmp
zstyle -a ":completion:${curcontext}:" tag-order order ||
- order=( 'arguments values' options globbed-files directories all-files )
+ order=('arguments values' options)
# But we also remove the tags we've already tried...
- tags=( "${(@)order:#(${(j:|:)~${=_next_tags_not}})}" )
+ tags=( "${(@)order:#(${(j:|:)~${=_next_tags_not}})(|:*)}" )
# ... unless that would remove all offered tags.
- [[ $#tags -ne $#order && "$tags" != *(${(j:|:)~argv})* ]] &&
- tags=( $order ) _next_tags_not=
-
+ if [[ $funcstack[4] = _files ]]; then
+ if zstyle -a ":completion:${curcontext}:" file-patterns tmp; then
+ [[ "$tags" = *${${tmp[-1]##[^\\]:}%:*}* ]] &&
+ tags=( $order ) _next_tags_not=
+ else
+ [[ "$tags" = *all-files* ]] && tags=( $order ) _next_tags_not=
+ fi
+ else
+ [[ $#tags -ne $#order && "$tags" != *(${(j:|:)~argv})* ]] &&
+ tags=( $order ) _next_tags_not=
+ fi
for tag in $tags; do
case $tag in
-) nodef=yes;;
*\(\)) "${${tag%%[ ]#\(\)}##[ ]#}" "$@";;
- \!*) comptry "${(@)argv:#(${(j:|:)~${=tag[2,-1]}})}";;
- ?*) comptry ${=tag};;
+ \!*) comptry "${(@)argv:#(${(j:|:)~${=~tag[2,-1]}})}";;
+ ?*) comptry -m "$tag";;
esac
done
- [[ -z "$nodef" ]] && comptry "$@"
+ if [[ -z "$nodef" ]]; then
+ if [[ $funcstack[4] = _files ]]; then
+ if zstyle -a ":completion:${curcontext}:" file-patterns tmp; then
+ [[ "$argv" = *${${tmp[-1]##[^\\]:}%:*}* ]] && _next_tags_not=
+ else
+ [[ "$argv" = *all-files* ]] && _next_tags_not=
+ fi
+ fi
+ comptry "${(@)argv:#(${(j:|:)~${=_next_tags_not}})(|:*)}"
+ fi
}
[[ -o kshautoload ]] || _next_tags "$@"
diff --git a/Completion/Core/_all_labels b/Completion/Core/_all_labels
new file mode 100644
index 000000000..fa7118ec4
--- /dev/null
+++ b/Completion/Core/_all_labels
@@ -0,0 +1,44 @@
+#autoload
+
+local gopt=-J len tmp pre suf tloop ret=1 descr
+
+if [[ "$1" = -t ]]; then
+ tloop=yes
+ shift
+fi
+if [[ "$1" = -([12]|)[VJ] ]]; then
+ gopt="$1"
+ shift
+fi
+
+tmp=${argv[(ib:4:)-]}
+len=$#
+if [[ tmp -lt len ]]; then
+ pre=$(( tmp-1 ))
+ suf=$tmp
+elif [[ tmp -eq $# ]]; then
+ pre=-2
+ suf=$(( len+1 ))
+else
+ pre=4
+ suf=5
+fi
+
+while [[ -z "$tloop" ]] || comptags -N; do
+ while comptags -A "$1" curtag; do
+ if [[ "$curtag" = *:* ]]; then
+ zformat -f descr "${curtag#*:}" "d:$3"
+ _description "$gopt" "${curtag%:*}" "$2" "$descr"
+ curtag="${curtag%:*}"
+
+ "$4" "${(P@)2}" "${(@)argv[5,-1]}"
+ else
+ _description "$gopt" "$curtag" "$2" "$3"
+
+ "${(@)argv[4,pre]}" "${(P@)2}" "${(@)argv[suf,-1]}" && ret=0
+ fi
+ done
+ [[ -z "$tloop" || ret -eq 0 ]] && break
+done
+
+return ret
diff --git a/Completion/Core/_alternative b/Completion/Core/_alternative
index 158f3a07a..b038aa8a4 100644
--- a/Completion/Core/_alternative
+++ b/Completion/Core/_alternative
@@ -1,19 +1,23 @@
#autoload
-local tags def expl descr action mesgs nm="$compstack[nmatches]"
-local context
+local tags def expl descr action mesgs nm="$compstate[nmatches]" subopts
+local opt curcontext="$curcontext"
+
+subopts=()
+while getopts 'O:C:' opt; do
+ case "$opt" in
+ O) subopts=( "${(@P)OPTARG}" ) ;;
+ C) curcontext="${curcontext%:*}:$OPTARG" ;;
+ esac
+done
+
+shift OPTIND-1
-if [[ "$1" = -C?* ]]; then
- context="${1[3,-1]}"
- shift
-elif [[ "$1" = -C ]]; then
- context="$2"
- shift 2
-fi
+[[ "$1" = -(|-) ]] && shift
mesgs=()
-_tags -C "$context" "${(@)argv%%:*}"
+_tags "${(@)argv%%:*}"
while _tags; do
for def; do
@@ -21,7 +25,7 @@ while _tags; do
descr="${${def#*:}%%:*}"
action="${def#*:*:}"
- _description expl "$descr"
+ _description "${def%%:*}" expl "$descr"
if [[ "$action" = \ # ]]; then
@@ -35,28 +39,35 @@ while _tags; do
eval ws\=\( "${action[3,-3]}" \)
- _describe "$descr" ws -M 'r:|[_-]=* r:|=*'
+ _describe "$descr" ws -M 'r:|[_-]=* r:|=*' "$subopts[@]"
elif [[ "$action" = \(*\) ]]; then
# Anything inside `(...)' is added directly.
- compadd "$expl[@]" - ${=action[2,-2]}
+ _all_labels "${def%%:*}" expl "$descr" \
+ compadd "$subopts[@]" - ${=action[2,-2]}
elif [[ "$action" = \{*\} ]]; then
# A string in braces is evaluated.
- eval "$action[2,-2]"
+ while _next_label "${def%%:*}" expl "$descr"; do
+ eval "$action[2,-2]"
+ done
elif [[ "$action" = \ * ]]; then
# If the action starts with a space, we just call it.
- ${(e)=~action}
+ eval "action=( $action )"
+ while _next_label "${def%%:*}" expl "$descr"; do
+ "$action[@]"
+ done
else
# Otherwise we call it with the description-arguments built above.
- action=( $=action )
- ${(e)action[1]} "$expl[@]" ${(e)~action[2,-1]}
+ eval "action=( $action )"
+ _all_labels "${def%%:*}" expl "$descr" \
+ "$action[1]" "$subopts[@]" "${(@)action[2,-1]}"
fi
fi
done
diff --git a/Completion/Core/_approximate b/Completion/Core/_approximate
index 1b40f7cbf..0815a308e 100644
--- a/Completion/Core/_approximate
+++ b/Completion/Core/_approximate
@@ -1,102 +1,30 @@
#autoload
# This code will try to correct the string on the line based on the
-# strings generated for the context if `compconfig[correct]' is set.
-# These corrected strings will be shown in a list and one can
-# cycle through them as in a menucompletion or get the corrected prefix.
-#
-# Supported configuration keys:
-#
-# approximate_accept
-# This 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 this
-# key will be used. E.g. with `compconf approximate_accept=2n' two
-# errors will be accepted, but if the user gives another number
-# with the numeric argument, this will be prefered. Also, with
-# `compconf approximate_accept=0n', normally no correction will be
-# tried, but if a numeric argument is given, automatic correction
-# will be used. On the other hand, if the string contains an `!'
-# and a `n' or `N', correction is not attempted if a numeric
-# argument is given. 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.
-#
-# approximate_original
-# This value 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 appear 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 immediately). Also, if the value 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.
-#
-# approximate_prompt
-# This can 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.
-#
-# approximate_insert
-# If this is set to a string starting with `unambig', the code
-# will try to insert a usable unambiguous string in the command
-# line instead of always cycling through the corrected strings.
-# If such a unambiguous string could be found, the original
-# string is not used, independent of the setting of
-# `approximate_original'. If no sensible string could be found,
-# one can cycle through the corrected strings as usual.
-#
-# If any of these keys is not set, but the the same key with the
-# prefix `correct' instead of `approximate' is set, that value will
-# be used.
-
-local _comp_correct _correct_prompt comax
-local cfgacc cfgorig cfgps cfgins
-
-# Only if all global matchers hav been tried.
-
-[[ compstate[matcher] -ne compstate[total_matchers] ]] && return 1
-
-# We don't try correction if the string is too short.
-
-[[ "${#:-$PREFIX$SUFFIX}" -le 1 ]] && return 1
-
-# Get the configuration values, using either the prefix `correct' or
-# `approximate'.
-
-if [[ "$compstate[pattern_match]" = (|\**) ]]; then
- cfgacc="${compconfig[approximate_accept]:-$compconfig[correct_accept]}"
- cfgorig="${compconfig[approximate_original]:-$compconfig[correct_original]}"
- cfgps="${compconfig[approximate_prompt]:-$compconfig[correct_prompt]}"
- cfgins="${compconfig[approximate_insert]:-$compconfig[correct_insert]}"
-else
- cfgacc="$compconfig[correct_accept]"
- cfgorig="$compconfig[correct_original]"
- cfgps="$compconfig[correct_prompt]"
- cfgins="$compconfig[correct_insert]"
-fi
+# strings generated for the context. These corrected strings will be
+# shown in a list and one can cycle through them as in a menucompletion
+# or get the corrected prefix.
+
+# We don't try correction if the string is too short or we have tried it
+# already.
+
+[[ _matcher_num -gt 1 || "${#:-$PREFIX$SUFFIX}" -le 1 ]] && return 1
+
+local _comp_correct _correct_expl comax cfgacc
+local oldcontext="${curcontext}" opm="$compstate[pattern_match]"
+
+zstyle -s ":completion:${curcontext}:" max-errors cfgacc || cfgacc='2 numeric'
# Get the number of errors to accept.
-if [[ "$cfgacc" = *[nN]* && NUMERIC -ne 1 ]]; then
- # Stop if we also have a `!'.
+if [[ "$cfgacc" = *numeric* && ${NUMERIC:-1} -ne 1 ]]; then
+ # A numeric argument may mean that we should not try correction.
- [[ "$cfgacc" = *\!* ]] && return 1
+ [[ "$cfgacc" = *not-numeric* ]] && return 1
# Prefer the numeric argument if that has a sensible value.
- comax="$NUMERIC"
+ comax="${NUMERIC:-1}"
else
comax="${cfgacc//[^0-9]}"
fi
@@ -105,13 +33,15 @@ fi
[[ "$comax" -lt 1 ]] && return 1
-# 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
+_tags corrections original
+
+# Otherwise temporarily define a function to use instead of
+# the builtin that adds matches. This is used to be able
+# to stick the `(#a...)' in the right place (after an
# ignored prefix).
compadd() {
- [[ "$*" != *-([a-zA-Z/]#|)U* &&
+ [[ ${argv[(I)-[a-zA-Z]#U[a-zA-Z]#]} -eq 0 &&
"${#:-$PREFIX$SUFFIX}" -le _comp_correct ]] && return
if [[ "$PREFIX" = \~*/* ]]; then
@@ -119,79 +49,49 @@ compadd() {
else
PREFIX="(#a${_comp_correct})$PREFIX"
fi
- if [[ -n "$_correct_prompt" ]]; then
- builtin compadd -X "$_correct_prompt" -J _correct "$@"
- else
- builtin compadd -J _correct "$@"
- fi
+ builtin compadd "$_correct_expl[@]" "$@"
}
-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 [[ -n "$_correct_prompt" ]]; then
- builtin compgen "$@" -X "$_correct_prompt" -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
-
-_correct_prompt="${cfgps//\%e/1}"
-
-# We also need to set `extendedglob' and make the completion
-# code behave as if globcomplete were set.
-
-setopt extendedglob
[[ -z "$compstate[pattern_match]" ]] && compstate[pattern_match]='*'
while [[ _comp_correct -le comax ]]; do
+ curcontext="${oldcontext/(#b)([^:]#:[^:]#:)/${match[1][1,-2]}-${_comp_correct}:}"
+
+ _description corrections _correct_expl corrections \
+ "e:$_comp_correct" "o:$PREFIX$SUFFIX"
+
if _complete; then
- if [[ "$cfgins" = unambig* &&
- "${#compstate[unambiguous]}" -ge "${#:-$PREFIX$SUFFIX}" ]]; then
+ if zstyle -t ":completion:${curcontext}:" insert-unambiguous &&
+ [[ "${#compstate[unambiguous]}" -ge "${#:-$PREFIX$SUFFIX}" ]]; then
compstate[pattern_insert]=unambiguous
- elif [[ compstate[nmatches] -gt 1 || "$cfgorig" = *always* ]]; then
- if [[ "$cfgorig" = *last* ]]; then
- builtin compadd -U -V _correct_original -nQ - "$PREFIX$SUFFIX"
- elif [[ -n "$cfgorig" ]]; then
- builtin compadd -U -nQ - "$PREFIX$SUFFIX"
- fi
+ elif _requested original &&
+ { [[ compstate[nmatches] -gt 1 ]] ||
+ zstyle -t ":completion:${curcontext}:" original }; then
+ local expl
+
+ _description -V original expl original
+
+ builtin compadd "$expl[@]" -U -Q - "$PREFIX$SUFFIX"
# If you always want to see the list of possible corrections,
- # set `compstate[list]=list' here.
+ # set `compstate[list]=list force' here.
- compstate[force_list]=list
+ [[ "$compstate[list]" != list* ]] &&
+ compstate[list]="$compstate[list] force"
fi
- compstate[matcher]="$compstate[total_matchers]"
- unfunction compadd compgen
+ unfunction compadd
+ compstate[pattern_match]="$opm"
return 0
fi
[[ "${#:-$PREFIX$SUFFIX}" -le _comp_correct+1 ]] && break
(( _comp_correct++ ))
-
- _correct_prompt="${cfgps//\%e/$_comp_correct}"
done
-compstate[matcher]="$compstate[total_matchers]"
-unfunction compadd compgen
+unfunction compadd
+compstate[pattern_match]="$opm"
return 1
diff --git a/Completion/Core/_call b/Completion/Core/_call
index 345dae50d..b038a80bc 100644
--- a/Completion/Core/_call
+++ b/Completion/Core/_call
@@ -1,4 +1,4 @@
-#autoload
+#autoload +X
local tmp
diff --git a/Completion/Core/_complete b/Completion/Core/_complete
index 0f4d5ff4b..c2679dcb8 100644
--- a/Completion/Core/_complete
+++ b/Completion/Core/_complete
@@ -2,51 +2,65 @@
# Generate all possible completions. Note that this is not intended as
# a normal completion function, but as one possible value for the
-# compconfig[completer] parameter.
+# completer style.
-local comp name
+local comp name oldcontext
+typeset -T curcontext="$curcontext" ccarray
+
+oldcontext="$curcontext"
+
+# If we have a user-supplied context name, use only that.
+
+if [[ -n "$compcontext" ]]; then
+ ccarray[3]="$compcontext"
+
+ comp="$_comps[$compcontext]"
+ [[ -z "$comp" ]] || "$comp"
+
+ return
+fi
# 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
+ ccarray[3]=-first-
"$comp"
- if (( $+_compskip )); then
- unset _compskip
+ if [[ "$_compskip" = all ]]; then
+ _compskip=''
(( compstate[nmatches] ))
return
fi
fi
+
# For arguments and command names we use the `_normal' function.
if [[ "$compstate[context]" = command ]]; then
- _normal
+ curcontext="$oldcontext"
+ _normal -s
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
+ local cname="-${compstate[context]:s/_/-/}-"
+
+ ccarray[3]="$cname"
+
+ comp="$_comps[$cname]"
# If not, we use default completion, if any.
- [[ -z "$comp" ]] && comp="$_comps[-default-]"
+ if [[ -z "$comp" ]]; then
+ if [[ "$_compskip" = *default* ]]; then
+ _compskip=''
+ return 1
+ fi
+ comp="$_comps[-default-]"
+ fi
[[ -z "$comp" ]] || "$comp"
fi
+_compskip=''
+
(( compstate[nmatches] ))
diff --git a/Completion/Core/_correct b/Completion/Core/_correct
index 35ab01cf1..c9c3d999c 100644
--- a/Completion/Core/_correct
+++ b/Completion/Core/_correct
@@ -1,8 +1,8 @@
#autoload
-# This is mainly a wrapper around the more general `_approximate.
+# This is mainly a wrapper around the more general `_approximate'.
# By setting `compstate[pattern_match]' to something unequal to `*' and
-# then calling `_approximate, we get only corrections, not all strings
+# then calling `_approximate', we get only corrections, not all strings
# with the corrected prefix and something after it.
#
# Supported configuration keys are the same as for `_approximate', only
diff --git a/Completion/Core/_description b/Completion/Core/_description
index 874ba8a96..7db47228b 100644
--- a/Completion/Core/_description
+++ b/Completion/Core/_description
@@ -1,22 +1,56 @@
#autoload
-local gropt=-J
+local name gropt=-J format gname hidden hide match opts
-if [[ "$1" = -V ]]; then
- gropt=-V
+opts=()
+
+if [[ "$1" = -([12]|)[VJ] ]]; then
+ gropt="$1"
shift
fi
-if [[ -n "$compconfig[group_matches]" ]]; then
- if [[ -n "$compconfig[description_format]" ]]; then
- eval "$1=($gropt ${(q)2} -X ${(q)compconfig[description_format]//\\%d/$2})"
+_lastdescr=( "$_lastdescr[@]" "$3" )
+
+_setup "$1"
+
+name="$2"
+
+zstyle -s ":completion:${curcontext}:$1" format format ||
+ zstyle -s ":completion:${curcontext}:descriptions" format format
+
+zstyle -s ":completion:${curcontext}:$1" hidden hidden
+if [[ "$hidden" = (all|yes|true|1|on) ]]; then
+ [[ "$hidden" = all ]] && format=''
+ opts=(-n)
+fi
+zstyle -s ":completion:${curcontext}:$1" group-name gname &&
+ [[ -z "$gname" ]] && gname="$1"
+zstyle -s ":completion:${curcontext}:$1" matcher match &&
+ opts=($opts -M "${(q)match}")
+[[ -n "$_matcher" ]] && opts=($opts -M "${(q)_matcher}")
+
+if [[ -z "$_comp_no_ignore" ]] &&
+ zstyle -a ":completion:${curcontext}:$1" ignored-patterns _comp_ignore; then
+ opts=( $opts -F _comp_ignore )
+else
+ _comp_ignore=()
+fi
+
+shift 2
+[[ -n "$format" ]] && zformat -f format "$format" "d:$1" "${(@)argv[2,-1]}"
+
+if [[ -n "$gname" ]]; then
+ if [[ -n "$format" ]]; then
+ eval "${name}=($opts $gropt ${(q)gname} -X \"${format}\")"
else
- eval "$1=($gropt ${(q)2})"
+ eval "${name}=($opts $gropt ${(q)gname})"
fi
else
- if [[ -n "$compconfig[description_format]" ]]; then
- eval "$1=(-X ${(q)compconfig[description_format]//\\%d/$2})"
+ if [[ -n "$format" ]]; then
+ eval "${name}=($opts $gropt -default- -X \"${format}\")"
else
- eval "$1=()"
+ eval "${name}=($opts $gropt -default-)"
fi
fi
+
+return 0
diff --git a/Completion/Core/_expand b/Completion/Core/_expand
index 9172b6cbf..eff8d8601 100644
--- a/Completion/Core/_expand
+++ b/Completion/Core/_expand
@@ -6,61 +6,20 @@
# This function will allow other completer functions to be called if
# the expansions done produce no result or do not change the original
# word from the line.
-#
-# Configuration keys:
-#
-# expand_substitute
-# If this is unset or set to the empty string, the code will first
-# try to expand all substitutions in the string (such as $(...) and
-# ${...}). If this is set to an non-empty string it should be
-# an expression usable inside a $[...] arithmetical expression.
-# In this case, expansion of substitutions will be done if the
-# expression evaluates to `1'. For example, with
-#
-# compconf expand_substitute='NUMERIC != 1'
-#
-# substitution will be performed only if given an explicit numeric
-# argument other than `1', as by typing ESC 2 TAB.
-#
-# expand_glob
-# If this is unset or set to an empty string, globbing will be
-# attempted on the word resulting from substitution or the
-# original string. The values accepted for this key are the same
-# as for expand_substitute.
-#
-# expand_menu
-# If this is unset or set to the empty string, the words resulting
-# from expansion (if any) will simply be inserted in the ommand line,
-# replacing the original string. However, if this key is set to an
-# non-empty string, the user can cycle through the expansion as in
-# a menucompletion. Unless the value contains the sub-string `only',
-# the user will still be offered all expansions at once as one of
-# the strings to insert in the command line. Also, if the value
-# contains the sub-string `last', the string with all expansion will
-# be offered first, whereas normally it is offered as the last string
-# to insert. Finally, if the value contains the sub-string `sort',
-# the expansions will be sorted alphabetically, normally they are
-# kept in the order the expansion produced them in.
-#
-# expand_original
-# If this is set to an non-empty string, the original string from the
-# line will be included in the list of strings the user can cycle
-# through as in a menucompletion. If the value contains the sub-string
-# `last', the original string will appear as the last string, with
-# other values it is inserted as the first one (so that the command
-# line does not change immediatly).
-#
-# expand_prompt
-# This may be set to a string that should be displayed before the
-# possible expansions. This is given to the -X option and thus may
-# contain the control sequences `%n', `%B', etc. Also, the sequence
-# `%o' in this string will be replaced by the original string.
-
-local exp word="$PREFIX$SUFFIX" group=-V
-
-# Do this only for the first global matcher.
-
-[[ "$compstate[matcher]" -le 1 ]] || return 1
+
+setopt localoptions nullglob
+
+[[ _matcher_num -gt 1 ]] && return 1
+
+local exp word="$PREFIX$SUFFIX" sort expr expl subd suf=" "
+
+# First, see if we should insert all *completions*.
+
+if zstyle -s ":completion:${curcontext}:" completions expr &&
+ [[ "${(e):-\$[$expr]}" -eq 1 ]]; then
+ compstate[insert]=all
+ return 1
+fi
# In exp we will collect the expansion.
@@ -69,79 +28,68 @@ exp=("$word")
# First try substitution. That weird thing spanning multiple lines
# changes quoted spaces, tabs, and newlines into spaces.
-[[ -z "$compconfig[expand_substitute]" ||
- "${(e):-\$[$compconfig[expand_substitute]]}" -eq 1 ]] &&
+zstyle -s ":completion:${curcontext}:" substitute expr &&
+ [[ "${(e):-\$[$expr]}" -eq 1 ]] &&
exp=( "${(e)exp//\\[
]/ }" )
# If the array is empty, store the original string again.
-[[ -z "$exp" ]] && exp=("$word")
+(( $#exp )) || exp=("$word")
+
+subd=("$exp[@]")
# Now try globbing.
-[[ -z "$compconfig[expand_glob]" ||
- "${(e):-\$[$compconfig[expand_glob]]}" -eq 1 ]] &&
- exp=( ${~exp}(N) )
+zstyle -s ":completion:${curcontext}:" glob expr &&
+ [[ "${(e):-\$[$expr]}" -eq 1 ]] &&
+ exp=( ${~exp} )
# If we don't have any expansions or only one and that is the same
# as the original string, we let other completers run.
-[[ $#exp -eq 0 ||
- ( $#exp -eq 1 && "$exp[1]" = "$word" ) ]] && return 1
+(( $#exp )) || exp=("$subd[@]")
-# We have expansions, should we menucomplete them?
+[[ $#exp -eq 1 && "$exp[1]" = "$word"(|\(N\)) ]] && return 1
-if [[ -z "$compconfig[expand_menu]" ]]; then
+# With subst-globs-only we bail out if there were no glob expansions,
+# regardless of any substitutions
- # No, so if the user only wants a list, we add the strings
- # separately. Otherwise we add the whole array as one string,
- # probably also adding the original string.
+zstyle -s ":completion:${curcontext}:" subst-globs-only expr &&
+ [[ "${(e):-\$[$expr]}" -eq 1 && "$subd" = "$exp"(|\(N\)) ]] && return 1
- if [[ -z "$compstate[insert]" ]]; then
- compadd -U -V _expand -Q - "$exp[@]"
- else
- [[ -n "$compconfig[expand_original]" &&
- "$compconfig[expand_original]" != *last* ]] &&
- compadd -UnQ -V _expand_original - "$word"
+# Now add as matches whatever the user requested.
- compadd -UQ -V _expand - "$exp"
+zstyle -s ":completion:${curcontext}:" sort sort
- [[ -n "$compconfig[expand_original]" &&
- "$compconfig[expand_original]" = *last* ]] &&
- compadd -UnQ -V _expand_original - "$word"
+[[ "$sort" = (yes|true|1|on) ]] && exp=( "${(@o)exp}" )
- compstate[insert]=menu
- fi
-else
- # Sorting? We just use a different group type then.
+# If there is only one expansion, add a suitable suffix
+(($#exp == 1)) && suf='' && [[ -d $exp && "$exp[1]" != */ ]] && suf='/'
- [[ "$compconfig[expand_menu]" = *sort* ]] && group=-J
+if [[ -z "$compstate[insert]" ]] ;then
+ _description all-expansions expl 'all expansions' "o:$word"
- # Now add the expansion string, probably also adding the original
- # and/or the string containing all expanded string.
+ compadd "$expl[@]" -UQ -qS "$suf" - "$exp"
+else
+ _tags all-expansions expansions original
- [[ -n "$compconfig[expand_original]" &&
- "$compconfig[expand_original]" != *last* ]] &&
- compadd -UnQ -V _expand_original - "$word"
- [[ "$compconfig[expand_menu]" = *last* &&
- "$compconfig[expand_menu]" != *only* ]] &&
- compadd -UnQ -V _expand_all - "$exp"
+ if _requested all-expansions; then
+ _description all-expansions expl 'all expansions'
+ compadd "$expl[@]" -UQ -qS "$suf" - "$exp"
+ fi
- if [[ -z "$compconfig[expand_prompt]" ]]; then
- compadd -UQ $group _expand - "$exp[@]"
- else
- compadd -UQ -X "${compconfig[expand_prompt]//\%o/$word}" \
- $group _expand - "$exp[@]"
+ if [[ $#exp -gt 1 ]] && _requested expansions; then
+ if [[ "$sort" = menu ]]; then
+ _description expansions expl expansions "o:$word"
+ else
+ _description -V expansions expl expansions "o:$word"
+ fi
+ compadd "$expl[@]" -UQ - "$exp[@]"
fi
- [[ "$compconfig[expand_menu]" != *last* &&
- "$compconfig[expand_menu]" != *only* ]] &&
- compadd -UnQ -V _expand_all - "$exp"
- [[ -n "$compconfig[expand_original]" &&
- "$compconfig[expand_original]" = *last* ]] &&
- compadd -UnQ -V _expand_original - "$word"
+ _requested original expl original && compadd "$expl[@]" -UQ - "$word"
compstate[insert]=menu
fi
diff --git a/Completion/Core/_files b/Completion/Core/_files
index d2cce35e7..1755abebd 100644
--- a/Completion/Core/_files
+++ b/Completion/Core/_files
@@ -1,26 +1,49 @@
#autoload
-# 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 opts tmp glob pats expl tag i pat descr minus
-local nm=$NMATCHES
+zparseopts -a opts \
+ '/=tmp' 'f=tmp' 'g+:-=tmp' q n 1 2 P: S: r: R: W: X+: M+: F: J+: V+:
-_path_files "$@"
+type="${(@j::M)${(@)tmp#-}#?}"
+(( $tmp[(I)-g*] )) && glob="${(j: :)${(M)tmp:#-g*}#-g}"
-if [[ $# -ne 0 && -nmatches nm ]]; then
- local opt opts
+if zstyle -a ":completion:${curcontext}:" file-patterns pats; then
+ [[ "$type" = */* ]] && glob="$glob *(-/)"
+ pats=( \ ${(M)^${pats//\\%p/ ${glob:-\*} }:#*[^\\]:*} )
+else
+ if [[ "$type" = *g* ]]; then
+ if [[ "$type" = */* ]]; then
+ pats=( " ${glob//:/\\:} *(-/):globbed-files" '*:all-files' )
+ else
+ pats=( " ${glob//:/\\:}:globbed-files"
+ '*(-/):directories' '*:all-files' )
+ fi
+ elif [[ "$type" = */* ]]; then
+ pats=( '*(-/):directories' '*:all-files' )
+ else
+ pats=( '*:all-files' )
+ fi
+fi
- # We didn't get any matches for those types of files described by
- # the `-g' or `-/' option. Now we try it again accepting all files.
- # First we get those options that we have to use even if then. If
- # we find out that the `-f' option was given, we already accepted
- # all files and give up immediatly.
+for tag in "${(@)${(@)pats#*[^\\]:}%%:*}"; do
- opts=()
- while getopts "P:S:W:F:J:V:X:f/g:" opt; do
- [[ "$opt" = f ]] && return
- [[ "$opt" = [PSWFJVX] ]] && opts=("$opts[@]" "-$opt" "$OPTARG")
- done
+ i="$pats[(I)*[^\\\\]:${tag}(|:*)]"
+ pat="${${pats[i]%%:${tag}*}//\\\\:/:}"
- _path_files "$opts[@]"
-fi
+ if [[ i -gt 0 && "$pat" != \ # ]]; then
+ if [[ "$pats[i]" = *:${tag}:* ]]; then
+ descr="${pats[i]#*:${tag}:}"
+ minus=()
+ else
+ descr=file
+ minus=(-)
+ fi
+ fi
+
+ _wanted "$tag" expl "$descr" \
+ _path_files -g "$pat" "$opts[@]" "$minus[@]" && return 0
+
+done
+
+return 1
diff --git a/Completion/Core/_ignored b/Completion/Core/_ignored
index 69a5244cc..4046f4c2d 100644
--- a/Completion/Core/_ignored
+++ b/Completion/Core/_ignored
@@ -4,11 +4,10 @@
(( $compstate[ignored] )) || return 1
-local curcontext="${curcontext/:[^:]#:/:ignored-${(M)#_completers[1,_completer_num]:#_ignored}:}"
local comp i _comp_no_ignore=yes tmp expl
zstyle -a ":completion:${curcontext}:" completer comp ||
- comp=( "${(@)_completers[1,_completer_num-1][(R)_ignored,-1]}" )
+ comp=( "${(@)_completers[1,_completer_num-1][(R)_ignored(|:*),-1]}" )
for i in "$comp[@]"; do
if [[ "$i" != _ignored ]] && "$i"; then
diff --git a/Completion/Core/_list b/Completion/Core/_list
index 099c6bc7b..37167726c 100644
--- a/Completion/Core/_list
+++ b/Completion/Core/_list
@@ -1,38 +1,16 @@
#autoload
# This completer function makes the other completer functions used
-# insert possible completions only after once the list has been
-# shown.
-#
-# Configuration keys:
-#
-# list_condition
-# If this key is unset or set to the empty string, this completer
-# will delay the insertion of matches unconditionally. However,
-# if this value is set, it should be set to an expression usable
-# inside a $[...] arithmetical expression. In this case, delaying
-# will be done if the expression evaluates to `1'.
-# For example, with
-#
-# compconf list_condition='NUMERIC != 1'
-#
-# delaying will be done only if given an explicit numeric argument
-# other than `1'.
-#
-# list_word
-# To find out if only listing should be done, the code normally
-# compares the contents of the line with the contents the line
-# had at the time of the last invocation. If this key is set to
-# an non-empty string comparison is done using only the current
-# word. So if it is set, attempting completion on a word equal
-# to the one completion was called on the last time will not
-# delay the generation of matches.
-
-local pre suf
+# insert possible completions only after the list has been shown at
+# least once.
+
+[[ _matcher_num -gt 1 ]] && return 1
+
+local pre suf expr
# Get the strings to compare.
-if [[ -z "$compconfig[list_word]" ]]; then
+if zstyle -t ":completion:${curcontext}:" word; then
pre="$HISTNO$LBUFFER"
suf="$RBUFFER"
else
@@ -42,16 +20,15 @@ fi
# Should we only show a list now?
-if [[ ( -z "$compconfig[list_condition]" ||
- "${(e):-\$[$compconfig[expand_glob]]}" -eq 1 ) &&
+zstyle -s ":completion:${curcontext}:" condition expr
+if [[ ( -z "$expr" || "${(e):-\$[$expr]}" -eq 1 ) &&
( "$pre" != "$_list_prefix" || "$suf" != "$_list_suffix" ) ]]; then
# Yes. Tell the completion code about it and save the new values
# to compare the next time.
compstate[insert]=''
- compstate[list]=list
- compstate[force_list]=yes
+ compstate[list]='list force'
_list_prefix="$pre"
_list_suffix="$suf"
fi
diff --git a/Completion/Core/_main_complete b/Completion/Core/_main_complete
index c7f5a5a96..d9278f435 100644
--- a/Completion/Core/_main_complete
+++ b/Completion/Core/_main_complete
@@ -2,47 +2,206 @@
# 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.
-local comp name
-setopt localoptions nullglob rcexpandparam globdots
-unsetopt markdirs globsubst shwordsplit nounset
+# If you want to complete only set or unset options for the unsetopt
+# and setopt builtin, un-comment these lines:
+#
+# local _set_options _unset_options
+#
+# _set_options=(${(k)options[(R)on]})
+# _unset_options=(${(k)options[(R)off]})
+#
+# This is needed because completion functions may set options locally
+# which makes the output of setopt and unsetopt reflect a different
+# state than the global one for which you are completing.
-# 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.
+setopt localoptions nullglob rcexpandparam extendedglob
+unsetopt markdirs globsubst shwordsplit nounset ksharrays
-comp="$_comps[-first-]"
-if [[ ! -z "$comp" ]]; then
- "$comp" "$@"
- if (( $+_compskip )); then
- unset _compskip
- return
- fi
+local func funcs ret=1 tmp _compskip format _comp_ignore \
+ _completers _completer _completer_num curtag \
+ _matchers _matcher _matcher_num _comp_tags \
+ context state line opt_args val_args curcontext="$curcontext" \
+ _last_nmatches=-1 _last_menu_style _def_menu_style _menu_style sel \
+ _saved_exact="${compstate[exact]}" \
+ _saved_lastprompt="${compstate[last_prompt]}" \
+ _saved_list="${compstate[list]}" \
+ _saved_insert="${compstate[insert]}"
+
+typeset -U _lastdescr
+
+[[ -z "$curcontext" ]] && curcontext=:::
+
+# Special completion contexts after `~' and `='.
+
+if compset -P 1 '='; then
+ compstate[context]=equal
+elif [[ "$PREFIX" != */* && "$PREFIX[1]" = '~' ]]; then
+ compset -p 1
+ compstate[context]=tilde
fi
-# For arguments we use the `_normal function.
+# Initial setup.
+
+_setup default
+_def_menu_style=( "$_last_menu_style[@]"
+
+# We can't really do that because the current value of $SELECTMIN
+# may be the one set by this function.
+# There is a similar problem with $ZLS_COLORS in _setup.
+
+# ${SELECTMIN+select${SELECTMIN:+\=$SELECTMIN}}
+
+ )
+_last_menu_style=()
-if [[ $CONTEXT == argument || $CONTEXT == command ]]; then
- _normal "$@"
+# Get the names of the completers to use in the positional parameters.
+
+if (( $# )); then
+ _completers=( "$@" )
else
- # Let's see if we have a special completion definition for the other
- # possible contexts.
+ zstyle -a ":completion:${curcontext}:" completer _completers ||
+ _completers=( _complete )
+fi
+
+# And now just call the completer functions defined.
+
+_completer_num=1
+
+# Call the pre-functions.
+
+funcs=( "$compprefuncs[@]" )
+compprefuncs=()
+for func in "$funcs[@]"; do
+ "$func"
+done
+
+for tmp in "$_completers[@]"; do
+
+ if [[ "$tmp" = *:-* ]]; then
+ _completer="${${tmp%:*}[2,-1]//_/-}${tmp#*:}"
+ tmp="${tmp%:*}"
+ elif [[ $tmp = *:* ]]; then
+ _completer="${tmp#*:}"
+ tmp="${tmp%:*}"
+ else
+ _completer="${tmp[2,-1]//_/-}"
+ fi
+ curcontext="${curcontext/:[^:]#:/:${_completer}:}"
- comp=''
+ zstyle -a ":completion:${curcontext}:" matcher-list _matchers ||
+ _matchers=( '' )
- case $CONTEXT in
- redirect) comp="$_comps[-redirect-]";;
- math) comp="$_comps[-math-]";;
- subscript) comp="$_comps[-subscript-]";;
- value) comp="$_comps[-value-]";;
- condition) comp="$_comps[-condition-]";;
- esac
+ _matcher_num=1
+ for _matcher in "$_matchers[@]"; do
+ if "$tmp"; then
+ ret=0
+ break 2
+ fi
+ (( _matcher_num++ ))
+ done
+ (( _completer_num++ ))
+done
- # If not, we use default completion, if any.
+curcontext="${curcontext/:[^:]#:/::}"
- [[ -z "$comp" ]] && comp="$_comps[-default-]"
- [[ -z "$comp" ]] || "$comp" "$@"
+if [[ $compstate[old_list] = keep || $compstate[nmatches] -gt 1 ]]; then
+ [[ _last_nmatches -ge 0 && _last_nmatches -ne $compstate[nmatches] ]] &&
+ _menu_style=( "$_last_menu_style[@]" "$_menu_style[@]" )
+
+ if [[ "$compstate[insert]" = "$_saved_insert" ]]; then
+ if [[ -n "$_menu_style[(r)(yes|true|1|on)]" ||
+ ( -n "$_menu_style[(r)auto*]" &&
+ "$compstate[insert]" = automenu ) ]]; then
+ compstate[insert]=menu
+ elif [[ -n "$_menu_style[(r)auto*]" &&
+ "$compstate[insert]" != automenu ]]; then
+ compstate[insert]=automenu-unambiguous
+ elif [[ -n "$_menu_style[(r)(no|false|0|off)]" ]]; then
+ compstate[insert]=unambiguous
+ elif [[ -n "$_def_menu_style[(r)(yes|true|1|on)]" ||
+ ( -n "$_def_menu_style[(r)auto*]" &&
+ "$compstate[insert]" = automenu ) ]]; then
+ compstate[insert]=menu
+ elif [[ -n "$_def_menu_style[(r)auto*]" &&
+ "$compstate[insert]" != automenu ]]; then
+ compstate[insert]=automenu-unambiguous
+ elif [[ -n "$_def_menu_style[(r)(no|false|0|off)]" ]]; then
+ compstate[insert]=unambiguous
+ fi
+ fi
+
+ _menu_style=( "$_menu_style[@]" "$_def_menu_style[@]" )
+
+ if [[ "$compstate[insert]" = *menu* ]]; then
+ if [[ -n "$_menu_style[(r)no-select*]" ]]; then
+ unset SELECTMIN
+ else
+ sel=( "${(@M)_menu_style:#select*}" )
+
+ if (( $# )); then
+ local min=9999999 i num
+
+ for i in "$sel[@]"; do
+ if [[ "$i" = *\=* ]]; then
+ num="${i#*\=}"
+ [[ num -lt 0 ]] && num=0
+ else
+ num=0
+ fi
+ [[ num -lt min ]] && min="$num"
+
+ (( min )) || break
+ done
+
+ zmodload -i zsh/complist
+ SELECTMIN="$min"
+ fi
+ fi
+ fi
+elif [[ $compstate[nmatches] -eq 0 &&
+ $#_lastdescr -ne 0 && $compstate[old_list] != keep ]] &&
+ zstyle -s ":completion:${curcontext}:warnings" format format; then
+
+ compstate[list]='list force'
+ compstate[insert]=''
+
+ if [[ "$format" = *%d* ]]; then
+ local str mesg
+
+ _lastdescr=( "\`${(@)^_lastdescr:#}'" )
+
+ case $#_lastdescr in
+ 1) str="$_lastdescr[1]";;
+ 2) str="$_lastdescr[1] or $_lastdescr[2]";;
+ *) str="${(j:, :)_lastdescr[1,-2]}, or $_lastdescr[-1]";;
+ esac
+
+ zformat -f mesg "$format" "d:$str"
+ compadd -UX "$mesg" -n - ''
+ else
+ _setup warnings
+ compadd -UQX "$format" -V warnings - "${(@)_lastdescr:#}"
+ fi
fi
+
+# Now call the post-functions.
+
+funcs=( "$comppostfuncs[@]" )
+comppostfuncs=()
+for func in "$funcs[@]"; do
+ "$func"
+done
+
+_lastcomp=( "${(@kv)compstate}" )
+_lastcomp[completer]="$_completer"
+_lastcomp[prefix]="$PREFIX"
+_lastcomp[suffix]="$SUFFIX"
+_lastcomp[iprefix]="$IPREFIX"
+_lastcomp[isuffix]="$ISUFFIX"
+_lastcomp[qiprefix]="$QIPREFIX"
+_lastcomp[qisuffix]="$QISUFFIX"
+_lastcomp[tags]="$_comp_tags"
+
+return ret
diff --git a/Completion/Core/_match b/Completion/Core/_match
index 3c639935c..18dab7423 100644
--- a/Completion/Core/_match
+++ b/Completion/Core/_match
@@ -1,53 +1,51 @@
#autoload
# This is intended to be used as a completer function after the normal
-# completer as in: `compconf completer=_complete:_match'.
+# completer as in: `zstyle ":completion:::::" completer _complete _match'.
# It temporarily switches on pattern matching, allowing you to try
# completion on patterns without having to setopt glob_complete.
#
# Note, however, that this is only really useful if you don't use the
# expand-or-complete function because otherwise the pattern will
# be expanded using globbing.
-#
-# Configuration key used:
-#
-# match_original
-# If this is set to a `only', pattern matching will only be tried
-# with the string from the line. If it is set to any other non-empty
-# string, the original pattern will be tried first and if that yields
-# no completions, matching will be tried again with a `*' inserted
-# at the cursor position. If this key is not set or set to an empty
-# string, matching will only be attempted with the `*' inserted.
-local tmp opm="$compstate[pattern_match]" ret=0
+[[ _matcher_num -gt 1 ]] && return 1
+
+local tmp opm="$compstate[pattern_match]" ret=0 orig ins
-# Do nothing if we don't have a pattern or there are still global
-# match specifications to try.
+# Do nothing if we don't have a pattern.
tmp="${${:-$PREFIX$SUFFIX}#[~=]}"
-[[ "$tmp:q" = "$tmp" ||
- compstate[matcher] -ne compstate[total_matchers] ]] && return 1
+[[ "$tmp:q" = "$tmp" ]] && return 1
+
+zstyle -s ":completion:${curcontext}:" match-original orig
+zstyle -b ":completion:${curcontext}:" insert-unambiguous ins
# Try completion without inserting a `*'?
-if [[ -n "$compconfig[match_original]" ]]; then
- compstate[matcher]=-1
+if [[ -n "$orig" ]]; then
compstate[pattern_match]='-'
_complete && ret=1
compstate[pattern_match]="$opm"
- compstate[matcher]="$compstate[total_matchers]"
- (( ret )) && return 0
+ if (( ret )); then
+ [[ "$ins" = yes &&
+ $#compstate[unambiguous] -ge ${#:-${PREFIX}${SUFFIX}} ]] &&
+ compstate[pattern_insert]=unambiguous
+ return 0
+ fi
fi
# No completion with inserting `*'?
-[[ "$compconfig[match_original]" = only ]] && return 1
+[[ "$orig" = only ]] && return 1
-compstate[matcher]=-1
compstate[pattern_match]='*'
_complete && ret=1
compstate[pattern_match]="$opm"
-compstate[matcher]="$compstate[total_matchers]"
+
+[[ ret -eq 1 && "$ins" = yes &&
+ $#compstate[unambiguous] -ge ${#:-${PREFIX}${SUFFIX}} ]] &&
+ compstate[pattern_insert]=unambiguous
return 1-ret
diff --git a/Completion/Core/_menu b/Completion/Core/_menu
index 4cbda4e14..41fc178ba 100644
--- a/Completion/Core/_menu
+++ b/Completion/Core/_menu
@@ -1,10 +1,12 @@
#autoload
+[[ _matcher_num -gt 1 ]] && return 1
+
# This completer is an example showing how menucompletion can be
# implemented with the new completion system.
# Use this one before the normal _complete completer, as in:
#
-# compconf completer=_menu:_complete
+# zstyle ":completion:::::" completer _menu _complete
if [[ -n "$compstate[old_list]" ]]; then
diff --git a/Completion/Core/_next_label b/Completion/Core/_next_label
new file mode 100644
index 000000000..e309e53ea
--- /dev/null
+++ b/Completion/Core/_next_label
@@ -0,0 +1,24 @@
+#autoload
+
+local gopt=-J descr
+
+if [[ "$1" = -([12]|)[VJ] ]]; then
+ gopt="$1"
+ shift
+fi
+
+if comptags -A "$1" curtag; then
+ if [[ "$curtag" = *:* ]]; then
+ zformat -f descr "${curtag#*:}" "d:$3"
+ _description "$gopt" "${curtag%:*}" "$2" "$descr"
+ curtag="${curtag%:*}"
+ eval "${2}=( \${(P)2} \$argv[4,-1] )"
+ else
+ _description "$gopt" "$curtag" "$2" "$3"
+ eval "${2}=( \$argv[4,-1] \${(P)2} )"
+ fi
+
+ return 0
+fi
+
+return 1
diff --git a/Completion/Core/_oldlist b/Completion/Core/_oldlist
new file mode 100644
index 000000000..bcb3e148a
--- /dev/null
+++ b/Completion/Core/_oldlist
@@ -0,0 +1,53 @@
+#autoload
+
+[[ _matcher_num -gt 1 ]] && return 1
+
+local list
+
+zstyle -s ":completion:${curcontext}:" old-list list
+
+# If this is a listing widget and there is already an old list,
+# and either the style :oldlist:old-list is `always', or it is not `never'
+# and the list is not already shown, then use the existing list for listing
+# (even if it was generated by another widget).
+# Do this also if there is an old list and it was generated by the
+# completer named by the oldlist_list key.
+
+if [[ -n $compstate[old_list] && $list != never ]]; then
+ if [[ $WIDGET = *list* && ( $list = always || $list != shown ) ]]; then
+ compstate[old_list]=keep
+ return 0
+ elif [[ $list = *${_lastcomp[completer]}* ]]; then
+ [[ "$_lastcomp[insert]" = unambig* ]] && compstate[to_end]=single
+ compstate[old_list]=keep
+ if [[ -o automenu ]]; then
+ compstate[insert]=menu
+ else
+ compadd -Qs "$SUFFIX" - "$PREFIX"
+ fi
+ return 0
+ fi
+fi
+
+# If this is a completion widget, and we have a completion inserted already,
+# and the style :oldlist:old-menu is `true', then we cycle through the
+# existing list (even if it was generated by another widget).
+
+if [[ -z $compstate[old_insert] && -n $compstate[old_list] ]]; then
+ compstate[old_list]=keep
+elif [[ $WIDGET = *complete(|-prefix|-word) ]] &&
+ zstyle -t ":completion:${curcontext}:" old-menu; then
+ if [[ -n $compstate[old_insert] ]]; then
+ compstate[old_list]=keep
+ if [[ $WIDGET = *reverse* ]]; then
+ compstate[insert]=$(( compstate[old_insert] - 1 ))
+ else
+ compstate[insert]=$(( compstate[old_insert] + 1 ))
+ fi
+ else
+ return 1
+ fi
+ return 0
+fi
+
+return 1
diff --git a/Completion/Core/_path_files b/Completion/Core/_path_files
index 83b6e8a09..ac4614dd8 100644
--- a/Completion/Core/_path_files
+++ b/Completion/Core/_path_files
@@ -1,85 +1,64 @@
#autoload
-# Utility function for in-path completion.
-# Supported arguments are: `-f', `-/', `-g <patterns>', `-J <group>',
-# `-V <group>', `-W paths', `-X explanation', and `-F <ignore>'. All but
-# the last have the same syntax and meaning as for `complist'. The
-# `-F <ignore>' 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'.
+# Utility function for in-path completion. This allows `/u/l/b<TAB>'
+# to complete to `/usr/local/bin'.
-# First see if we should generate matches for the global matcher in use.
+local linepath realpath donepath prepath testpath exppath skips skipped
+local tmp1 tmp2 tmp3 tmp4 i orig eorig pre suf tpre tsuf opre osuf cpre
+local pats haspats=no ignore pfxsfx rem remt sopt gopt opt
+local nm=$compstate[nmatches] menu matcher mopts atmp sort match
-_match_test _path_files || return
+typeset -U prepaths exppaths
-# 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
-
-setopt localoptions nullglob rcexpandparam globdots extendedglob
+setopt localoptions nullglob rcexpandparam
unsetopt markdirs globsubst shwordsplit nounset
-prepaths=('')
-ignore=()
-group=()
-sopt='-'
-gopt=''
-pats=()
-addpfx=()
-addsfx=()
-expl=()
+exppaths=()
# Get the options.
-while getopts "P:S:W:F:J:V:X:f/g:" opt; do
- case "$opt" in
- P) addpfx=(-P "$OPTARG")
- ;;
- S) addsfx=(-S "$OPTARG")
- ;;
- W) tmp1="$OPTARG"
- if [[ "$tmp1[1]" = '(' ]]; then
- prepaths=( ${^=tmp1[2,-2]}/ )
- else
- prepaths=( ${(P)=${tmp1}} )
- (( ! $#prepaths )) && prepaths=( ${tmp1}/ )
- fi
- (( ! $#prepaths )) && prepaths=( '' )
- ;;
- F) tmp1="$OPTARG"
- if [[ "$tmp1[1]" = '(' ]]; then
- ignore=( ${^=tmp1[2,-2]}/ )
- else
- ignore=( ${(P)${tmp1}} )
- fi
- (( $#ignore )) && ignore=(-F "( $ignore )")
- ;;
- [JV]) group=("-$opt" "$OPTARG")
- ;;
- X) expl=(-X "$OPTARG")
- ;;
- f) sopt="${sopt}f"
- pats=("$pats[@]" '*')
- ;;
- /) sopt="${sopt}/"
- pats=("$pats[@]" '*(-/)')
- ;;
- g) gopt='-g'
- pats=("$pats[@]" ${=OPTARG})
- ;;
- esac
-done
+zparseopts -a mopts \
+ 'P:=pfxsfx' 'S:=pfxsfx' 'q=pfxsfx' 'r:=pfxsfx' 'R:=pfxsfx' \
+ 'W:=prepaths' 'F:=ignore' 'M+:=matcher' \
+ J+: V+: X+: 1: 2: n: 'f=tmp1' '/=tmp1' 'g+:-=tmp1'
+
+sopt="-${(@j::M)${(@)tmp1#-}#?}"
+(( $tmp1[(I)-[/g]*] )) && haspats=yes
+(( $tmp1[(I)-g*] )) && gopt=yes
+if (( $tmp1[(I)-/] )); then
+ pats=( '*(-/)' ${=${(M)tmp1:#-g*}#-g} )
+else
+ pats=( "${(@)=${(@M)tmp1:#-g*}#-g}" )
+fi
+pats=( "${(@)pats:# #}" )
+
+if (( $#prepaths )); then
+ tmp1="${prepaths[2]}"
+ if [[ "$tmp1[1]" = '(' ]]; then
+ prepaths=( ${^=tmp1[2,-2]%/}/ )
+ elif [[ "$tmp1[1]" = '/' ]]; then
+ prepaths=( "${tmp1%/}/" )
+ else
+ prepaths=( ${(P)^tmp1%/}/ )
+ (( ! $#prepaths )) && prepaths=( ${tmp1%/}/ )
+ fi
+ (( ! $#prepaths )) && prepaths=( '' )
+else
+ prepaths=( '' )
+fi
+
+if (( $#ignore )); then
+ if [[ "${ignore[2]}" = \(* ]]; then
+ ignore=( ${=ignore[2][2,-2]} )
+ else
+ ignore=( ${(P)ignore[2]} )
+ fi
+fi
# If we were given no file selection option, we behave as if we were given
# a `-f'.
-if [[ "$sopt" = - ]]; then
+if [[ "$sopt" = -(f|) ]]; then
if [[ -z "$gopt" ]]; then
sopt='-f'
pats=('*')
@@ -88,224 +67,472 @@ if [[ "$sopt" = - ]]; then
fi
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.
+if (( ! $mopts[(I)-[JVX]] )); then
+ local expl
-[[ "$str" = \\\~* ]] && str="$str[2,-1]"
-
-# We will first try normal completion called with `complist', but only if we
-# weren't given a `-F' option.
-
-if (( ! $#ignore )); then
- # First build an array containing the `-W' option, if there is any and we
- # want to use it. We don't want to use it if the string from the command line
- # is a absolute path or relative to the current directory.
-
- if [[ -z "$tmp1[1]" || "$str[1]" = [~/] || "$str" = (.|..)/* ]]; then
- tmp1=()
+ if [[ -z "$gopt" && "$sopt" = -/ ]]; then
+ _description directories expl directory
else
- tmp1=(-W "( $prepaths )")
+ _description files expl file
+ fi
+ tmp1=$expl[(I)-M*]
+ if (( tmp1 )); then
+ if (( $#matcher )); then
+ matcher[2]="$matcher[2] $expl[1+tmp1]"
+ else
+ matcher=(-M "$expl[1+tmp1]")
+ fi
fi
+ mopts=( "$mopts[@]" "$expl[@]" )
+fi
- # Now call complist.
+if zstyle -s ":completion:${curcontext}:files" sort tmp1; then
+ case "$tmp1" in
+ *size*) sort=oL;;
+ *links*) sort=ol;;
+ *(time|date|modi)*) sort=om;;
+ *access*) sort=oa;;
+ *(inode|change)*) sort=oc;;
+ *) sort=on;;
+ esac
+ [[ "$tmp1" = *rev* ]] && sort[1]=O
- nm=$NMATCHES
- if [[ -z "$gopt" ]]; then
- complist "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" "$tmp1[@]" $sopt
+ if [[ "$sort" = on ]]; then
+ sort=''
else
- complist "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" "$tmp1[@]" $sopt -g "$pats"
+ mopts=( "${(@)mopts/#-J/-V}" )
+
+ tmp2=()
+ for tmp1 in "$pats[@]"; do
+ if [[ "$tmp1" = (#b)(?*)(\(\([^\|~]##\)\)) ]]; then
+ tmp2=( "$tmp2[@]" "${match[1]}((${sort}${match[2][3,-1]}" )
+ elif [[ "$tmp1" = (#b)(?*)(\([^\|~]##\)) ]]; then
+ tmp2=( "$tmp2[@]" "${match[1]}(${sort}${match[2][2,-1]}" )
+ else
+ tmp2=( "$tmp2[@]" "${tmp1}(${sort})" )
+ fi
+ done
+ pats=( "$tmp2[@]" )
fi
+fi
+
+# Check if we have to skip over sequences of slashes. The value of $skips
+# is used below to match the pathname components we always have to accept
+# immediatly.
+
+if zstyle -t ":completion:${curcontext}:paths" squeeze-slashes; then
+ skips='((.|..|)/)##'
+else
+ skips='((.|..)/)##'
+fi
+
+# We get the prefix and the suffix from the line and save the whole
+# original string. Then we see if we will do menucompletion.
+
+pre="$PREFIX"
+suf="$SUFFIX"
+opre="$PREFIX"
+osuf="$SUFFIX"
+orig="${PREFIX}${SUFFIX}"
+eorig="$orig"
- # If this generated any matches, we don't want to do in-path completion.
+[[ $compstate[insert] = (*menu|[0-9]*) || -n "$_comp_correct" ||
+ ( -n "$compstate[pattern_match]" &&
+ "${orig#\~}" != "${${orig#\~}:q}" ) ]] && menu=yes
- [[ -nmatches nm ]] || return
+# If given no `-F' option, we may want to use $fignore, turned into patterns.
- # No `-F' option, so we want to use `fignore'.
+[[ -z "$_comp_no_ignore" && $#ignore -eq 0 &&
+ ( -z $gopt || "$pats" = \ #\*\ # ) && -n $FIGNORE ]] &&
+ ignore=( "?*${^fignore[@]}" )
- ignore=(-F fignore)
+if (( $#ignore )); then
+ _comp_ignore=( "$_comp_ignore[@]" "$ignore[@]" )
+ (( $mopts[(I)-F] )) || mopts=( "$mopts[@]" -F _comp_ignore )
fi
+(( $#matcher )) && mopts=( "$mopts[@]" "$matcher[@]" )
+
# Now let's have a closer look at the string to complete.
-if [[ "$str[1]" = \~ ]]; then
+if [[ "$pre[1]" = \~ ]]; then
# It begins with `~', so remember anything before the first slash to be able
# to report it to the completion code. Also get an expanded version of it
# (in `realpath'), so that we can generate the matches. Then remove that
# prefix from the string to complete, set `donepath' to build the correct
# paths and make sure that the loop below is run only once with an empty
# prefix path by setting `prepaths'.
-
- linepath="${str%%/*}/"
- eval realpath\=$linepath
- str="${str#*/}"
+
+ linepath="${pre[2,-1]%%/*}"
+ if [[ -z "$linepath" ]]; then
+ realpath="${HOME%/}/"
+ elif (( $+userdirs[$linepath] )); then
+ realpath="${userdirs[$linepath]%/}/"
+ elif (( $+nameddirs[$linepath] )); then
+ realpath="${nameddirs[$linepath]%/}/"
+ else
+ _message "unknown user \`$linepath'"
+ return 1
+ fi
+ linepath="~${linepath}/"
+ [[ "$realpath" = "$linepath" ]] && return 1
+ pre="${pre#*/}"
+ orig="${orig#*/}"
+ donepath=''
+ prepaths=( '' )
+elif [[ "$pre" = *\$*/* ]]; then
+
+ # If there is a parameter expansion in the word from the line, we try
+ # to complete the beast by expanding the prefix and completing anything
+ # after the first slash after the parameter expansion.
+ # This fails for things like `f/$foo/b/<TAB>' where the first `f' is
+ # meant as a partial path.
+
+ linepath="${(M)pre##*\$[^/]##/}"
+ realpath=${(e)~linepath}
+ [[ "$realpath" = "$linepath" ]] && return 1
+ pre="${pre#${linepath}}"
+ i="${#linepath//[^\\/]}"
+ orig="${orig[1,(in:i:)/][1,-2]}"
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
+ if [[ "$pre[1]" = / ]]; then
# If it is a absolut path name, we remove the first slash and put it in
# `donepath' meaning that we treat it as the path that was already handled.
# Also, we don't use the paths from `-W'.
- str="$str[2,-1]"
+ pre="$pre[2,-1]"
+ orig="$orig[2,-1]"
donepath='/'
prepaths=( '' )
else
# The common case, we just use the string as it is, unless it begins with
# `./' or `../' in which case we don't use the paths from `-W'.
- [[ "$str" = (.|..)/* ]] && prepaths=( '' )
+ [[ "$pre" = (.|..)/* ]] && prepaths=( '' )
donepath=''
fi
fi
-# First we skip over all pathname components in `str' which really exist in
-# the file-system, so that `/usr/lib/l<TAB>' doesn't offer you `lib' and
-# `lib5'. Pathname components skipped this way are taken from `str' and added
-# to `donepath'.
+# Now we generate the matches. First we loop over all prefix paths given
+# with the `-W' option.
-while [[ "$str" = */* ]] do
- [[ -e "$realpath$donepath${str%%/*}" ]] || break
- donepath="$donepath${str%%/*}/"
- str="${str#*/}"
-done
+for prepath in "$prepaths[@]"; do
-# Now build the glob pattern by calling `_match_pattern'.
-patstr="$str"
-matchflags=""
-_match_pattern _path_files patstr matchflags
+ # Get local copies of the prefix, suffix, and the prefix path to use
+ # in the following loop, which walks through the pathname components
+ # in the string from the line.
-# 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.
+ tpre="$pre"
+ tsuf="$suf"
+ testpath="$donepath"
-patstr="$patstr:gs-/-*/-:gs/*.*.//:gs-/*.-/.-:gs/**/*/"
+ tmp2="${(M)tpre##${~skips}}"
+ tpre="${tpre#$tmp2}"
-# Finally, generate the matches. First we loop over all the paths from `-W'.
-# Note that in this loop `str' is used as a modifyable version of `patstr'
-# and `testpath' is a modifyable version of `donepath'.
+ tmp1=( "$prepath$realpath$donepath$tmp2" )
-for prepath in "$prepaths[@]"; do
- str="$patstr"
- testpath="$donepath"
+ while true; do
- # The second loop tests the components of the path in `str' to get the
- # possible matches.
+ # Get the prefix and suffix for matching.
- while [[ "$str" = */* ]] do
- # `rest' is the pathname after the first slash that is left. In `tmp1'
- # we get the globbing matches for the pathname component currently
- # handled.
+ if [[ "$tpre" = */* ]]; then
+ PREFIX="${tpre%%/*}"
+ SUFFIX=""
+ else
+ PREFIX="${tpre}"
+ SUFFIX="${tsuf%%/*}"
+ fi
- rest="${str#*/}"
- tmp1="${prepath}${realpath}${testpath}${~matchflags}${str%%/*}(-/)"
- tmp1=( $~tmp1 )
+ # Get the matching files by globbing.
- if [[ $#tmp1 -eq 0 ]]; then
- # If this didn't produce any matches, we don't need to test this path
- # any further, so continue with the next `-W' path, if any.
+ tmp2=( "$tmp1[@]" )
+ if [[ "$tpre$tsuf" = */* ]]; then
+ if [[ ! -o globdots && "$PREFIX" = .* ]]; then
+ tmp1=( ${^tmp1}${skipped}*(-/) ${^tmp1}${skipped}.*(-/) )
+ else
+ tmp1=( ${^tmp1}${skipped}*(-/) )
+ fi
+ if [[ -o globdots || "$PREFIX" = .* ]] &&
+ zstyle -s ":completion:${curcontext}:paths" special-dirs atmp; then
+ if [[ "$atmp" = (yes|true|1|on) ]]; then
+ tmp1=( "$tmp1[@]" . .. )
+ elif [[ "$atmp" = .. ]]; then
+ tmp1=( "$tmp1[@]" .. )
+ fi
+ fi
+ else
+ if [[ ! -o globdots && "$PREFIX" = .* ]]; then
+ tmp1=( ${^tmp1}${skipped}${^~pats} ${^tmp1}${skipped}.${^~pats:#.*} )
+ else
+ tmp1=( ${^tmp1}${skipped}${^~pats} )
+ fi
+ if [[ "$sopt" = *[/f]* && ( -o globdots || "$PREFIX" = .* ) ]] &&
+ zstyle -s ":completion:${curcontext}:paths" special-dirs atmp; then
+ if [[ "$atmp" = (yes|true|1|on) ]]; then
+ tmp1=( "$tmp1[@]" . .. )
+ elif [[ "$atmp" = .. ]]; then
+ tmp1=( "$tmp1[@]" .. )
+ fi
+ fi
+ fi
- continue 2
- elif [[ $#tmp1 -gt 1 ]]; then
- # If it produced more than one match, we want to remove those which
- # don't have possible following pathname components matching the
- # rest of the string we are completing. (The case with only one
- # match is handled below.)
- # In `collect' we will collect those of the produced pathnames that
- # have a matching possible path-suffix. In `suffixes' we build an
- # array containing strings build from the rest of the string to
- # complete and the glob patterns we were given as arguments.
-
- collect=()
- suffixes=( $rest$^pats )
- suffixes=( "${(@)suffixes:gs.**.*.}" )
-
- # 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 -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.
-
- if [[ $#collect -eq 0 ]]; then
+ if [[ -n "$PREFIX$SUFFIX" ]]; then
+ # See which of them match what's on the line.
+
+ if [[ -n "$_comp_correct" ]]; then
+ tmp2=( "$tmp1[@]" )
+ builtin compadd -D tmp1 -F _comp_ignore "$matcher[@]" - "${(@)tmp1:t}"
+
+ if [[ $#tmp1 -eq 0 ]]; then
+ tmp1=( "$tmp2[@]" )
+ compadd -D tmp1 -F _comp_ignore "$matcher[@]" - "${(@)tmp2:t}"
+ fi
+ else
+ [[ "$tmp1[1]" = */* ]] && tmp2=( "$tmp1[@]" )
+
+ builtin compadd -D tmp1 -F _comp_ignore "$matcher[@]" - "${(@)tmp1:t}"
+ fi
+
+ # If no file matches, save the expanded path and continue with
+ # the outer loop.
+
+ if (( ! $#tmp1 )); then
+ if [[ "$tmp2[1]" = */* ]]; then
+ tmp2=( "${(@)tmp2#${prepath}${realpath}}" )
+ if [[ "$tmp2[1]" = */* ]]; then
+ tmp2=( "${(@)tmp2:h}" )
+ compquote tmp2
+ if [[ "$tmp2" = */ ]]; then
+ exppaths=( "$exppaths[@]" ${^tmp2}${tpre}${tsuf} )
+ else
+ exppaths=( "$exppaths[@]" ${^tmp2}/${tpre}${tsuf} )
+ fi
+ else
+ exppaths=( "$exppaths[@]" ${tpre}${tsuf} )
+ fi
+ fi
continue 2
- elif [[ $#collect -ne 1 ]]; then
- # If we have more than one possible match, this means that the
- # pathname component currently handled is ambiguous, so we give
- # it to the completion code.
- # First we build the full path prefix in `tmp1'.
+ fi
+ elif (( ! $#tmp1 )); then
+ # A little extra hack: if we were completing `foo/<TAB>' and `foo'
+ # contains no files, this will normally produce no matches and other
+ # completers might think that's it's their time now. But if the next
+ # completer is _correct or something like that, this will result in
+ # an attempt to correct a valid directory name. So we just add the
+ # original string in such a case so that the command line doesn't
+ # change but other completers still think there are matches.
+ # We do this only if we weren't given a `-g' or `-/' option because
+ # otherwise this would keep `_files' from completing all filenames
+ # if none of the patterns match.
+
+ if [[ -z "$tpre$tsuf" && -n "$pre$suf" ]]; then
+ pfxsfx=(-S '' "$pfxsfx[@]")
+ ### Don't remember what the break was good for. We explicitly
+ ### execute this only when there are no matches in the directory,
+ ### so why continue?
+ ###
+ ### tmp1=( "$tmp2[@]" )
+ ### break
+ elif [[ "$haspats" = no && -z "$tpre$tsuf" &&
+ "$pre" = */ && -z "$suf" ]]; then
+ PREFIX="${opre}"
+ SUFFIX="${osuf}"
+ compadd -nQS '' - "$linepath$donepath$orig"
+ tmp4=-
+ fi
+ continue 2
+ fi
- tmp1="$prepath$realpath$testpath"
+ if [[ -z "$_comp_no_ignore" && "$tpre$tsuf" != */* && $#tmp1 -ne 0 ]] &&
+ zstyle -s ":completion:${curcontext}:files" ignore-parents rem &&
+ [[ ( "$rem" != *dir* || "$pats" = '*(-/)' ) &&
+ ( "$rem" != *..* || "$tmp1" = *../* ) ]]; then
+ if [[ "$rem" = *parent* ]]; then
+ for i in ${(M)^tmp1:#*/*}(-/); do
+ remt="${${i#$prepath$realpath$donepath}%/*}"
+ while [[ "$remt" = */* &&
+ ! "$prepath$realpath$donepath$remt" -ef "$i" ]]; do
+ remt="${remt%/*}"
+ done
+ [[ "$remt" = */* || "$remt" -ef "$i" ]] &&
+ _comp_ignore=( "$_comp_ignore[@]" "${(q)i}" )
+ done
+ fi
+ if [[ "$rem" = *pwd* ]]; then
+ for i in ${^tmp1}(-/); do
+ [[ "$i" -ef "$PWD" ]] && _comp_ignore=( "$_comp_ignore[@]" "${(q)i}" )
+ done
+ fi
+ (( $#_comp_ignore && $mopts[(I)-F] )) || mopts=( "$mopts[@]" -F _comp_ignore )
+ fi
- # Now produce all matching pathnames in `collect'.
+ # Step over to the next component, if any.
- collect=( ${~collect}/${~matchflags}${~suffixes} )
+ if [[ "$tpre" = */* ]]; then
+ tpre="${tpre#*/}"
+ elif [[ "$tsuf" = */* ]]; then
+ tpre="${tsuf#*/}"
+ tsuf=""
+ else
+ break
+ fi
- # And then remove the common path prefix from all these matches.
+ # There are more components, so skip over the next components and make a
+ # slash be added.
- collect=( ${collect#$tmp1} )
+ tmp2="${(M)tpre##((.|..|)/)##}"
+ if [[ -n "$tmp2" ]]; then
+ skipped="/$tmp2"
+ tpre="${tpre#$tmp2}"
+ else
+ skipped=/
+ fi
+ done
+
+ # The next loop searches the first ambiguous component.
+
+ tmp3="$pre$suf"
+ tpre="$pre"
+ tsuf="$suf"
+ tmp1=( "${(@)tmp1#${prepath}${realpath}${testpath}}" )
- # Finally, we add all these matches with the common (unexpanded)
- # pathprefix (the `-p' option), the path-prefix (the `-W' option)
- # to allow the completion code to test file type, and the path-
- # suffix (the `-s' option). We also tell the completion code that
- # these are file names and that `fignore' should be used as usual
- # (the `-f' and `-F' options).
+ while true; do
- for i in $collect; do
- compadd "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" -p "$linepath$testpath" -W "$tmp1" -s "/${i#*/}" -f "$ignore[@]" - "${i%%/*}"
- done
+ # First we check if some of the files match the original string
+ # for this component. If there are some we remove all other
+ # names. This avoids having `foo' complete to `foo' and `foobar'.
- # We have just finished handling all the matches from above, so we
- # can continue with the next `-W' path.
+ if [[ "$tmp3" = */* ]]; then
+ tmp4=( "${(@M)tmp1:#${tmp3%%/*}/*}" )
+ (( $#tmp4 )) && tmp1=( "$tmp4[@]" )
+ fi
+
+ # Next we see if this component is ambiguous.
- continue 2
+ if [[ "$tmp3" = */* ]]; then
+ tmp4=$tmp1[(I)^${(q)tmp1[1]%%/*}/*]
+ else
+ tmp4=$tmp1[(I)^${(q)tmp1[1]}]
+ fi
+
+ if [[ "$tpre" = */* ]]; then
+ tmp2="${cpre}${tpre%%/*}"
+ PREFIX="${donepath}${linepath}${tmp2}"
+ SUFFIX="/${tpre#*/}${tsuf#*/}"
+ else
+ tmp2="${cpre}${tpre}"
+ PREFIX="${donepath}${linepath}${tmp2}"
+ SUFFIX="${tsuf}"
+ fi
+
+ if (( tmp4 )) ||
+ [[ -n "$compstate[pattern_match]" && "$tmp2" != "${(q)tmp2}" ]]; then
+ # It is. For menucompletion we now add the possible completions
+ # for this component with the unambigous prefix we have built
+ # and the rest of the string from the line as the suffix.
+ # For normal completion we add the rests of the filenames
+ # collected as the suffixes to make the completion code expand
+ # it as far as possible.
+
+ tmp2="$testpath"
+ compquote tmp1 tmp2
+
+ if [[ -n $menu || -z "$compstate[insert]" ]] ||
+ ! zstyle -t ":completion:${curcontext}:paths" expand suffix; then
+ (( tmp4 )) && zstyle -t ":completion:${curcontext}:paths" cursor &&
+ compstate[to_end]=''
+ if [[ "$tmp3" = */* ]]; then
+ compadd -Qf "$mopts[@]" -p "$linepath$tmp2" -s "/${tmp3#*/}" \
+ -W "$prepath$realpath$testpath" \
+ "$pfxsfx[@]" -M "r:|/=* r:|=*" \
+ - "${(@)tmp1%%/*}"
+ else
+ compadd -Qf "$mopts[@]" -p "$linepath$tmp2" \
+ -W "$prepath$realpath$testpath" \
+ "$pfxsfx[@]" -M "r:|/=* r:|=*" \
+ - "$tmp1[@]"
+ fi
+ else
+ if [[ "$tmp3" = */* ]]; then
+ atmp=( -Qf "$mopts[@]" -p "$linepath$tmp2"
+ -W "$prepath$realpath$testpath"
+ "$pfxsfx[@]" -M "r:|/=* r:|=*" )
+ for i in "$tmp1[@]"; do
+ compadd "$atmp[@]" -s "/${i#*/}" - "${i%%/*}"
+ done
+ else
+ compadd -Qf "$mopts[@]" -p "$linepath$tmp2" \
+ -W "$prepath$realpath$testpath" \
+ "$pfxsfx[@]" -M "r:|/=* r:|=*" \
+ - "$tmp1[@]"
+ fi
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.
+ tmp4=-
+ break
+ fi
+
+ # If we have checked all components, we stop now and add the
+ # strings collected after the loop.
- tmp1=( "$collect[1]" )
+ if [[ "$tmp3" != */* ]]; then
+ tmp4=""
+ break
fi
- # This is also reached if the first globbing produced only one match
- # in this case we just continue with the next pathname component, too.
- tmp1="$tmp1[1]"
- testpath="$testpath${tmp1##*/}/"
- str="$rest"
+ # Otherwise we add the unambiguous component to `testpath' and
+ # take it from the filenames.
+
+ testpath="${testpath}${tmp1[1]%%/*}/"
+ tmp1=( "${(@)tmp1#*/}" )
+
+ tmp3="${tmp3#*/}"
+
+ if [[ "$tpre" = */* ]]; then
+ cpre="${cpre}${tpre%%/*}/"
+ tpre="${tpre#*/}"
+ elif [[ "$tsuf" = */* ]]; then
+ cpre="${cpre}${tpre}/"
+ tpre="${tsuf#*/}"
+ tsuf=""
+ else
+ tpre=""
+ tsuf=""
+ fi
done
- # We are here if all pathname components except the last one (which is still
- # not tested) are unambiguous. So we add matches with the full path prefix,
- # no path suffix, the `-W' we are currently handling, all the matches we
- # can produce in this directory, if any.
-
- tmp1="$prepath$realpath$testpath"
- suffixes=( $str$^pats )
- suffixes=( "${(@)suffixes:gs.**.*.}" )
- tmp2=( ${~tmp1}${~matchflags}${~suffixes} )
- if [[ $#tmp2 -eq 0 && "$sopt" = */* ]]; then
- [[ "$testpath[-1]" = / ]] && testpath="$testpath[1,-2]"
- compadd "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" -f - "$linepath$testpath"
- else
- compadd "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" -p "$linepath$testpath" -W "$prepath$realpath$testpath" -f "$ignore[@]" - ${(@)tmp2#$tmp1}
+ if [[ -z "$tmp4" ]]; then
+ if [[ "$osuf" = */* ]]; then
+ PREFIX="${opre}${osuf}"
+ SUFFIX=""
+ else
+ PREFIX="${opre}"
+ SUFFIX="${osuf}"
+ fi
+ tmp4="$testpath"
+ compquote tmp4 tmp1
+ compadd -Qf "$mopts[@]" -p "$linepath$tmp4" -W "$prepath$realpath$testpath" \
+ "$pfxsfx[@]" -M "r:|/=* r:|=*" - "$tmp1[@]"
fi
done
+
+# If we are configured to expand paths as far as possible and we collected
+# expanded paths that are different from the string on the line, we add
+# them as possible matches.
+
+if zstyle -t ":completion:${curcontext}:paths" expand prefix &&
+ [[ nm -eq compstate[nmatches] && $#exppaths -ne 0 &&
+ "$exppaths" != "$eorig" ]]; then
+ PREFIX="${opre}"
+ SUFFIX="${osuf}"
+ compadd -Q "$mopts[@]" -S '' -M "r:|/=* r:|=*" -p "$linepath" - "$exppaths[@]"
+fi
+
+[[ nm -ne compstate[nmatches] ]]
diff --git a/Completion/Core/_prefix b/Completion/Core/_prefix
index 6306b4aa0..f6e3b0831 100644
--- a/Completion/Core/_prefix
+++ b/Completion/Core/_prefix
@@ -4,10 +4,10 @@
[[ -n "$SUFFIX" ]] || return 1
-local curcontext="${curcontext/:[^:]#:/:prefix:}" comp i
+local comp i
zstyle -a ":completion:${curcontext}:" completer comp ||
- comp=( "${(@)_completers[1,-${#_completers_left}-1][(R)_prefix,-1]}" )
+ comp=( "${(@)_completers[1,_completer_num-1][(R)_prefix(|:*),-1]}" )
if zstyle -t ":completion:${curcontext}:" add-space; then
ISUFFIX=" $SUFFIX"
diff --git a/Completion/Core/_requested b/Completion/Core/_requested
index 082c45820..bd838a28e 100644
--- a/Completion/Core/_requested
+++ b/Completion/Core/_requested
@@ -1,9 +1,20 @@
#autoload
-local tag tname="$funcstack[2,-1]"
+local gopt=-J
-for tag; do
- [[ "${_cur_tags[${tname}]}" = *:${tag}(:|\[*\]:)* ]] && return 0
-done
+if [[ "$1" = -([12]|)[VJ] ]]; then
+ gopt="$1"
+ shift
+fi
-return 1
+if comptags -R "$1"; then
+ _comp_tags="$_comp_tags $1"
+ if [[ $# -gt 3 ]]; then
+ _all_labels "$gopt" "$@"
+ elif [[ $# -gt 1 ]]; then
+ _description "$gopt" "$@"
+ fi
+ return 0
+else
+ return 1
+fi
diff --git a/Completion/Core/_setup b/Completion/Core/_setup
index f12c34b34..ed7307e69 100644
--- a/Completion/Core/_setup
+++ b/Completion/Core/_setup
@@ -1,13 +1,61 @@
#autoload
-local colors i
-
-for i; do
- if _style -a "$i" list-colors colors; then
- if [[ "$1" = default ]]; then
- ZLS_COLORS="${(j.:.)${(@)colors:gs/:/\\\:}}"
- else
- eval "ZLS_COLORS=\"(${i})\${(j.:(${i}).)\${(@)colors:gs/:/\\\:}}:\${ZLS_COLORS}\""
- fi
+local val nm="$compstate[nmatches]"
+
+if zstyle -a ":completion:${curcontext}:$1" list-colors val; then
+ zmodload -i zsh/complist
+ if [[ "$1" = default ]]; then
+ ZLS_COLORS="${(j.:.)${(@)val:gs/:/\\\:}}"
+ else
+ eval "ZLS_COLORS=\"(${1})\${(j.:(${1}).)\${(@)val:gs/:/\\\:}}:\${ZLS_COLORS}\""
fi
-done
+
+# Here is the problem mentioned in _main_complete.
+
+# elif [[ "$1" = default && -n "$ZLS_COLORS$ZLS_COLOURS" ]]; then
+# zmodload -i zsh/complist
+# ZLS_COLORS="$ZLS_COLORS$ZLS_COLOURS"
+
+fi
+
+if zstyle -t ":completion:${curcontext}:$1" list-packed; then
+ compstate[list]="${compstate[list]} packed"
+elif [[ $? -eq 1 ]]; then
+ compstate[list]="${compstate[list]:gs/packed//}"
+else
+ compstate[list]="$_saved_list"
+fi
+
+if zstyle -t ":completion:${curcontext}:$1" list-rows-first; then
+ compstate[list]="${compstate[list]} rows"
+elif [[ $? -eq 1 ]]; then
+ compstate[list]="${compstate[list]:gs/rows//}"
+else
+ compstate[list]="$_saved_list"
+fi
+
+if zstyle -t ":completion:${curcontext}:$1" last-prompt; then
+ compstate[last_prompt]=yes
+elif [[ $? -eq 1 ]]; then
+ compstate[last_prompt]=''
+else
+ compstate[last_prompt]="$_saved_lastprompt"
+fi
+
+if zstyle -t ":completion:${curcontext}:$1" accept-exact; then
+ compstate[exact]=accept
+elif [[ $? -eq 1 ]]; then
+ compstate[exact]=''
+else
+ compstate[exact]="$_saved_exact"
+fi
+
+[[ _last_nmatches -ge 0 && _last_nmatches -ne nm ]] &&
+ _menu_style=( "$_last_menu_style[@]" "$_menu_style[@]" )
+
+if zstyle -a ":completion:${curcontext}:$1" menu val; then
+ _last_nmatches=$nm
+ _last_menu_style=( "$val[@]" )
+else
+ _last_nmatches=-1
+fi
diff --git a/Completion/Core/_tags b/Completion/Core/_tags
index af8dc21dd..496f5b7e0 100644
--- a/Completion/Core/_tags
+++ b/Completion/Core/_tags
@@ -1,81 +1,83 @@
#autoload
-if (( $# )); then
- local cmd="$words[1]" func="$funcstack[2]" defs i tags tag pat style prio
-
- while getopts 'c:f:' i; do
- if [[ "$i" = c ]]; then
- cmd="$OPTARG"
- else
- func="$OPTARG"
- fi
- done
-
- shift OPTIND-1
-
- defs=( "${(@M)argv:#${(kj:|:)~override_tags[(R)(|+*)]}}" )
- (( $#defs )) && set -- "$defs[@]"
-
- _offered_tags=( "$_offered_tags[@]" "$@" )
- _last_tags=()
-
- defs=()
- for i; do
- if [[ -n ${override_tags[$i]} && ${override_tags[$i]} != (\[|+\[)* ]]; then
- if [[ ${override_tags[$i]} = *\[* ]]; then
- prio=( "${i}:*=${override_tags[$i]#+}" )
- else
- prio=( "${i}:${(@v)^comptags[(I)(|*:)${i}(|:*)]}" )
- (( $#prio )) || prio=( "${i}:${comptags[any]}" )
- prio="${${${prio[(r)(|*:)\*=[^:]#\[*\](|:*)]}##(|*:)\*}%%:*}"
- prio=( "${i}:*=${override_tags[$i]#+}${(M)prio%%\[*\]}" )
- fi
- else
- prio=( "${i}:${(@v)^comptags[(I)(|*:)${i}(|:*)]}" )
- (( $#prio )) || prio=( "${i}:${comptags[any]}" )
- fi
- defs=( "$defs[@]" "$prio[@]" )
- done
-
- tags=()
- for i in "$defs[@]"; do
- tag="${i%%:*}"
- for pat in "${(s.:.)i#*:}"; do
- if [[ ( "$pat" = _* && "$func" = ${~pat%%\=*} ) ||
- "$cmd" = ${~pat%%\=*} ]]; then
- prio="${pat#*\=}"
- [[ "$prio" = -* ]] && continue 2
-
- if [[ "$prio" = *\[*\] ]]; then
- style="${(M)prio%%\[*}"
- prio="${prio%%\[*}"
- else
- style=''
- fi
- [[ ${override_tags[$tag]} = (|+)\[* ]] &&
- style="${override_tags[$tag]#+}"
-
- (( prio++ ))
-
- tags[$prio]="${tags[$prio]}:${tag}${style}"
- break
- fi
- done
- done
+local prev
- prios=( "${(@)tags:#}" )
+# A `--' as the first argument says that we should tell comptags to use
+# the preceding function nesting level. This is only documented here because
+# if everythings goes well, users won't have to worry about it and should
+# not mess with it.
- return 0
+if [[ "$1" = -- ]]; then
+ prev=-
+ shift
fi
-_failed_tags=( "$_failed_tags[@]" "$_last_tags[@]" )
+if (( $# )); then
+
+ # We have arguments: the tags supported in this context.
+
+ local curcontext="$curcontext" order tag nodef tmp
+
+ if [[ "$1" = -C?* ]]; then
+ curcontext="${curcontext%:*}:${1[3,-1]}"
+ shift
+ elif [[ "$1" = -C ]]; then
+ curcontext="${curcontext%:*}:${2}"
+ shift 2
+ else
+ targs=()
+ fi
+
+ [[ "$1" = -(|-) ]] && shift
-(( $#prios )) || return 1
+ if zstyle -a ":completion:${curcontext}:" group-order order; then
+ local name
-tags="${prios[1]}:"
-shift 1 prios
+ for name in "$order[@]"; do
+ compadd -J "$name"
+ compadd -V "$name"
+ compadd -J "$name" -1
+ compadd -V "$name" -1
+ compadd -J "$name" -2
+ compadd -V "$name" -2
+ done
+ fi
+
+ # Set and remember offered tags.
+
+ comptags "-i$prev" "$curcontext" "$@"
+
+ # Sort the tags.
+
+ if [[ -n "$_sort_tags" ]]; then
+ "$_sort_tags" "$@"
+ else
+ zstyle -a ":completion:${curcontext}:" tag-order order ||
+ order=('arguments values' options)
+
+ for tag in $order; do
+ case $tag in
+ -) nodef=yes;;
+ *\(\)) if ! "${${tag%%[ ]#\(\)}##[ ]#}" "$@"; then
+ nodef=yes
+ break
+ fi
+ ;;
+ \!*) comptry "${(@)argv:#(${(j:|:)~${=~tag[2,-1]}})}";;
+ ?*) comptry -m "$tag";;
+ esac
+ done
+
+ [[ -z "$nodef" ]] && comptry "$@"
+ fi
+
+ # Return non-zero if at least one set of tags should be used.
+
+ comptags "-T$prev"
+
+ return
+fi
-_last_tags=( "${(@s.:.)${${tags#:}%:}}" )
-_tried_tags=( "$_tried_tags[@]" "$_last_tags[@]" )
+# The other mode: switch to the next set of tags.
-return 0
+comptags "-N$prev"
diff --git a/Completion/Core/_wanted b/Completion/Core/_wanted
index 7baa3e724..32875ec57 100644
--- a/Completion/Core/_wanted
+++ b/Completion/Core/_wanted
@@ -1,6 +1,6 @@
#autoload
-local targs
+local targs gopt=-J
if [[ "$1" = -C?* ]]; then
targs=( -C "${1[3,-1]}" )
@@ -12,10 +12,22 @@ else
targs=()
fi
-[[ "$1" = -(|-) ]] && shift
+if [[ "$1" = -([12]|)[VJ] ]]; then
+ gopt="$1"
+ shift
+fi
+
+if [[ $# -gt 3 ]]; then
+ if _tags "$targs[@]" "$1"; then
+ _comp_tags="$_comp_tags $1"
-if [[ $# -gt 1 ]]; then
- _tags "$targs[@]" "$1" && _description "${(@)argv[2,-1]}"
+ _all_labels -t "$gopt" "$@"
+ else
+ return 1
+ fi
+elif [[ $# -gt 1 ]]; then
+ _tags -- "$targs[@]" "$1" && _comp_tags="$_comp_tags $1" &&
+ _description "$gopt" "$@"
else
- _tags "$targs[@]" "$1"
+ _tags -- "$targs[@]" "$1" && _comp_tags="$_comp_tags $1"
fi
diff --git a/Completion/Core/compdump b/Completion/Core/compdump
index 8be096f50..3cccbd06e 100644
--- a/Completion/Core/compdump
+++ b/Completion/Core/compdump
@@ -1,4 +1,4 @@
-# This is a file to be sourced to dump the definitions for new-style
+# This is a function to dump the definitions for new-style
# completion defined by 'compinit' in the same directory. The output
# should be directed into the "compinit.dump" in the same directory as
# compinit. If you rename init, just stick .dump onto the end of whatever
@@ -9,33 +9,46 @@
# To do this, simply remove the .dump file, start a new shell, and
# create the .dump file as before. Again, compinit -d handles this
# automatically.
-#
-# It relies on KSH_ARRAYS not being set.
# 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}
+emulate -L zsh
+setopt extendedglob
+
+typeset _d_file _d_f _d_bks _d_line _d_als
+
+_d_file=${_comp_dumpfile-${0:h}/compinit.dump}.$HOST.$$
typeset -U _d_files
-_d_files=( ${^~fpath}/_*~*~(N:t) )
+_d_files=( ${^~fpath:/.}/^([^_]*|*~|*.zwc)(N:t) )
print "#files: $#_d_files" > $_d_file
-unset _d_files
-
# First dump the arrays _comps and _patcomps. The quoting hieroglyphyics
# ensure that a single quote inside a variable is itself correctly quoted.
print "_comps=(" >> $_d_file
for _d_f in ${(ok)_comps}; do
- print -r - "'${_d_f//\'/'\\''}'" "'${_comps[$_d_f]//\'/'\\''}'"
+ print -r - "${(q)_d_f}" "${(q)_comps[$_d_f]}"
done >> $_d_file
print ")" >> $_d_file
print "\n_patcomps=(" >> $_d_file
-for _d_f in "$_patcomps[@]"; do
- print -r - "'${_d_f//\'/'\\''}'"
+for _d_f in "${(ok@)_patcomps}"; do
+ print -r - "${(q)_d_f}" "${(q)_patcomps[$_d_f]}"
+done >> $_d_file
+print ")" >> $_d_file
+
+print "\n_postpatcomps=(" >> $_d_file
+for _d_f in "${(ok@)_postpatcomps}"; do
+ print -r - "${(q)_d_f}" "${(q)_postpatcomps[$_d_f]}"
+done >> $_d_file
+print ")" >> $_d_file
+
+print "\n_compautos=(" >> $_d_file
+for _d_f in "${(ok@)_compautos}"; do
+ print -r - "${(q)_d_f}" "${(q)_compautos[$_d_f]}"
done >> $_d_file
print ")" >> $_d_file
@@ -44,11 +57,13 @@ print >> $_d_file
# Now dump the key bindings. We dump all bindings for zle widgets
# whose names start with a underscore.
# We need both the zle -C's and the bindkey's to recreate.
+# We can ignore any zle -C which rebinds a standard widget (second
+# argument to zle does not begin with a `_').
_d_bks=()
zle -lL |
while read -rA _d_line; do
- if [[ ${_d_line[5]} = _* ]]; then
+ if [[ ${_d_line[3]} = _* && ${_d_line[5]} = _* ]]; then
print -r - ${_d_line}
_d_bks=($_d_bks ${_d_line[3]})
fi
@@ -73,17 +88,26 @@ done))
# print them out: about five to a line looks neat
+_i=5
+print -n autoload -U >> $_d_file
while (( $#_d_als )); do
- print -n autoload
- for (( _i = 0; _i < 5; _i++ )); do
- if (( $#_d_als )); then
- print -n " $_d_als[1]"
- shift _d_als
+ if (( ! $+_compautos[$_d_als[1]] )); then
+ print -n " $_d_als[1]"
+ if (( _i-- && $#_d_als > 1 )); then
+ _i=5
+ print -n '\nautoload -U'
fi
- done
- print
+ fi
+ shift _d_als
done >> $_d_file
print >> $_d_file
-unset _d_line _d_zle _d_bks _d_als _d_f _f_file
+for _i in "${(ok@)_compautos}"; do
+ print "autoload -U $_compautos[$_i] $_i" >> $_d_file
+done
+
+mv $_d_file ${_d_file%.$HOST.$$}
+
+unfunction compdump
+autoload -U compdump
diff --git a/Completion/Core/compinit b/Completion/Core/compinit
index ec5867838..6a35d17a7 100644
--- a/Completion/Core/compinit
+++ b/Completion/Core/compinit
@@ -1,25 +1,23 @@
# Initialisation for new style completion. This mainly contains some helper
-# function and aliases. Everything else is split into different files in this
-# directory that will automatically be made autoloaded (see the end of this
-# file).
+# functions and aliases. Everything else is split into different files that
+# will automatically be made autoloaded (see the end of this file).
# The names of the files that will be considered for autoloading have to
-# start with a underscores (like `_setopt).
+# start with an underscores (like `_setopt').
# The first line of these files will be read and has to say what should be
# done with its contents:
#
-# `#defcomp <names ...>'
-# if the first line looks like this, the file is
-# autoloaded as a function and that function will
-# be called to generate the matches when completing
-# for one of the commands whose <name> is given
+# `#compdef <names ...>'
+# If the first line looks like this, the file is autoloaded as a
+# function and that function will be called to generate the matches
+# when completing for one of the commands whose <names> are given.
#
-# `#defpatcomp <pattern>'
-# this defines a function that should be called to generate
-# matches for commands whose name matches <pattern>; note
-# that only one pattern may be given
+# `#compdef -p <pattern>'
+# This defines a function that should be called to generate matches
+# for commands whose name matches <pattern>. Note that only one pattern
+# may be given.
#
-# `#defkeycomp <style> [ <key-sequence> ... ]
-# this is used to bind special completions to all the given
+# `#compdef -k <style> [ <key-sequence> ... ]'
+# This is used to bind special completions to all the given
# <key-sequence>(s). The <style> is the name of one of the built-in
# completion widgets (complete-word, delete-char-or-list,
# expand-or-complete, expand-or-complete-prefix, list-choices,
@@ -29,35 +27,89 @@
# rather than by the context. The widget has the same name as
# the autoload file and can be bound using bindkey in the normal way.
#
-# `#autoload'
-# this is for helper functions that are not used to
+# `#compdef -K <widget-name> <style> <key-sequence> [ ... ]'
+# This is similar to -k, except it takes any number of sets of
+# three arguments. In each set, the widget <widget-name> will
+# be defined, which will behave as <style>, as with -k, and will
+# be bound to <key-sequence>, exactly one of which must be defined.
+# <widget-name> must be different for each: this must begin with an
+# underscore, else one will be added, and should not clash with other
+# completion widgets (names based on the name of the function are the
+# clearest), but is otherwise arbitrary. It can be tested in the
+# function by the parameter $WIDGET.
+#
+# `#autoload [ <options> ]'
+# This is for helper functions that are not used to
# generate matches, but should automatically be loaded
-# when they are called
+# when they are called. The <options> will be given to the
+# autoload builtin when making the function autoloaded. Note
+# that this need not include `-U'.
#
# 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.
-#
-# 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.
+# 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 we got the `-d'-flag, we will automatically dump the new state (at
-# the end).
+# the end). This takes the dumpfile as an argument. -d (with the
+# default dumpfile) is now the default; to turn off dumping use -D.
+
+emulate -L zsh
+setopt extendedglob
+
+typeset _i_dumpfile _i_files _i_line _i_done _i_dir _i_autodump=1
+typeset _i_tag _i_file _i_addfiles
+
+while [[ $# -gt 0 && $1 = -[dDf] ]]; do
+ if [[ "$1" = -d ]]; then
+ _i_autodump=1
+ shift
+ if [[ $# -gt 0 && "$1" != -[df] ]]; then
+ _i_dumpfile="$1"
+ shift
+ fi
+ elif [[ "$1" = -D ]]; then
+ _i_autodump=0
+ shift
+ elif [[ "$1" = -f ]]; then
+ # Not used any more; use _compdir
+ shift
+ shift
+ fi
+done
-if [[ "$1" = -d ]]; then
- _i_autodump=1
+# The associative array containing the definitions for the commands.
+# Definitions for patterns will be stored in the associations `_patcomps'
+# and `_postpatcomps'. `_compautos' contains the names and options
+# for autoloaded functions that get options.
+
+typeset -gA _comps _patcomps _postpatcomps _compautos
+
+# The associative array use to report information about the last
+# cmpletion to the outside.
+
+typeset -gA _lastcomp
+
+# Remember dumpfile.
+if [[ -n $_i_dumpfile ]]; then
+ # Explicitly supplied dumpfile.
+ _comp_dumpfile="$_i_dumpfile"
else
- _i_autodump=0
+ _comp_dumpfile="${ZDOTDIR:-$HOME}/.zcompdump"
fi
-# The associative array containing the definitions for the commands.
-# Definitions for patterns will be stored in the normal array `_patcomps'.
+# These can hold names of functions that are to be called before/after all
+# matches have been generated.
-typeset -A _comps
-_patcomps=()
+compprefuncs=()
+comppostfuncs=()
+
+# Loading it now ensures that the `funcstack' parameter is always correct.
+
+: $funcstack
# This function is used to register or delete completion functions. For
# registering completion functions, it is invoked with the name of the
@@ -70,6 +122,9 @@ _patcomps=()
# function will be invoked when completing for a command whose name
# matches the pattern given as argument after the function name (in this
# case only one argument is accepted).
+# The option `-P' is like `-p', but the function will be called after
+# trying to find a function defined for the command on the line if no
+# such function could be found.
# With the `-k' option a function for a special completion keys is
# defined and immediatly bound to those keys. Here, the extra arguments
# are the name of one of the builtin completion widgets and any number
@@ -78,7 +133,8 @@ _patcomps=()
# whose name is given as the first argument be autoloaded. When defining
# a function for command names the `-n' option may be given and keeps
# the definitions from overriding any previous definitions for the
-# commands.
+# commands; with `-k', the `-n' option prevents compdef from rebinding
+# a key sequence which is already bound.
# For deleting definitions, the `-d' option must be given. Without the
# `-p' option, this deletes definitions for functions for the commands
# whose names are given as arguments. If combined with the `-p' option
@@ -110,11 +166,16 @@ compdef() {
# Get the options.
- while getopts "anpkd" opt; do
+ if [[ $#* -eq 0 ]]; then
+ echo "compdef needs parameters"
+ return 1
+ fi
+
+ while getopts "anpPkKd" opt; do
case "$opt" in
a) autol=yes;;
n) new=yes;;
- [pk]) if [[ -n "$type" ]]; then
+ [pPkK]) if [[ -n "$type" ]]; then
# Error if both `-p' and `-k' are given (or one of them
# twice).
echo "$0: type already set to $type"
@@ -122,6 +183,10 @@ compdef() {
fi
if [[ "$opt" = p ]]; then
type=pattern
+ elif [[ "$opt" = P ]]; then
+ type=postpattern
+ elif [[ "$opt" = K ]]; then
+ type=widgetkey
else
type=key
fi
@@ -131,12 +196,17 @@ compdef() {
done
shift OPTIND-1
+ if [[ $#* -eq 0 ]]; then
+ echo "compdef needs parameters"
+ return 1
+ fi
+
if [[ -z "$delete" ]]; then
# Adding definitions, first get the name of the function name
# and probably do autoloading.
func="$1"
- [[ -n "$autol" ]] && autoload "$func"
+ [[ -n "$autol" ]] && autoload -U "$func"
shift
case "$type" in
@@ -145,11 +215,33 @@ compdef() {
echo "$0: only one pattern allowed"
return 1
fi
- # Patterns are stored in strings like `c* foo', with a space
- # between the pattern and the function name.
-
- _patcomps=("$_patcomps[@]" "$1 $func")
+ _patcomps[$1]="$func"
;;
+ postpattern)
+ if [[ $# -gt 1 ]]; then
+ echo "$0: only one pattern allowed"
+ return 1
+ fi
+ _postpatcomps[$1]="$func"
+ ;;
+ widgetkey)
+ while [[ -n $1 ]]; do
+ if [[ $# -lt 3 ]]; then
+ echo "$0: compdef -K requires <widget> <comp-widget> <key>"
+ return 1
+ fi
+ [[ $1 = _* ]] || 1="_$1"
+ [[ $2 = .* ]] || 2=".$2"
+ zle -C "$1" "$2" "$func"
+ if [[ -n $new ]]; then
+ bindkey "$3" | read -A opt
+ [[ $opt[-1] = undefined-key ]] && bindkey "$3" "$1"
+ else
+ bindkey "$3" "$1"
+ fi
+ shift 3
+ done
+ ;;
key)
if [[ $# -lt 2 ]]; then
echo "$0: missing keys"
@@ -157,30 +249,44 @@ compdef() {
fi
# Define the widget.
- zle -C "$func" "$1" "$func"
+ if [[ $1 = .* ]]; then
+ zle -C "$func" "$1" "$func"
+ else
+ zle -C "$func" ".$1" "$func"
+ fi
shift
# And bind the keys...
for i; do
+ if [[ -n $new ]]; then
+ bindkey "$i" | read -A opt
+ [[ $opt[-1] = undefined-key ]] || continue
+ fi
bindkey "$i" "$func"
done
;;
*)
# For commands store the function name in the `_comps'
# associative array, command names as keys.
- for i; do
- [[ -z "$new" || "${+_comps[$i]}" -eq 0 ]] && _comps[$i]="$func"
- done
+ if [[ -z "$new" ]]; then
+ for i; do
+ _comps[$i]="$func"
+ done
+ else
+ for i; do
+ [[ "${+_comps[$i]}" -eq 0 ]] && _comps[$i]="$func"
+ done
+ fi
;;
esac
else
# Handle the `-d' option, deleting.
case "$type" in
pattern)
- # Note the space.
- for i; do
- _patcomps=("${(@)patcomps:#$i *}")
- done
+ unset "_patcomps[$^@]"
+ ;;
+ postpattern)
+ unset "_postpatcomps[$^@]"
;;
key)
# Oops, cannot do that yet.
@@ -189,81 +295,210 @@ compdef() {
return 1
;;
*)
- # Deleting definitons for command is even simpler.
- for i; do
- unset "_comps[$i]"
- done
+ unset "_comps[$^@]"
esac
fi
}
-# Now we automatically make the definition files autoloaded.
+# Do *not* use this...
-# First we get the name of a dump file if this will be used.
+compconf() {
-: ${COMPDUMP:=$0.dump}
+ local style name val i tmp cmt
-if [[ ! -o extendedglob ]]; then
- _i_noextglob=yes
- setopt extendedglob
-fi
+ if [[ -z "$_compconf_warn" ]]; then
+ _compconf_warn=yep
+
+ print "
+
+Hello
+
+\`compconf' will be removed in the near future, we now use a more
+general (and powerful) mechanism using the \`zstyle' builtin. An
+approximation to your old setup using \`zstyle' should be available
+in the file:
+
+ \`${HOME}/.zsh-styles'
+
+Note that the values for the styles may be partly incorrect. Please
+read the manual to find out how to configure the completion system
+with styles.
+
+Have fun
+
+ Sven
+" 1>&2
+ command rm -f ${HOME}/.zsh-styles
+ fi
+
+ for i; do
+ name="${i%%\=*}"
+ val="${i#*\=}"
+
+ tmp=''
+ cmt=''
+
+ case "$name" in
+ urls_path)
+ tmp="'*:urls' path ${(qq)val}"
+ ;;
+ urls_localhttp)
+ tmp="'*:urls' local ${${(qqs.:.)val}}"
+ ;;
+ describe_options)
+ tmp="'*:options' verbose 'yes'"
+ ;;
+ describe_values)
+ tmp="'*:values' verbose 'yes'"
+ ;;
+ autodescribe_options)
+ tmp="'*:options' auto-description ${(qq)val}"
+ ;;
+ description_format)
+ tmp="'*:descriptions' format ${(qq)val}"
+ ;;
+ message_format)
+ tmp="'*:messages' format ${(qq)val}"
+ ;;
+ warning_format)
+ tmp="'*:warnings' format ${(qq)val}"
+ ;;
+ option_prefix)
+ tmp="'*:options' prefix-needed yes"
+ [[ "$val" = hide* ]] &&
+ tmp="$tmp
+zstyle ':completion:*:options' prefix-hidden yes"
+ ;;
+ group_matches)
+ tmp="'*' group-name ''"
+ ;;
+ colors_path)
+ tmp="'*:colors' path ${(qq)val}"
+ ;;
+ path_expand)
+ tmp="'*:paths' expand ${(qq)val}"
+ ;;
+ path_cursor)
+ tmp="'*:paths' cursor ${(qq)val}"
+ ;;
+ (approximate|incremental|predict|list|oldlist|match)_*)
+ tmp="'*${name%%_*}:*' ${${name#*_}//_/-} ${(qq)val}"
+ ;;
+ correct_*)
+ cmt="# This one is a bit ugly. You may want to use only \`*:correct'
+# if you also have the \`correctword_*' or \`approximate_*' keys.
+"
+ tmp="'*(correct(|-word)|approximate):*' ${name#*_} ${(qq)val}"
+ ;;
+ correctword_*)
+ tmp="'*:correct-word' ${name#correctword_} ${(qq)val}"
+ ;;
+ expand_*)
+ cmt="# This one is a bit ugly. You may want to use only \`*:expand'
+# if you also have the \`expandword_*' keys.
+"
+ tmp="'*expand(|expand-word):*' ${name#*_} ${(qq)val}"
+ ;;
+ expandword_*)
+ tmp="'expand-word:*' ${name#expandword_} ${(qq)val}"
+ ;;
+ history_*)
+ tmp="'history-words:*' ${name#history_} ${(qq)val}"
+ ;;
+ completer)
+ tmp="'*' completer ${${(qqs.:.)val}}"
+ ;;
+ last_prompt)
+ tmp="'*' last-prompt 'yes'"
+ ;;
+ esac
+ [[ -n "$tmp" ]] && style="${style}${cmt}zstyle :completion:${tmp}
+"
+ done
+
+ eval "${style}"
+
+ print "$style" >>! ${HOME}/.zsh-styles
+}
+
+# Now we automatically make the definition files autoloaded.
typeset -U _i_files
-_i_files=( ${^~fpath}/_*~*~(N:t) )
-_i_initname=$0
+_i_files=( ${^~fpath:/.}/^([^_]*|*~|*.zwc)(N:t) )
+if [[ $#_i_files -lt 20 || $_compdir = */Core || -d $_compdir/Core ]]; then
+ # Too few files: we need some more directories,
+ # or we need to check that all directories (not just Core) are present.
+ if [[ -n $_compdir ]]; then
+ _i_addfiles=()
+ if [[ $_compdir = */Core ]]; then
+ # Add all the Completion subdirectories
+ _i_addfiles=(${_compdir:h}/*(/))
+ elif [[ -d $_compdir/Core ]]; then
+ # Likewise
+ _i_addfiles=(${_compdir}/*(/))
+ fi
+ for _i_line in {1..$#i_addfiles}; do
+ _i_file=${_i_addfiles[$_i_line]}
+ [[ -d $_i_file && -z ${fpath[(r)$_i_file]} ]] ||
+ _i_addfiles[$_i_line]=
+ done
+ fpath=($fpath $_i_addfiles)
+ _i_files=( ${^~fpath:/.}/^([^_]*|*~|*.zwc)(N:t) )
+ fi
+fi
+
+
+# Rebind the standard widgets
+for _i_line in complete-word delete-char-or-list expand-or-complete \
+ expand-or-complete-prefix list-choices menu-complete \
+ menu-expand-or-complete reverse-menu-complete; do
+ zle -C $_i_line .$_i_line _main_complete
+done
+zle -la menu-select && zle -C menu-select .menu-select _main_complete
+
_i_done=''
+# Make sure compdump is available, even if we aren't going to use it.
+autoload -U compdump compinstall
+
# If we have a dump file, load it.
-if [[ -f "$COMPDUMP" ]]; then
- read -rA _i_line < "$COMPDUMP"
+if [[ -f "$_comp_dumpfile" ]]; then
+ read -rA _i_line < "$_comp_dumpfile"
if [[ _i_autodump -eq 1 && $_i_line[2] -eq $#_i_files ]]; then
- builtin . "$COMPDUMP"
+ builtin . "$_comp_dumpfile"
_i_done=yes
fi
- unset _i_line
fi
if [[ -z "$_i_done" ]]; then
for _i_dir in $fpath; do
[[ $_i_dir = . ]] && continue
- for _i_file in $_i_dir/_*~*~(N); do
+ for _i_file in $_i_dir/^([^_]*|*~|*.zwc)(N); do
read -rA _i_line < $_i_file
_i_tag=$_i_line[1]
shift _i_line
- if [[ $_i_tag = '#defcomp' ]]; then
- compdef -na "${_i_file:t}" "${_i_line[@]}"
- elif [[ $_i_tag = '#defpatcomp' ]]; then
- compdef -pa "${_i_file:t}" "${_i_line[@]}"
- elif [[ $_i_tag = '#defkeycomp' ]]; then
- compdef -ka "${_i_file:t}" "${_i_line[@]}"
- elif [[ $_i_tag = '#autoload' ]]; then
- autoload ${_i_file:t}
- fi
+ case $_i_tag in
+ (\#compdef)
+ if [[ $_i_line[1] = -[pPkK](n|) ]]; then
+ compdef ${_i_line[1]}na "${_i_file:t}" "${(@)_i_line[2,-1]}"
+ else
+ compdef -na "${_i_file:t}" "${_i_line[@]}"
+ fi
+ ;;
+ (\#autoload)
+ autoload -U "$_i_line[@]" ${_i_file:t}
+ [[ "$_i_line" != \ # ]] && _compautos[${_i_file:t}]="$_i_line"
+ ;;
+ esac
done
done
- bindkey |
- while read -rA _i_line; do
- if [[ "$_i_line[2]" = complete-word ||
- "$_i_line[2]" = delete-char-or-list ||
- "$_i_line[2]" = expand-or-complete ||
- "$_i_line[2]" = expand-or-complete-prefix ||
- "$_i_line[2]" = list-choices ||
- "$_i_line[2]" = menu-complete ||
- "$_i_line[2]" = menu-expand-or-complete ||
- "$_i_line[2]" = reverse-menu-complete ]]; then
- zle -C _complete_$_i_line[2] $_i_line[2] _main_complete
- bindkey "${_i_line[1][2,-2]}" _complete_$_i_line[2]
- fi
- done
-
- unset _i_dir _i_line _i_file _i_tag
-
# If autodumping was requested, do it now.
- (( _i_autodump )) && builtin . ${_i_initname:h}/compdump
+ if [[ $_i_autodump = 1 ]]; then
+ compdump
+ fi
fi
-[[ -z "$_i_noextglob" ]] || unsetopt extendedglob
-
-unset _i_files _i_initname _i_done _i_autodump _i_noextglob
+unfunction compinit
+autoload -U compinit
diff --git a/Completion/Core/compinstall b/Completion/Core/compinstall
index d96121cf2..ad05cb5a1 100644
--- a/Completion/Core/compinstall
+++ b/Completion/Core/compinstall
@@ -1,72 +1,149 @@
-# This script is to be run by a user to setup the new function based
+# This script is to be run by a user to set up the new function based
# completion system. The functions themselves are assumed to be already
# available in some directory; they should have been installed with the
-# the shell (except we haven't written that yet).
+# the shell. If they have been, the commands `autoload -U compinit; compinit'
+# in the shell startup file should be enough, although you can run
+# compinstall for more configuration choices.
#
-# Run it as a script under zsh and answer the questions.
-# You can run it as `zsh compinstall $FPATH' and it will be able to check
-# your function path for the completion functions.
-#
-# Normally, this will alter ~/.zshrc (or wherever ZDOTDIR puts it),
-# but you can make that unwritable and it will leave the lines in a
-# temporary file instead.
-#
-# You can use this script to modify what compinstall previously
-# added to ~/.zshrc.
+# Simply run this script as a function and answer the questions.
+# Normally it will alter ~/.zshrc (or wherever ZDOTDIR puts it), but you
+# can make that unwritable and it will leave the lines in a temporary file
+# instead. It doesn't matter if .zshrc didn't exist before. If your
+# .zshrc usually exits before the end, then you should take the code added
+# by compinstall and put it (including the comment lines at the start and
+# end) at the point you want it to be executed. If you run compinstall
+# again it will find and replace those lines, so you can use this script to
+# modify what compinstall previously added to ~/.zshrc.
#
# It is safe to abort with ^C any time you are being prompted for
# information; your .zshrc will not be altered.
#
# To do:
-# - Maybe this should be sourced, then it can check the user's current
-# setup better. But then there is a potentially horrendous option
-# setting/resetting problem. (Maybe we need another way of doing that.)
# - Should probably offer to set different options for _approximate than
# for _complete if both are used.
# - Could add code for setting other completers and options.
# - Could add keys for context-sensitive help.
-# - Probably should allow a set of directories to be added to $fpath,
-# like Core, Base, etc.
-# In case a startup script changed options
-emulate zsh
-[[ -n $1 ]] && FPATH=$1
+emulate -L zsh
-for f in $fpath; do
- if [[ $f != . && -f $f/compinit && -f $f/compdump ]]; then
- fdir=$f
- break
- fi
-done
+typeset _ci_options _ci_f _ci_fdir _ci_files _ci_dumpfile _ci_lines
+typeset _ci_type _ci_completer _ci_accept _ci_cprompt _ci_startline
+typeset _ci_endline _ci_ifile _ci_tmpf _ci_compstyle _ci_warn
+typeset _ci_dtype _ci_existing _ci_line _ci_end
-if [[ -z $fdir ]]; then
- print "Trying to find where the completion functions are..."
- if [[ $0 = */* && -f $0:h/compinit && -f $0:h/compdump ]]; then
- fdir=$0:h
- else
- # more guesses?
- print \
+# Look for the defaults.
+_ci_startline='# The following lines were added by compinstall'
+_ci_endline='# End of lines added by compinstall'
+
+_ci_ifile=${ZDOTDIR:-~}/.zshrc
+_ci_lines=''
+_ci_existing=''
+
+typeset -A _ci_defaults
+
+if [[ -f $_ci_ifile ]]; then
+ # This assumes the lines haven't been altered by the user too much
+ # after they were added.
+ _ci_compstyle=0
+ sed -n "/^$_ci_startline/,/^$_ci_endline/p" $_ci_ifile |
+ while read -rA _ci_line; do
+ if (( $_ci_compstyle )); then
+ # parse a compstyle component as first argument
+ if [[ $_ci_line[-1] != \\ ]]; then
+ _ci_end=-1
+ _ci_compstyle=0
+ else
+ _ci_end=-2
+ fi
+ if [[ $_ci_line[1] = *=* ]]; then
+ _ci_f="${${_ci_line[1,$_ci_end]}#*=}"
+ if [[ $_ci_f = \'*\' ]]; then
+ # strip quotes
+ _ci_f=${_ci_f[2,-2]//\'\\\'\'/\'}
+ fi
+ _ci_defaults[${_ci_line[1]%%\=*}]=$_ci_f
+ fi
+ _ci_existing="${_ci_existing} $_ci_line
+"
+ elif [[ $_ci_line[1] = compinit ]]; then
+ # parse the line running compinit
+ [[ $_ci_line[2] = -f ]] && _ci_fdir=$_ci_line[3]
+ [[ $_ci_line[-2] = -d ]] && _ci_dumpfile=$_ci_line[-1]
+ elif [[ $_ci_line[1] = _compdir=* ]]; then
+ _ci_fdir=${_ci_line[1]##_compdir=}
+ elif [[ $_ci_line[1] = compstyle ]]; then
+ # parse a compstyle component as second argument (should be completer)
+ [[ $_ci_line[3] = completer ]] &&
+ _ci_completer=${_ci_line[3,-1]}
+ [[ $_ci_line[-1] == \\ ]] && _ci_compstyle=1
+ _ci_existing="${_ci_existing}$_ci_line
+"
+ elif [[ $_ci_line[1] != \#* && $_ci_line[1] != (autoload|\[\[) ]]; then
+ if [[ -z $_ci_warn ]]; then
+ _ci_warn=1
+ print "Warning: existing lines in compinstall setup not understood:"
+ fi
+ print - $_ci_line
+ _ci_existing="${_ci_existing}$_ci_line
+"
+ fi
+ done
+fi
+
+
+# Find out where the completion functions are kept.
+
+if [[ -z $_ci_fdir || ! -f ${~_ci_fdir}/compinit ||
+ ! -f ${~_ci_fdir}/compdump ]]; then
+ for _ci_f in $fpath; do
+ if [[ $_ci_f != . && -f $_ci_f/compinit && -f $_ci_f/compdump ]]; then
+ _ci_fdir=$_ci_f
+ break
+ elif [[ $_ci_f != . && -f $_ci_f/Core/compinit &&
+ -f $_ci_f/Core/compdump ]]
+ then
+ _ci_fdir=$_ci_f/Core
+ break
+ fi
+ done
+fi
+
+if [[ -z $_ci_fdir || ! -d ${~_ci_fdir} ]]; then
+ print \
"Please edit the name of the directory where the completion functions are
installed. If they are not installed, you will need to find them in the
Completion/* directories of the zsh distribution and install them yourself,
or insult your system manager for incompetence."
- vared -c fdir
- while [[ ! -d ${~fdir} || ! -f ${~fdir}/compinit ||
- ! -f ${~fdir}/compdump ]]; do
- print "I can't find them in that directory. Try again or abort."
- vared fdir
- done
+ vared -c _ci_fdir
+ while [[ ! -d ${~_ci_fdir} ||
+ ((! -f ${~_ci_fdir}/compinit || ! -f ${~_ci_fdir}/compdump) &&
+ (! -f ${~_ci_fdir}/Core/compinit || ! -f ${~_ci_fdir}/Core/compdump)) ]]
+ do
+ print "I can't find them in that directory. Try again or abort."
+ vared _ci_fdir
+ done
+ if [[ -f ${~_ci_fdir}/Core/compinit && ! -f ${~_ci_fdir}/compinit ]]; then
+ _ci_fdir=$_ci_fdir/Core
fi
- eval "fpath=($fdir \$fpath)"
- fdir=${fdir/#$HOME/\~}
- lines="fpath=($fdir \$fpath)\n"
else
- print "Found completion functions in your fpath, will not alter it."
+ print "Keeping existing completion directiory $_ci_fdir"
+fi
+
+if [[ ${~_ci_fdir} != /* ]]; then
+ _ci_fdir=$(cd $_ci_fdir;builtin pwd)
fi
-files=( ${^~fpath:/.}/_(|*[^~])(N:t) )
-if [[ $#files -lt 20 ]]; then
+# Check if this is in fpath already, else put it there (with ~'s expanded).
+_ci_f=${~_ci_fdir}
+[[ -z ${fpath[(r)$_ci_f]} ]] && fpath=($fpath $_ci_f)
+
+# Contract $HOME to ~ in the parameter to be used for writing.
+_ci_fdir=${_ci_fdir/#$HOME/\~}
+
+# Now check the fpath, ignoring the directory .
+_ci_files=( ${^~fpath:/.}/_(|*[^~])(N:t) )
+if [[ $#_ci_files -lt 20 ]]; then
print "
Hmmm, completion functions seem a bit thin on the ground. There should
be lots of files with names beginning with an underscore (_). You should
@@ -75,12 +152,20 @@ look and see what's happened to these.
read
fi
-if [[ -w ${~fdir} && ( ! -f ${~fdir}/compinit.dump ||
- -w ${~fdir}/compinit.dump ) ]]
+
+# Set up the dumpfile
+_ci_dtype=existing
+if [[ -z $_ci_dumpfile ]]; then
+ _ci_dumpfile="${ZDOTDIR:-$HOME}/.zcompdump"
+ _ci_dtype=standard
+fi
+
+if [[ -w ${~_ci_dumpfile:h} && ( ! -f ${~_ci_dumpfile} ||
+ -w ${~_ci_dumpfile} ) ]]
then
print "
-Using standard dumpfile
- ${~fdir}/compinit.dump
+Using $_ci_dtype dumpfile
+ ${_ci_dumpfile}
to speed up initialisation.
[Hit return to continue]"
read
@@ -88,23 +173,32 @@ else
print "
I will force completion to dump its status, which will speed up the shell's
start-up considerably. However, I can't write the file I'd like to, namely
-$fdir/compinit.dump. Please edit a replacement."
- dumpfile='~/.compinit.dump'
- vared dumpfile
- while ! touch ${~dumpfile} >& /dev/null; do
+${_ci_dumpfile}. Please edit a replacement."
+ vared _ci_dumpfile
+ while ! touch ${~_ci_dumpfile} >& /dev/null; do
print "Sorry, I can't write that either. Try again."
- vared dumpfile
+ vared _ci_dumpfile
done
- [[ -s $dumpfile ]] || rm -f $dumpfile
- dumpfile=" $dumpfile"
+ [[ -s $_ci_dumpfile ]] || rm -f $_ci_dumpfile
fi
-fdir=${fdir/#$HOME/\~}
-
-lines="${lines}. $fdir/compinit -d$dumpfile\n"
+_ci_lines="${_ci_lines}_compdir=$_ci_fdir
+[[ -z \$fpath[(r)\$_compdir] ]] && fpath=(\$fpath \$_compdir)
+autoload -U compinit
+compinit"
+[[ $_ci_dtype != standard ]] && _ci_lines="${_ci_lines} $_ci_dumpfile"
+_ci_lines="${_ci_lines}
+"
print "
+Would you like to set some more advanced options? Otherwise, you
+can re-run compinstall later to set these. [n]"
+
+# The whole of the next part should be indented, but I can't be bothered.
+if read -q; then
+
+ print "
In addition to completion, zsh can also perform correction of the
current word, or approximate completion, i.e. completion where the part of
the word typed so far can be corrected; or it can try correction, then
@@ -112,105 +206,156 @@ approximate completion if that fails. Would you like:
0: Just ordinary completion
C: Correction
A: Approximate completion
- B: Both?
-Please type one of the keys above:"
-while read -k type; do
- print
- case $type in
- 0*) completer=_complete
- break
- ;;
- [cC]*) completer=_complete:_correct
- break
- ;;
- [aA]*) completer=_complete:_approximate
- break;
- ;;
- [bB]*) completer=_complete:_correct:_approximate
- break
- ;;
- *) print Try again
- ;;
- esac
-done
-
-lines="${lines}compconf completer=$completer"
-
-
-if [[ $completer = *(correct|approx)* ]]; then
- print "
-Correction and approximation will normally allow up to two errors,
-and you will be able to use a numeric prefix (e.g. <Esc>4) to allow
-more. The standard prompt is \`correct to:'. Do you want to change
-any of this? [n]"
- if read -q; then
- print "Number of errors to accept normally (0 is OK):"
- read accept
- while [[ $accept != <-> ]]; do
- read accept"?Please enter a number: "
- done
- print \
+ B: Both"
+ if [[ -n $_ci_completer ]]; then
+ print " Default: use the current completers:\n$_ci_completer"
+ else
+ print "Please type one of the keys above."
+ fi
+ while read -k _ci_type; do
+ print
+ case $_ci_type in
+ 0*) _ci_completer=_complete
+ break
+ ;;
+ [cC]*) _ci_completer='_complete _correct'
+ break
+ ;;
+ [aA]*) _ci_completer='_complete _approximate'
+ break;
+ ;;
+ [bB]*) _ci_completer='_complete _correct _approximate'
+ break
+ ;;
+ *) [[ -n $_ci_completer ]] && break
+ print Try again
+ ;;
+ esac
+ done
+
+ _ci_lines="${_ci_lines}zstyle ':completion*' completer $_ci_completer"
+
+
+ if [[ $_ci_completer = *(correct|approx)* ]]; then
+ _ci_accept=${_ci_defaults[correct_accept]}
+ _ci_cprompt=${_ci_defaults[correct_prompt]}
+ print "
+Correction and approximation will allow up to ${${_ci_accept:-2}%%[^0-9]*} \
+errors. "
+ case $_ci_accept in
+ *n*!*|*!*n) print "A numeric prefix, if not 1, will cause correction \
+not to be done."
+ ;;
+ *n*) print "A numeric prefix gives the maximum number of errors which \
+will be accepted."
+ ;;
+ *) print "The numeric prefix will not be used."
+ esac
+print "The correction prompt is \`${_ci_cprompt:-correct to:}'.
+Do you want to change any of this? [n]"
+ if read -q; then
+ print "Number of errors to accept normally (0 is OK):"
+ _ci_accept=${_ci_accept%%[^0-9]*}
+ vared _ci_accept
+ while [[ $_ci_accept != <-> ]]; do
+ print "Please enter a number:"
+ vared _ci_accept
+ done
+ print \
"How would you like the numeric prefix to be treated:
0: Not used by correction
- U: Used to given the number of errors
+ U: The number gives the largest number of errors which will be
+ accepted when correcting
I: If present, and not 1, do not perform correction?
Please type one of the keys above:"
- while read -k type; do
- print
- case $type in
- 0*) break
- ;;
- [uU]*) accept="${accept}n"
- break
- ;;
- [Ii]*) accept="${accept}!n"
- break
- ;;
- *) print Try again
- ;;
- esac
- done
- lines="$lines \\\\
- correct_accept='$accept'"
- print "
+ while read -k _ci_type; do
+ print
+ case $_ci_type in
+ 0*) break
+ ;;
+ [uU]*) _ci_accept="${_ci_accept}n"
+ break
+ ;;
+ [Ii]*) _ci_accept="${_ci_accept}!n"
+ break
+ ;;
+ *) print Try again
+ ;;
+ esac
+ done
+ print "
Instead of the prompt \`correct to:', you can have no prompt, or a
prompt of your choosing which can display the number of errors found by
containing the string \`%e'. Do you wish to change the correction
prompt? [n]"
- if read -q; then
- cprompt=''
- print "Edit a new prompt (may be empty):"
- vared cprompt
- lines="$lines \\\\
- correct_prompt='${cprompt//\'/\'\\\'\'}'"
+ if read -q; then
+ print "Edit a new prompt (may be empty):"
+ vared _ci_cprompt
+ [[ -z $_ci_cprompt ]] && _ci_cprompt=':empty:'
+ fi
+ fi
+ if [[ -n $_ci_accept ]]; then
+ _ci_lines="$_ci_lines \\
+ correct_accept='$_ci_accept'"
+ unset '_ci_defaults[correct_accept]'
+ fi
+ if [[ -n $_ci_cprompt ]]; then
+ _ci_cprompt=${_ci_cprompt##:empty:}
+ _ci_lines="$_ci_lines \\
+ correct_prompt='${_ci_cprompt//\'/\'\\\'\'}'"
+ unset '_ci_defaults[correct_prompt]'
fi
fi
-fi
-lines="$lines\n"
+ _ci_warn=''
+ for _ci_f in ${(k)_ci_defaults}; do
+ if [[ -z $_ci_warn ]]; then
+ print "
+(Keeping other existing configuration settings...)"
+ _ci_warn=1
+ fi
+ _ci_lines="$_ci_lines \\
+ ${_ci_f}='${_ci_defaults[$_ci_f]//\'/\'\\\'\'}'"
+ done
+ _ci_lines="$_ci_lines
+"
-startline='# The following lines were added by compinstall'
-endline='# End of lines added by compinstall'
+else
-ifile=${ZDOTDIR:-~}/.zshrc
-[[ -f $ifile ]] || touch $ifile
-tmpf=${TMPPPREFIX:-/tmp/zsh}compinstall$$
+ if [[ -n $_ci_existing ]]; then
+ print -nr "
+I will retain the following lines from the existing completion setup:
+$_ci_existing"
+ _ci_lines="$_ci_lines${_ci_existing}"
+ fi
+
+fi # End of advanced options
-if [[ ! -w $ifile ]]; then
- print "\nI can't write to $ifile. I will leave the lines to add in
-\`$tmpf' and you must add them by hand."
- print "\n$startline\n$lines\n$endline" >$tmpf
- return 0
-fi
-if grep $endline $ifile >& /dev/null; then
- print -- "$startline\n$lines$endline" >$tmpf
- sed -e "/^$endline/r $tmpf
-/^$startline/,/^$endline/d" $ifile >${tmpf}2 && mv ${tmpf}2 $ifile &&
- print "\nSuccesfully modified old compinstall lines in $ifile."
- rm -f $tmpf ${tmpf}2
+[[ -f $_ci_ifile ]] || touch $_ci_ifile
+_ci_tmpf=${TMPPPREFIX:-/tmp/zsh}compinstall$$
+
+if [[ ! -w $_ci_ifile ]]; then
+ print "\nI can't write to $_ci_ifile. I will leave the lines to add in
+\`$_ci_tmpf' and you must add them by hand."
+ print -r - "$_ci_startline
+$_ci_lines$_ci_endline" >$_ci_tmpf
+elif grep $_ci_endline $_ci_ifile >& /dev/null; then
+ print -r - "$_ci_startline
+$_ci_lines$_ci_endline" >$_ci_tmpf
+ sed -e "/^$_ci_endline/r $_ci_tmpf
+/^$_ci_startline/,/^$_ci_endline/d" $_ci_ifile >${_ci_tmpf}2 &&
+ mv ${_ci_tmpf}2 $_ci_ifile &&
+ print "\nSuccesfully modified old compinstall lines in $_ci_ifile."
+ rm -f $_ci_tmpf ${_ci_tmpf}2
else
- print "\n$startline\n$lines\n$endline" >>$ifile &&
- print "\nSuccessfully appended lines to $ifile."
+ print -r - "$_ci_startline
+$_ci_lines$_ci_endline" >>$_ci_ifile &&
+ print "\nSuccessfully appended lines to $_ci_ifile."
fi
+
+unfunction compinstall
+autoload -U compinstall
+
+return 0
diff --git a/Completion/Linux/_rpm b/Completion/Linux/_rpm
index 7fdc80ab0..9ef2d57d9 100644
--- a/Completion/Linux/_rpm
+++ b/Completion/Linux/_rpm
@@ -3,7 +3,7 @@
# This uses `_arguments' in a state-machine kind of way. These states
# have names and before executing the default action for such a state
# we try to call a function with the name `_rpm_<state>'. If such a
-# function exists, we return with it's return status immediatly. This
+# function exists, we return with its return status immediately. This
# allows users to override the default completions by simply defining
# these functions.
# The states (and possible values for the `<state>' above) are:
@@ -43,28 +43,36 @@ local ret=1 tmp expl
# Used by `_arguments', made local here.
-local state lstate line
-tyeset -A options
+local curcontext="$curcontext" state lstate line
+typeset -A opt_args
state=''
# Do simple completions or get the first state.
-_arguments \
+_arguments -C -s \
'--rcfile:resource file:_files' \
'--ftpproxy:FTP proxy server:_hosts' \
'--ftpport:FTP port number:' \
- '-q:*:query:->query' \
- -{V,v,vv,y,-{setperms,setugids,querytags,initdb,showrc}} \
- '-pipe:*:pipe command:_command_names -e' \
- '--verify:*:verify:->verify' \
- -{i,-install}':*:install:->install' \
- -{U,-upgrade}':*:upgrade:->upgrade' \
- -{e,-erase}':*:uninstall:->uninstall' \
- -'b+:build stage:((p\:execute\ \%prep\ stage l\:do\ a\ list\ check c\:execute\ build\ stage i\:execute\ install\ stage b\:build\ a\ binary\ package a\:build\ binary\ and\ source\ packages)):*:build:->build_b' \
- -'t+:build stage:((p\:execute\ \%prep\ stage l\:do\ a\ list\ check c\:execute\ build\ stage i\:execute\ install\ stage b\:build\ a\ binary\ package a\:build\ binary\ and\ source\ packages)):*:build:->build_t' \
+ '-q+[query mode]:*:query:->query' \
+ '*-v[verbose mode]' \
+ --{setperms,setugids,querytags,initdb,showrc} \
+ '--pipe:pipe command:_command_names -e' \
+ -{V,y}'[verify mode]:*:verify:->verify' \
+ '--verify[verify mode]:*:verify:->verify' \
+ '-i+[install mode]:*:install:->install' \
+ '--install:*:install:->install' \
+ '-U+[upgrade mode]:*:upgrade:->upgrade' \
+ '--upgrade:*:upgrade:->upgrade' \
+ '-F+[freshen mode]:*:upgrade:->upgrade' \
+ '--freshen:*:upgrade:->upgrade' \
+ '-e+[uninstall mode]:*:uninstall:->uninstall' \
+ '--erase:*:uninstall:->uninstall' \
+ -'b+[build mode (spec file)]:build stage:((p\:execute\ \%prep\ stage l\:do\ a\ list\ check c\:execute\ build\ stage i\:execute\ install\ stage b\:build\ a\ binary\ package a\:build\ binary\ and\ source\ packages)):*:build:->build_b' \
+ -'t+[build mode (tar file)]:build stage:((p\:execute\ \%prep\ stage l\:do\ a\ list\ check c\:execute\ build\ stage i\:execute\ install\ stage b\:build\ a\ binary\ package a\:build\ binary\ and\ source\ packages)):*:build:->build_t' \
--{rebuild,rmsource,recompile,resign,addsign}':*:RPM package:->package' \
- -{K,-checksig}':*:sigcheck:->sigcheck' \
+ '-K+[signature check mode]:*:sigcheck:->sigcheck' \
+ '--checksig:*:sigcheck:->sigcheck' \
'--rebuilddb:*:rebuild:->rebuild' && ret=0
# As long as we have a state name...
@@ -73,7 +81,7 @@ while [[ -n "$state" ]]; do
# First try to call a user-defined function.
- funcall ret _rpm_$state && return ret
+ _funcall ret _rpm_$state && return ret
# Copy the state and reset `state', to simplify the test above.
@@ -85,24 +93,24 @@ while [[ -n "$state" ]]; do
case "$lstate" in
query)
- _arguments \
- -{v,vv} \
+ _arguments -s \
+ '*-v[verbose mode]' -q \
'--rcfile:resource file:_files' \
'--ftpproxy:FTP proxy server:_hosts' \
'--ftpport:FTP port number:' \
'--root:RPM root directory:_files -/' \
'--dbpath:RPM database path:_files -/' \
'--queryformat:RPM query format:->tags' \
- '-f:file:_files' \
- '-p:RPM package file:->package_file' \
+ '-f[specify file to query owner of]:file:_files' \
+ '-p+[specify uninstalled package file to query]:*:RPM package file:->package_file' \
'--triggeredby:RPM package:->package' \
'--whatprovides:RPM capability:->capability' \
'--whatrequires:RPM capability:->capability' \
'*:RPM package:->package_or_file' && ret=0
;;
verify)
- _arguments \
- -{v,vv} \
+ _arguments -s \
+ '*-v[verbose mode]' '(-y)-V' '(-V)-y' \
'--rcfile:resource file:_files' \
'--ftpproxy:FTP proxy server:_hosts' \
'--ftpport:FTP port number:' \
@@ -112,15 +120,18 @@ while [[ -n "$state" ]]; do
'*:RPM package:->package' && ret=0
;;
upgrade)
- tmp=( --oldpackage )
+ tmp=( -U --oldpackage )
;&
install)
- _arguments "$tmp[@]" \
- -{v,vv} \
+ (( $#tmp )) || tmp=(-i)
+ _arguments -s "$tmp[@]" \
+ '*-v[verbose mode]' \
'--rcfile:resource file:_files' \
'--ftpproxy:FTP proxy server:_hosts' \
'--ftpport:FTP port number:' \
- -{-{badreloc,excludedocs,force,hash,allfiles,ignorearch,ignoreos,includedocs,justdb,nodeps,noorder,noscripts,notriggers,percent,replacefiles,replacepkgs,test},h} \
+ '(-h)--hash' '(--hash)-h' \
+ '(--replacepkgs --replacefiles --oldpackage)--force' \
+ --{badreloc,excludedocs,allfiles,ignorearch,ignoreos,includedocs,justdb,nodeps,noorder,noscripts,notriggers,percent,replacefiles,replacepkgs,test} \
'--relocate:relocate:->relocate' \
'--prefix:package prefix directory:_files -/' \
'--root:RPM root directory:_files -/' \
@@ -128,8 +139,8 @@ while [[ -n "$state" ]]; do
'*:pkg file:->package_file' && ret=0
;;
uninstall)
- _arguments \
- -{v,vv} \
+ _arguments -s \
+ '*-v[verbose mode]' -e \
'--rcfile:resource file:_files' \
'--ftpproxy:FTP proxy server:_hosts' \
'--ftpport:FTP port number:' \
@@ -139,13 +150,13 @@ while [[ -n "$state" ]]; do
'*:RPM package:->package' && ret=0
;;
build_b)
- tmp=( '*:RPM package:->package' )
+ tmp=( '*:spec file:_files -g \*.spec' )
;&
build_t)
(( $#tmp )) || tmp=( '*:tar file:_files -g \*.\(\#i\)tar\(.\*\|\)' )
- _arguments \
- -{v,vv} \
+ _arguments -s \
+ '*-v[verbose mode]' \
'--rcfile:resource file:_files' \
'--ftpproxy:FTP proxy server:_hosts' \
'--ftpport:FTP port number:' \
@@ -156,8 +167,8 @@ while [[ -n "$state" ]]; do
'--timecheck:time check (seconds):' "$tmp[1]" && ret=0
;;
sigcheck)
- _arguments \
- -{v,vv} \
+ _arguments -s \
+ '*-v[verbose mode]' -K \
'--rcfile:resource file:_files' \
'--ftpproxy:FTP proxy server:_hosts' \
'--ftpport:FTP port number:' \
@@ -165,8 +176,8 @@ while [[ -n "$state" ]]; do
'*:RPM package file:->package_or_file' && ret=0
;;
rebuild)
- _arguments \
- -{v,vv} \
+ _arguments -s \
+ '*-v[verbose mode]' \
'--rcfile:resource file:_files' \
'--ftpproxy:FTP proxy server:_hosts' \
'--ftpport:FTP port number:' \
@@ -178,21 +189,23 @@ while [[ -n "$state" ]]; do
state=package_file
;&
package)
- _description expl 'RPM package'
- compadd "$expl[@]" -M 'r:|-=* r:|=*' - $(rpm -qa) && ret=0
+ _wanted packages expl 'RPM package' \
+ compadd -M 'r:|-=* r:|=*' - $(_call packages rpm -qa) && ret=0
;;
package_file)
- if compset -P ftp:; then
+ if compset -P ftp://; then
_hosts -S/ && ret=0
else
- _files -g '*.(#i)rpm' && ret=0
+ _alternative \
+ 'files:RPM package file:_files -g \*.\(\#i\)rpm' \
+ 'prefixes:ftp URL prefix:compadd ftp://' && ret=0
fi
;;
tags)
if compset -P '*\{'; then
- _description expl 'RPM tag'
- compadd "$expl[@]" -M 'm:{a-z}={A-Z}' -S '}' - \
- "${(@)${(@f)$(rpm --querytags)}#RPMTAG_}" && ret=0
+ _wanted tags expl 'RPM tag' \
+ compadd -M 'm:{a-z}={A-Z}' -S '\}' - \
+ "${(@)${(@f)$(_call tags rpm --querytags)}#RPMTAG_}" && ret=0
else
_message 'RPM format'
fi
@@ -201,10 +214,10 @@ while [[ -n "$state" ]]; do
_message 'RPM capability'
;;
relocate)
- if compset -P '*\='; then
- _description expl 'new path'
+ if compset -P '*='; then
+ _description directories expl 'new path'
else
- _description expl 'old path'
+ _description directories expl 'old path'
fi
_files "$expl[@]" -/ && ret=0
diff --git a/Completion/User/_gdb b/Completion/User/_gdb
index ff54e6a07..55e149bb7 100644
--- a/Completion/User/_gdb
+++ b/Completion/User/_gdb
@@ -1,36 +1,44 @@
#compdef gdb
-# This uses the configuration keys `ps_args' and `ps_listargs'
-# described in the `_wait' function.
+local cur="$words[CURRENT]" prev w list ret=1 expl
-local cur="$words[CURRENT]" prev w list ret=1
-
-_long_options -t '*=(CORE|SYM)FILE' '_files' \
- '*=EXECFILE' '_files *(*)' \
- '*=TTY' 'compadd /dev/tty*' && return 0
+[[ "$PREFIX" = --* ]] &&
+ _arguments -- '*=(CORE|SYM)FILE:core file:_files' \
+ '*=EXECFILE:executable:_files \*\(-\*\)' \
+ '*=TTY:terminal device:compadd /dev/tty\*' && return 0
if compset -P '-(cd|directory)='; then
_files -/
elif compset -P '-tty='; then
- compadd - /dev/tty*
+ _wanted devices expl 'terminal device' compadd - /dev/tty*
elif compset -P '-(exec|se)='; then
- _files -/g '*(*)'
+ _description files expl executable
+ _files "$expl[@]" -g '*(-*)'
elif compset -P '-(symbols|core|command)='; then
_files
-elif compset -P -; then
- compadd -QS '' - symbols\= exec\= se\= core\= command\= directory\= \
- cd\= tty\=
- compadd - help h s e c x d nx n quiet q batch fullname f b
+elif [[ "$PREFIX" = -* ]]; then
+ if _wanted options; then
+ while _next_label options expl option; do
+ compadd "$expl[@]" -QS '' - -symbols\= -exec\= -se\= -core\= -command\= \
+ -directory\= -cd\= -tty\= && ret=0
+ compadd "$expl[@]" - -help -h -s -e -c -x -d -nx -n -quiet -q \
+ -batch -fullname -f -b && ret=0
+ (( ret )) || return 0
+ done
+ fi
else
prev="$words[CURRENT-1]"
case "$prev" in
- (-d) _files -/ && return 0 ;;
- (-e) _files -/g '*(*)' && return 0 ;;
+ (-d) _files -/ && return 0 ;;
(-[csx]) _files && return 0 ;;
- (-b) compadd -V baud 0 50 75 110 134 150 200 300 600 1200 1800 2400 4800 \
- 9600 19200 38400 57600 115200 230400 && return 0 ;;
+ (-e) _description files expl executable
+ _files "$expl[@]" -g '*(-*)' && return 0 ;;
+ (-b) _wanted -V values expl 'baud rate' \
+ compadd 0 50 75 110 134 150 200 300 600 1200 1800 2400 4800 \
+ 9600 19200 38400 57600 115200 230400 && return 0 ;;
esac
+
w=( "${(@)words[2,-1]}" )
while [[ "$w[1]" = -* ]]; do
[[ "$w[1]" = -[decsxb] ]] && shift 1 w
@@ -38,13 +46,9 @@ else
done
if [[ $#w -gt 1 ]]; then
- _files && ret=0
- list=("${(F)${(@Mr:COLUMNS-1:)${(f)$(ps ${compconfig[ps_listargs]:-$compconfig[ps_args]} 2>/dev/null)}[2,-1]:#[ ]#${PREFIX}[0-9]#${SUFFIX}[ ]*${w[1]:t}}}
-")
- compadd -y list - ${${${(M)${(f)"$(ps $compconfig[ps_args] 2>/dev/null)"}:#*${w[1]:t}*}## #}%% *} && ret=0
-
- return ret
+ _alternative 'files:: _files' "processes:: _pids -m ${w[1]:t}"
else
- _files -/g '*(*)'
+ _description files expl executable
+ _files "$expl[@]" -g '*(-*)'
fi
fi
diff --git a/Completion/User/_getconf b/Completion/User/_getconf
index 7ce709588..59e9a83bc 100644
--- a/Completion/User/_getconf
+++ b/Completion/User/_getconf
@@ -1,20 +1,19 @@
#compdef getconf
-local expl
+local expl ret=1
if [[ CURRENT -eq 2 ]]; then
_tags syswideconfig pathconfig standardsconfig
while _tags; do
- if _requested -V syswideconfig expl 'systemwide configuration variables'
- then
- compadd "$expl[@]" -S '' ARG_MAX BC_BASE_MAX BC_DIM_MAX BC_SCALE_MAX \
+ _requested -V syswideconfig expl 'systemwide configuration variables' \
+ compadd -S '' ARG_MAX BC_BASE_MAX BC_DIM_MAX BC_SCALE_MAX \
BC_STRING_MAX CHILD_MAX COLL_WEIGHTS_MAX EXPR_NEST_MAX LINE_MAX \
- NGROUPS_MAX OPEN_MAX RE_DUP_MAX STREAM_MAX TZNAME_MAX
- fi
- if _requested -V standardsconfig \
- expl 'system-standards configuration variables'; then
- compadd "$expl[@]" -S '' _POSIX_CHILD_MAX _POSIX_LINK_MAX \
+ NGROUPS_MAX OPEN_MAX RE_DUP_MAX STREAM_MAX TZNAME_MAX && ret=0
+
+ _requested -V standardsconfig \
+ expl 'system-standards configuration variables' \
+ compadd -S '' _POSIX_CHILD_MAX _POSIX_LINK_MAX \
_POSIX_MAX_CANON _POSIX_MAX_INPUT _POSIX_NAME_MAX _POSIX_NGROUPS_MAX \
_POSIX_OPEN_MAX _POSIX_PATH_MAX _POSIX_PIPE_BUF _POSIX_SSIZE_MAX \
_POSIX_STREAM_MAX _POSIX_TZNAME_MAX _POSIX_VERSION \
@@ -22,15 +21,17 @@ if [[ CURRENT -eq 2 ]]; then
POSIX2_BC_STRING_MAX POSIX2_COLL_WEIGHTS_MAX POSIX2_EXPR_NEST_MAX \
POSIX2_LINE_MAX POSIX2_RE_DUP_MAX POSIX2_VERSION POSIX2_C_BIND \
POSIX2_C_DEV POSIX2_FORT_DEV POSIX2_FORT_RUN POSIX2_LOCALEDEF \
- POSIX2_SW_DEV _XOPEN_VERSION
- fi
- if _requested -V pathconfig expl 'system path configuration variables'
- then
- compadd "$expl[@]" -S '' PIPE_BUF _POSIX_CHOWN_RESTRICTED \
- _POSIX_NO_TRUNC _POSIX_VDISABLE
- compadd "$expl[@]" -S ' ' LINK_MAX MAX_CANON MAX_INPUT NAME_MAX PATH_MAX \
- PIPE_BUF
- fi
+ POSIX2_SW_DEV _XOPEN_VERSION && ret=0
+
+ _requested pathconfig &&
+ while _next_label -V pathconfig expl 'system path configuration variables'; do
+ compadd "$expl[@]" -S '' PIPE_BUF _POSIX_CHOWN_RESTRICTED \
+ _POSIX_NO_TRUNC _POSIX_VDISABLE && ret=0
+ compadd "$expl[@]" -S ' ' LINK_MAX MAX_CANON MAX_INPUT NAME_MAX \
+ PATH_MAX PIPE_BUF && ret=0
+ (( ret )) || break
+ done
+ (( ret )) || return 0
done
else
_files -/
diff --git a/Completion/User/_groups b/Completion/User/_groups
index 975189174..27444d26d 100644
--- a/Completion/User/_groups
+++ b/Completion/User/_groups
@@ -1,6 +1,19 @@
#compdef newgrp
-: ${(A)groups:=${${(s: :)$(</etc/group)}%%:*}}
-# : ${(A)groups:=${${(s: :)$(ypcat group.byname)}%%:*}} # If you use NIS
+local expl groups tmp
-compadd $groups
+_wanted groups || return 1
+
+if ! zstyle -a ":completion:${curcontext}:" groups groups; then
+ (( $+_cache_groups )) ||
+ if (( ${+commands[ypcat]} )) &&
+ tmp=$(_call groups ypcat group.byname); then
+ : ${(A)_cache_groups:=${${(f)tmp}%%:*}} # If you use YP
+ else
+ : ${(A)_cache_groups:=${${(s: :)$(</etc/group)}%%:*}}
+ fi
+
+ groups=( "$_cache_groups[@]" )
+fi
+
+_all_labels groups expl group compadd "$@" - "$groups[@]"
diff --git a/Completion/User/_lp b/Completion/User/_lp
index f37c62a14..cfa2a147c 100644
--- a/Completion/User/_lp
+++ b/Completion/User/_lp
@@ -1,50 +1,98 @@
#compdef lp lpr lpq lprm
-local file expl ret=1 list disp strs shown
+local expl ret=1 printer list disp strs shown
if (( ! $+_lp_cache )); then
+ local file entry names i
+
file=( /etc/(printcap|printers.conf)(N) )
- if (( $#file )); then
- _lp_cache=( "${(@)${(@s:|:)${(@)${(@f)$(< $file[1])}:#[ \#]*}%%:*}%%[ ]*}" )
- else
- # Default value. Could probably be improved
+ _lp_cache=()
+ _lp_alias_cache=()
- _lp_cache=( lp0 )
+ if (( $#file )); then
+ while read entry; do
+ if [[ "$entry" = [^[:blank:]\#\*_]*:* ]]; then
+ names=( "${(s:|:)entry%%:*}" )
+ if [[ "$entry" = *:description=* ]]; then
+ disp="${${entry##*:description=}%%:*}"
+ elif [[ $#names -gt 1 && "$names[-1]" = *\ * ]] ;then
+ disp="$names[-1]"
+ else
+ disp=''
+ fi
+ if [[ -n "$disp" ]]; then
+ _lp_cache=( "$_lp_cache[@]" "${names[1]}:${disp}" )
+ _lp_alias_cache=( "$_lp_alias_cache[@]" "${(@)^names[2,-1]:#*\ *}:${disp}" )
+ else
+ _lp_cache=( "$_lp_cache[@]" "${names[1]}" )
+ _lp_alias_cache=( "$_lp_alias_cache[@]" "${(@)names[2,-1]:#*\ *}" )
+ fi
+ fi
+ done < $file[1]
fi
+ (( $#_lp_cache )) || _lp_cache=( 'lp0:Guessed default printer' )
+ (( $#_lp_alias_cache )) || unset _lp_alias_cache
fi
if compset -P -P || [[ "$words[CURRENT-1]" = -P ]]; then
- _wanted printers expl printer && compadd "$expl" - "$_lp_cache[@]"
+ if _wanted printers; then
+ if zstyle -T ":completion:${curcontext}:printers" verbose; then
+ zformat -a list ' -- ' "$_lp_cache[@]"
+ disp=(-ld list)
+ else
+ disp=()
+ fi
+ _all_labels printers expl printer \
+ compadd "$disp[@]" - "${(@)_lp_cache%%:*}" && return 0
+
+ (( $+_lp_alias_cache )) || return 1
+
+ if zstyle -T ":completion:${curcontext}:printers" verbose; then
+ zformat -a list ' -- ' "$_lp_alias_cache[@]"
+ disp=(-ld list)
+ else
+ disp=()
+ fi
+ compadd "$expl[@]" "$disp[@]" - "${(@)_lp_alias_cache%%:*}"
+ else
+ return 1
+ fi
else
if [[ "$words[1]" = (lpq|lprm) ]]; then
- list=( "${(@M)${(f@)$(lpq)}:#[0-9]*}" )
+ if [[ "$words" = *-P* ]]; then
+ printer=(-P "${${words##*-P( |)}%% *}")
+ else
+ printer=()
+ fi
+ list=( ${(M)"${(f@)$(_call jobs lpq $printer 2> /dev/null)}":#[0-9]*} )
if (( $#list )); then
_tags users jobs
while _tags; do
- if _requested users expl user; then
+ if _requested users; then
strs=( "${(@)${(@)list##[^ ]##[ ]##[^ ]##[ ]##}%%[ ]*}" )
if [[ -z "$shown" ]] &&
- zstyle -t ":completion:${curcontext}:users" verbose; then
+ zstyle -T ":completion:${curcontext}:users" verbose; then
disp=(-ld list)
shown=yes
else
disp=()
fi
- compadd "$expl[@]" "$disp[@]" - "$strs[@]" || _users && ret=0
+ _all_labels users expl user compadd "$disp[@]" - "$strs[@]" ||
+ _users && ret=0
fi
- if _requested jobs expl job; then
+ if _requested jobs; then
strs=( "${(@)${(@)list##[^ ]##[ ]##[^ ]##[ ]##[^ ]##[ ]##}%%[ ]*}" )
if [[ -z "$shown" ]] &&
- zstyle -t ":completion:${curcontext}:jobs" verbose; then
+ zstyle -T ":completion:${curcontext}:jobs" verbose; then
disp=(-ld list)
shown=yes
else
disp=()
fi
- compadd "$expl[@]" "$disp[@]" - "$strs[@]" && ret=0
+ _all_labels jobs expl job compadd "$disp[@]" - "$strs[@]" && ret=0
fi
(( ret )) || return 0
done
diff --git a/Completion/User/_make b/Completion/User/_make
index d576b0308..741cbb7dc 100644
--- a/Completion/User/_make
+++ b/Completion/User/_make
@@ -1,3 +1,32 @@
-#defcomp make gmake pmake
+#compdef make gmake pmake
-complist -s "\$(awk '/^[a-zA-Z0-9][^/ ]+:/ {print \$1}' FS=: [mM]akefile)"
+local prev="$words[CURRENT-1]" file expl tmp
+
+if [[ "$prev" = -[CI] ]]; then
+ _files -/
+elif [[ "$prev" = -[foW] ]]; then
+ _files
+else
+ file="$words[(I)-f]"
+ if (( file )); then
+ file="$words[file+1]"
+ elif [[ -e Makefile ]]; then
+ file=Makefile
+ elif [[ -e makefile ]]; then
+ file=makefile
+ else
+ file=''
+ fi
+
+ if [[ -n "$file" ]] && _wanted targets; then
+ tmp=(
+ $(awk '/^[a-zA-Z0-9][^\/ \t]+:/ {print $1}
+ /^\.include *<bsd\.port\.(subdir\.|pre\.)?mk>/ || /^\.include *".*mk\/bsd\.pkg\.(subdir\.)?mk"/ {
+ print "fetch fetch-list extract patch configure build install reinstall deinstall package describe checkpatch checksum makesum" }' \
+ FS=: $file)
+ )
+ _all_labels targets expl 'make target' compadd "$tmp[@]" && return 0
+ fi
+ compset -P 1 '*='
+ _files
+fi
diff --git a/Completion/User/_mh b/Completion/User/_mh
index 67ce49fd2..c1f397744 100644
--- a/Completion/User/_mh
+++ b/Completion/User/_mh
@@ -1,28 +1,36 @@
-#defcomp folder comp inc mark refile repl scan show next prev rmm pick whom mhn mhpath mhpatch
+#compdef 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
# where standard mh library files live. (It works anyway, but this
# will save a little time.)
+
local mymhdir=~/Mail
local mhlib=/usr/lib/mh
+local prev="$words[CURRENT-1]" expl
+
# To be on the safe side, check this exists and if not, get it anyway.
[[ -d $mymhdir ]] || mymhdir=$(mhpath +)
-if [[ -iprefix - ]]; then
+if compset -P 1 -; 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+)/) {
- $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
+ if _wanted options; then
+ _all_labels options expl option \
+ 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
+ fi
+ return 1
+elif compset -P 1 '[+@]' || [[ "$prev" = -draftfolder ]]; then
# Complete folder names.
local mhpath
+
if [[ $IPREFIX != '@' ]]; then
[[ $IPREFIX = '+' ]] || IPREFIX=+
mhpath=$mymhdir
@@ -30,13 +38,12 @@ elif [[ -iprefix '+' || -iprefix '@' || -current -1 -draftfolder ]]; then
mhpath=$(mhpath)
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
+ _wanted files expl 'MH folder' _path_files -W mhpath -/
+elif [[ "$prev" = -(editor|(whatnow|rmm|show|more)proc) ]]; then
+ _command_names -e
+elif [[ "$prev" = -file ]]; then
+ _files
+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,15 +51,16 @@ 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
+ _wanted files expl 'MH template file' _files -W mhfpath -g '*(.)'
+elif [[ "$prev" = -(no|)cc ]]; then
+ _wanted -C "$prev" values expl 'CC address' compadd all to cc me
+elif [[ "$prev" = -[rw]cache ]]; then
+ _wanted -C "$prev" values expl cache compadd public private never ask
else
# Generate sequences.
- local foldnam folddir f
- for f in $argv; do
+ local foldnam folddir f ret
+
+ for f in $words; do
[[ $f = [@+]* ]] && foldnam=$f
done
if [[ $foldnam = '+'* ]]; then
@@ -64,7 +72,14 @@ 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 '<->'
+ if _wanted sequences; then
+ while _next_label sequences expl sequence; do
+ compadd "$expl[@]" $(mark $foldnam 2>/dev/null | awk -F: '{ print $1 }') &&
+ ret=0
+ compadd "$expl[@]" reply next cur prev first last all unseen && ret=0
+ _files "$expl[@]" -W folddir -g '<->' && ret=0
+ (( ret )) || return 0
+ done
+ fi
+ return ret
fi
diff --git a/Completion/User/_nedit b/Completion/User/_nedit
index 1f030e369..a3fcd9785 100644
--- a/Completion/User/_nedit
+++ b/Completion/User/_nedit
@@ -40,10 +40,11 @@ else
'(-background)-bg[specify background color]:background color:_x_color' \
'(-fg)-foreground:foreground color:_x_color' \
'(-foreground)-fg[specify foreground color]:foreground color:_x_color' \
- '-import[load additional preferences file]:nedit preferences file:_files' \
+ '*-import[load additional preferences file]:nedit preferences file:_files' \
"$nedit_common[@]"
fi
-[[ $state = lang ]] && _wanted neditlanguages expl 'language mode' &&
- compadd "$expl[@]" - ${(f)"$(sed -n \
- '/^nedit.languageMode/,/^nedit/ s/.* \([^:]*\).*/\1/p' < ~/.nedit)"}
+[[ $state = lang ]] &&
+ _wanted neditlanguages expl 'language mode' \
+ compadd - ${(f)"$(sed -n \
+ '/^nedit.languageMode/,/^nedit/ s/.* \([^:]*\).*/\1/p' < ~/.nedit)"}
diff --git a/Completion/User/_netscape b/Completion/User/_netscape
index f176083d2..b29c27c6c 100644
--- a/Completion/User/_netscape
+++ b/Completion/User/_netscape
@@ -1,8 +1,9 @@
#compdef netscape
-local state
+local curcontext="$curcontext" state line ret=1
+typeset -A opt_args
-_x_arguments \
+_x_arguments -C \
'-xrm:resource:_x_resource' \
'-help[show usage message]' \
'-version[show the version number and build date]' \
@@ -21,55 +22,70 @@ _x_arguments \
-{,no-}{,irix-}session-management \
-{done-save,ignore}-geometry-prefs \
-{component-bar,composer,edit,messenger,mail,discussions,news} \
- '*:location:->urls'
+ '*:location:->urls' && ret=0
+
+[[ "$state" = "urls" ]] &&
+ _files "$@" && return 0
-[ "$state" = "urls" ] && _files "$@" && return
# Handle netscape remote commands
-if [ "$state" = "remote" ]; then
+if [[ "$state" = "remote" ]]; then
local -a remote_commands
remote_commands=(openURL openFile saveAs mailto addBookmark)
[[ $compstate[quoting] = (double|single) ]] && compset -q
compset -P '*\('
case $IPREFIX in
- openURL*|addBookmark* ) state=urls;;
- openFile* ) _files -W ~;;
- saveAs* )
+ openURL*|addBookmark*) state=urls;;
+ openFile*) _files -W ~;;
+ saveAs*)
if compset -P "*,"; then
- compadd -s")" -M 'm:{a-zA-Z}={A-Za-z}' HTML Text PostScript
+ _wanted types expl 'data type' \
+ compadd -s")" -M 'm:{a-zA-Z}={A-Za-z}' HTML Text PostScript &&
+ ret=0
else
- _path_files -W ~
+ _files -W ~ && ret=0
fi
;;
- mailto* )
+ mailto*)
compset -P "*,"
if compset -P '*@'; then
- _description expl 'remote host name'
- _hosts "$expl[@]" -q -S,
+ _wanted hosts expl 'remote host name' _hosts -q -S, && ret=0
else
- _description expl 'login name'
- _users "$expl[@]" -q -S@
+ _wanted users expl 'login name' _users -q -S@ && ret=0
fi
;;
- * )
- if [ "$QIPREFIX" ]; then
- compadd -q -S '(' -M 'm:{a-zA-Z}={A-Za-z}' $remote_commands
- else
- compadd -s'(' -S '' -M 'm:{a-zA-Z}={A-Za-z}' $remote_commands
+ *)
+ if _wanted commands; then
+ if [[ -z "$QIPREFIX" ]]; then
+ _all_labels commands expl 'remote commands' \
+ compadd -s'(' -S '' -M 'm:{a-zA-Z}={A-Za-z}' - \
+ $remote_commands && ret=0
+ else
+ _all_labels commands expl 'remote commands' \
+ compadd -qS '(' -M 'm:{a-zA-Z}={A-Za-z}' - \
+ $remote_commands && ret=0
+ fi
fi
;;
esac
fi
-if [ "$state" = "urls" ]; then
+if [[ "$state" = "urls" ]]; then
# Complete netscape urls
- if [[ -prefix about: ]]; then
- compset -P about:
- compadd authors blank cache document fonts global hype image-cache \
- license logo memory-cache mozilla plugins
+ if compset -P about: ; then
+ _wanted values expl 'about what' \
+ compadd authors blank cache document fonts global hype image-cache \
+ license logo memory-cache mozilla plugins && ret=0
else
- compadd -S '' about: mocha: javascript:
- _urls "$@"
+ if _wanted prefixes; then
+ while _next_label prefixes expl 'URL prefix'; do
+ compadd "$expl[@]" -S '' about: mocha: javascript: && ret=0
+ _urls "$@" && ret=0
+ (( ret )) || return 0
+ done
+ fi
fi
fi
+
+return ret
diff --git a/Completion/User/_tiff b/Completion/User/_tiff
index bbc331442..8fd008f0f 100644
--- a/Completion/User/_tiff
+++ b/Completion/User/_tiff
@@ -10,21 +10,22 @@ fi
if [[ $# -ne 0 || $+_in_tiff -ne 0 ]]; then
if (( ! $# )); then
- _description expl 'picture file'
+ _description files expl 'picture file'
set -- "$expl[@]"
fi
- _path_files "$@" -g "$pat" || _files "$@" -g '*.(#i)tiff'
+ _wanted files expl 'picture file' _path_files "$@" -g "$pat" - ||
+ _files "$@" "$expl[@]" -g '*.(#i)tiff'
return
fi
local _in_tiff=yes
-local state line ret=1
-typeset -A options
+local curcontext="$curcontext" state line ret=1
+typeset -A opt_args
case "$words[1]" in
tiff2bw)
- _arguments \
+ _arguments -C \
'-c[specify compression scheme]:compression scheme:->compress' \
'-r[specify rows per strip]:rows per strip:' \
'-R[specify percentage of red channel]:percentage of red channel:' \
@@ -59,7 +60,7 @@ tiffcmp)
':second input TIFF file:_files -g \*.\(\#i\)' && ret=0
;;
tiffcp)
- _arguments \
+ _arguments -C \
'-B[write output in bin-endian byte order]' \
'-c[specify compression scheme]:compression scheme:->compress' \
'-o[set initial TIFF directory (file offset)]:file offset:' \
@@ -74,7 +75,7 @@ tiffcp)
'*:input TIFF file:_files -g \*.\(\#i\)' && ret=0
;;
tiffdither)
- _arguments \
+ _arguments -C \
'-c[specify compression scheme]:compression scheme:->compress' \
'-f[specify fill order]:fill order:(lsb2msb msb2lsb)' \
'-r[specify rows per strip]:rows per strip:' \
@@ -102,7 +103,7 @@ tiffinfo)
'*:input TIFF file:_files -g \*.\(\#i\)' && ret=0
;;
tiffmedian)
- _arguments \
+ _arguments -C \
'-r[specify rows per strip]:rows per strip:' \
'-C[specify number of colormap entries]:number of colormap entries:' \
'-c[specify compression scheme]:compression scheme:->compress' \
@@ -135,14 +136,14 @@ fax2tiff)
':FAX input file:_files -g \*.\(\#i\)\(g\[34\]\|fax\)' && ret=0
;;
gif2tiff)
- _arguments \
+ _arguments -C \
'-r[specify rows per strip]:rows per strip:' \
'-c[specify compression scheme]:compression scheme:->compress' \
':input GIF file:_files -g \*.\(\#i\)gif' \
':output file:_files -g \*.\(\#i\)tiff' && ret=0
;;
ppm2tiff)
- _arguments \
+ _arguments -C \
'-r[specify rows per strip]:rows per strip:' \
'-c[specify compression scheme]:compression scheme:->compress' \
'-R[specify resolution]:resolution:' \
@@ -150,14 +151,14 @@ ppm2tiff)
':output file:_files -g \*.\(\#i\)tiff' && ret=0
;;
ras2tiff)
- _arguments \
+ _arguments -C \
'-r[specify rows per strip]:rows per strip:' \
'-c[specify compression scheme]:compression scheme:->compress' \
':input raster image file:_files -g \*.\(\#i\)ras\(\|t\)' \
':output file:_files -g \*.\(\#i\)tiff' && ret=0
;;
pal2rgb)
- _arguments \
+ _arguments -C \
'-C[specify number of bits for colormap entries]:bits for colormap entries:(8 16)' \
'-p[set sample packing]:sample packing:(contig separate)' \
'-c[specify compression scheme]:compression scheme:->compress' \
@@ -166,7 +167,7 @@ pal2rgb)
':output file:_files -g \*.\(\#i\)tiff' && ret=0
;;
*)
- _description expl 'picture file'
+ _description files expl 'picture file'
_files "$expl[@]" -g "$pat" && ret=0
esac
@@ -194,9 +195,13 @@ if [[ -n "$state" ]]; then
;;
esac
else
- _description expl 'compression scheme'
- compadd "$expl[@]" - none g4 packbits && ret=0
- compadd "$expl[@]" -qS: - lzw zip jpeg g3 && ret=0
+ if _wanted values; then
+ while _next_label values expl 'compression scheme'; do
+ compadd "$expl[@]" - none g4 packbits && ret=0
+ compadd "$expl[@]" -qS: - lzw zip jpeg g3 && ret=0
+ (( ret )) || return 0
+ done
+ fi
fi
fi
diff --git a/Completion/User/_urls b/Completion/User/_urls
index 19f7eea3a..03e8902cb 100644
--- a/Completion/User/_urls
+++ b/Completion/User/_urls
@@ -1,65 +1,155 @@
-#autoload
+#compdef curl
# Usage: _urls [-f]
# Options:
-# -f : complete files.
-
-# To complete URLs, you must make a URL database locally such as:
+# -f : complete files first.
+#
+# Configuration styles used:
+#
+# path
+# The path to a directory containing a URL database, such as:
+#
+# % cd ~/.zsh/urls
+# % find . -ls
+# ... drwxr-xr-x ... 512 Sep 3 02:46 .
+# ... drwxr-xr-x ... 512 Sep 3 02:48 ./http
+# ... drwxr-xr-x ... 512 Sep 3 02:52 ./http/www.zsh.org
+# ... drwxr-xr-x ... 512 Sep 3 03:01 ./http/www.zsh.org/mla
+# ... drwxr-xr-x ... 512 Sep 3 03:01 ./http/www.zsh.org/mla/workers
+# ... drwxr-xr-x ... 512 Sep 3 03:01 ./http/www.zsh.org/mla/workers/1999
+# ... -rw-r--r-- ... 0 Sep 3 03:01 ./http/www.zsh.org/mla/workers/1999/index.html
+# ... drwxr-xr-x ... 512 Sep 3 02:48 ./http/sunsite.auc.dk
+# ... drwxr-xr-x ... 512 Sep 3 02:48 ./http/sunsite.auc.dk/zsh
+# ... drwxr-xr-x ... 512 Sep 3 02:47 ./bookmark
+# ... drwxr-xr-x ... 512 Sep 3 02:48 ./bookmark/zsh
+# ... -rw-r--r-- ... 27 Sep 3 02:47 ./bookmark/zsh/home
+# ... -rw-r--r-- ... 20 Sep 3 02:48 ./bookmark/zsh/meta
+# % cat bookmark/zsh/home
+# http://sunsite.auc.dk/zsh/
+# % cat bookmark/zsh/meta
+# http://www.zsh.org/
#
-# % cd ~/.zsh/urls
-# % find . -ls
-# ... drwxr-xr-x ... 512 Sep 3 02:46 .
-# ... drwxr-xr-x ... 512 Sep 3 02:48 ./http
-# ... drwxr-xr-x ... 512 Sep 3 02:52 ./http/www.zsh.org
-# ... drwxr-xr-x ... 512 Sep 3 03:01 ./http/www.zsh.org/mla
-# ... drwxr-xr-x ... 512 Sep 3 03:01 ./http/www.zsh.org/mla/workers
-# ... drwxr-xr-x ... 512 Sep 3 03:01 ./http/www.zsh.org/mla/workers/1999
-# ... -rw-r--r-- ... 0 Sep 3 03:01 ./http/www.zsh.org/mla/workers/1999/index.html
-# ... drwxr-xr-x ... 512 Sep 3 02:48 ./http/sunsite.auc.dk
-# ... drwxr-xr-x ... 512 Sep 3 02:48 ./http/sunsite.auc.dk/zsh
-# ... drwxr-xr-x ... 512 Sep 3 02:47 ./bookmark
-# ... drwxr-xr-x ... 512 Sep 3 02:48 ./bookmark/zsh
-# ... -rw-r--r-- ... 27 Sep 3 02:47 ./bookmark/zsh/home
-# ... -rw-r--r-- ... 20 Sep 3 02:48 ./bookmark/zsh/meta
+# local
+# Specify a local web server as an array with three elements:
+# <hostname> <doc root> <user area>
+# where hostname is the name of the web server, doc root is the path to
+# the default web pages for the server and user area is the directory
+# name used by a user placing web pages within their home area.
+# E.g.:
+# zstyle ':completion:*:urls' local www /usr/local/apache/htdocs public_html
-local ipre scheme dirs files
+local ipre scheme host user uhosts ret=1 expl
+local urls_path localhttp
+zstyle -s ":completion:${curcontext}:urls" path urls_path ||
+ urls_path="${ZDOTDIR:-$HOME}/.zsh/urls"
+zstyle -a ":completion:${curcontext}:urls" local localhttp
+local localhttp_servername="$localhttp[1]"
+local localhttp_documentroot="$localhttp[2]"
+local localhttp_userdir="$localhttp[3]"
if [[ "$1" = -f ]]; then
shift
- _files "$@" && return
-fi
-
-if [[ -z "$compconfig[_urls_dir]" ]]; then
- compconfig[_urls_dir]=${ZDOTDIR:-$HOME}/.zsh/urls
+ _wanted -C -f files && _files "$@" && return
fi
ipre="$IPREFIX"
-if [[ -prefix [-+.a-z0-9]#: ]]; then
- scheme="${PREFIX%%:*}"
- compset -P "[-+.a-z0-9]#:"
-else
- compadd -S '' http:// ftp:// bookmark:
- return
+if ! compset -P '(#b)([-+.a-z0-9]#):' && _wanted -C argument prefixes; then
+ while _next_label prefixes expl 'URL prefix' "$@"; do
+ [[ -d $urls_path/bookmark ]] &&
+ compadd "$expl[@]" -S '' bookmark: && ret=0
+ compadd "$expl[@]" -S '' file: ftp:// gopher:// http:// && ret=0
+ (( ret )) || return 0
+ done
+ return ret
fi
+scheme="$match[1]"
case "$scheme" in
- http) compset -P // || { compadd "$@" -S '' //; return };;
- ftp) compset -P // || { compadd "$@" -S '' //; return };;
+ http|ftp|gopher)
+ if ! compset -P //; then
+ _wanted -C "$scheme" prefixes expl 'end of prefix' compadd "$@" -S '' //
+ return
+ fi
+ ;;
+ file)
+ if ! compset -P //; then
+ _wanted -C file files || return 1
+
+ while _next_label files expl 'local file' "$@"; do
+ if [[ -prefix / ]]; then
+ _path_files "$expl[@]" -S '' -g '*(^/)' && ret=0
+ _path_files "$expl[@]" -S/ -r '/' -/ && ret=0
+ elif [[ -z "$PREFIX" ]]; then
+ compadd "$expl[@]" -S '/' -r '/' - "${PWD%/}" && ret=0
+ fi
+ (( ret )) || return 0
+ done
+ return ret
+ fi
+ ;;
+ bookmark)
+ if [[ -f "$urls_path/$scheme/${(Q)PREFIX}${(Q)SUFFIX}" &&
+ -s "$urls_path/$scheme/${(Q)PREFIX}${(Q)SUFFIX}" ]]; then
+ _wanted -C bookmark bookmarks expl bookmarks \
+ compadd "$@" -U - \
+ "$ipre$(<"$urls_path/$scheme/${(Q)PREFIX}${(Q)SUFFIX}")" && ret=0
+ else
+ if _wanted -C bookmark files; then
+ while _next_label files expl 'bookmark'; do
+ _path_files -W "$urls_path/$scheme" "$expl[@]" -S '' -g '*(^/)' &&
+ ret=0
+ _path_files -W "$urls_path/$scheme" -S/ -r '/' -/ && ret=0
+ (( ret )) || return 0
+ done
+ fi
+ fi
+ return ret
+ ;;
esac
-if [[ "$scheme" = bookmark &&
- -f "$compconfig[_urls_dir]/$scheme/$PREFIX$SUFFIX" &&
- -s "$compconfig[_urls_dir]/$scheme/$PREFIX$SUFFIX" ]]; then
- compadd "$@" -QU -- "$ipre$(<"$compconfig[_urls_dir]/$scheme/$PREFIX$SUFFIX")"
-else
- dirs=($compconfig[_urls_dir]/$scheme/$PREFIX*$SUFFIX(/:t))
- files=($compconfig[_urls_dir]/$scheme/$PREFIX*$SUFFIX(.:t))
- compset -P '*/'
- compadd "$@" -Q -S '/' - $dirs
- if [[ "$scheme" = bookmark ]]; then
- compadd "$@" -QS '' - $files
+# Complete hosts
+if ! compset -P '(#b)([^/]#)/' && _wanted hosts; then
+ uhosts=($urls_path/$scheme/$PREFIX*$SUFFIX(/:t))
+
+ while _next_label hosts expl host "$@"; do
+ (( $#uhosts )) || _hosts -S/ && ret=0
+ [[ "$scheme" = http ]] && uhosts=($uhosts $localhttp_servername)
+ compadd "$expl[@]" -S/ - $uhosts && ret=0
+ (( ret )) || return 0
+ done
+ return ret
+fi
+host="$match[1]"
+
+# Complete part after hostname
+
+_wanted -C local files || return 1
+
+if [[ "$localhttp_servername" = "$host" ]]; then
+ if compset -P \~; then
+ if ! compset -P '(#b)([^/]#)/'; then
+ _users -S/
+ return
+ fi
+ user="$match[1]"
+ while _next_label files expl 'local file'; do
+ _path_files "$expl[@]" -W ~$user/$localhttp_userdir -g '*(^/)' && ret=0
+ _path_files "$expl[@]" -W ~$user/$localhttp_userdir -S/ -r '/' -/ && ret=0
+ (( ret )) || return 0
+ done
else
- compadd "$@" -Q - $files
+ while _next_label files expl 'local file'; do
+ _path_files "$expl[@]" -W $localhttp_documentroot -g '*(^/)' && ret=0
+ _path_files "$expl[@]" -W $localhttp_documentroot -S/ -r '/' -/ && ret=0
+ (( ret )) || return 0
+ done
fi
+else
+ while _next_label files expl 'local file'; do
+ _path_files "$expl[@]" -W $urls_path/$scheme/$host -g '*(^/)' && ret=0
+ _path_files "$expl[@]" -W $urls_path/$scheme/$host -S/ -r '/' -/ && ret=0
+ (( ret )) || return 0
+ done
fi
+return $ret
diff --git a/Completion/User/_users b/Completion/User/_users
index fc1e87e52..d04731af9 100644
--- a/Completion/User/_users
+++ b/Completion/User/_users
@@ -1,6 +1,10 @@
-#autoload
+#compdef last passwd groups
-local expl
+local expl users
-_description expl user
-compgen "$@" "$expl[@]" -u
+_wanted users || return 1
+
+zstyle -a ":completion:${curcontext}:" users users &&
+ _all_labels users expl user compadd "$@" - "$users[@]" && return 0
+
+_all_labels users expl user compadd "$@" - "${(@k)userdirs}"
diff --git a/Completion/User/_users_on b/Completion/User/_users_on
index 920688089..b19cff6e7 100644
--- a/Completion/User/_users_on
+++ b/Completion/User/_users_on
@@ -1,10 +1,12 @@
-#autoload write
+#compdef write
local expl
+_wanted users || return 1
+
if which users >/dev/null; then
- _description expl users logged on
- compadd "$@" "$expl[@]" - $(users) && return 0
+ _all_labels users expl 'users logged on' \
+ compadd "$@" - $(_call users users) && return 0
else
# Other methods of finding out users logged on should be added here
return 1
diff --git a/Completion/X/_x_colormapid b/Completion/X/_x_colormapid
index 4fe6aac42..3c637c1d9 100644
--- a/Completion/X/_x_colormapid
+++ b/Completion/X/_x_colormapid
@@ -2,7 +2,7 @@
local expl list desc
-_wanted colormapids expl 'colormap id' || return 1
+_wanted colormapids || return 1
list=(${(f)"$(xprop -root -f RGB_COLOR_MAP 32xcccccccxx ': $0\n'|awk -F'[ ():]' '/^[a-zA-Z_]+\(RGB_COLOR_MAP\)/ {print $5, "--", $1}')"})
@@ -12,4 +12,5 @@ else
desc=()
fi
-compadd "$expl[@]" "$@" "$desc[@]" - "${(@)list%% *}"
+_all_labels colormapids expl 'colormap id' \
+ compadd "$@" "$desc[@]" - "${(@)list%% *}"
diff --git a/Completion/X/_x_extension b/Completion/X/_x_extension
index 967938e28..11e53fa6c 100644
--- a/Completion/X/_x_extension
+++ b/Completion/X/_x_extension
@@ -2,16 +2,18 @@
local expl
-(( $+_xe_cache )) || _xe_cache=( "${(@)${(@f)$(xdpyinfo)}[(r)number of extensions:*,-1][2,(r)default screen number:*][1,-2]//[ ]}" )
+_wanted extensions || return 1
-_description expl 'X extension'
+(( $+_xe_cache )) || _xe_cache=( "${(@)${(@f)$(xdpyinfo)}[(r)number of extensions:*,-1][2,(r)default screen number:*][1,-2]//[ ]}" )
if [[ "$1" = -a ]]; then
shift
- compadd "$@" "$expl[@]" -M 'm:{a-z}={A-Z} r:|-=* r:|=*' - all "$_xe_cache[@]"
+ _all_labels extensions expl 'X extensions' \
+ compadd "$@" -M 'm:{a-z}={A-Z} r:|-=* r:|=*' - all "$_xe_cache[@]"
else
[[ "$1" = - ]] && shift
- compadd "$@" "$expl[@]" -M 'm:{a-z}={A-Z} r:|-=* r:|=*' - "$_xe_cache[@]"
+ _all_labels extensions expl 'X extensions' \
+ compadd "$@" -M 'm:{a-z}={A-Z} r:|-=* r:|=*' - "$_xe_cache[@]"
fi
diff --git a/Completion/X/_x_font b/Completion/X/_x_font
index e0acb4014..43a713b34 100644
--- a/Completion/X/_x_font
+++ b/Completion/X/_x_font
@@ -1,3 +1,16 @@
#autoload
-_message 'font'
+local expl
+
+_wanted fonts || return 1
+
+# This *has* to be improved some day...
+
+if (( ! $+_font_cache )); then
+ typeset -gU _font_cache
+
+ _font_cache=( "${(@)^${(@f)$(_call fonts xlsfonts)}%%--*}--" )
+fi
+
+_all_labels fonts expl font \
+ compadd -M 'r:|-=* r:|=*' "$@" -S '' - "$_font_cache[@]"
diff --git a/Completion/X/_x_keysym b/Completion/X/_x_keysym
index 6b031014a..f50762f7e 100644
--- a/Completion/X/_x_keysym
+++ b/Completion/X/_x_keysym
@@ -2,6 +2,8 @@
local expl
+_wanted keysyms || return 1
+
if (( ! $+_keysym_cache )); then
local file
@@ -16,5 +18,5 @@ if (( ! $+_keysym_cache )); then
fi
fi
-_description expl 'key symbol'
-compadd "$@" "$expl[@]" -M 'm:{a-z}={A-Z} r:|-=* r:|=*' - $_keysym_cache
+_all_labels keysyms expl 'key symbol' \
+ compadd "$@" -M 'm:{a-z}={A-Z} r:|-=* r:|=*' - $_keysym_cache
diff --git a/Completion/X/_x_window b/Completion/X/_x_window
index 118c7f131..1862db9a7 100644
--- a/Completion/X/_x_window
+++ b/Completion/X/_x_window
@@ -1,19 +1,18 @@
#autoload
-setopt localoptions extendedglob
-
local list expl
-list=( "${(@)${(M@)${(@f)$(xwininfo -root -tree)}:#[ ]#0x[0-9a-f]# \"*}##[ ]#}" )
+_wanted windows || return 1
+
+list=( "${(@)${(M@)${(@f)$(_call windows xwininfo -root -tree)}:#[ ]#0x[0-9a-f]# \"*}##[ ]#}" )
if [[ "$1" = -n ]]; then
shift
- _description expl 'window name'
- compadd "$@" "$expl[@]" -d list - "${(@)${(@)list#*\"}%%\"*}"
+ _all_labels windows expl 'window name' \
+ compadd "$@" -d list - "${(@)${(@)list#*\"}%%\"*}"
else
[[ "$1" = - ]] && shift
- _description expl 'window ID'
- compadd "$@" "$expl[@]" -d list - "${(@)list%% *}"
+ _all_labels windows expl 'window ID' compadd "$@" -d list - "${(@)list%% *}"
fi
diff --git a/Completion/X/_xmodmap b/Completion/X/_xmodmap
index 0f6514eb6..1cd461d4c 100644
--- a/Completion/X/_xmodmap
+++ b/Completion/X/_xmodmap
@@ -1,11 +1,9 @@
#compdef xmodmap
-setopt localoptions extendedglob
+local curcontext="$curcontext" state line ret=1
+typeset -A opt_args
-local state line ret=1
-typeset -A options
-
-_x_arguments \
+_x_arguments -C \
-{help,grammar,verbose,quiet} \
'-n[only show what would be done]' \
'*-e[specify expression]:expression:->expr' \
@@ -57,7 +55,7 @@ if [[ -n "$state" ]]; then
pointer*)
if compset -P '*=[ ]#'; then
compset -P '*[ ]'
- _description expl 'button code'
+ _description values expl 'button code'
compadd "$expl[@]" -qS ' ' 1 2 3 4 5 default
return
else
@@ -84,9 +82,13 @@ if [[ -n "$state" ]]; then
[[ "$what" = *ksym* ]] && _x_keysym "$suf[@]" && ret=0
else
- _description expl command
- compadd "$expl[@]" -S ' ' keycode keysym clear add remove && ret=0
- compadd "$expl[@]" -S ' = ' pointer && ret=0
+ if _wanted commands; then
+ while _next_label commands expl command; do
+ compadd "$expl[@]" -S ' ' keycode keysym clear add remove && ret=0
+ compadd "$expl[@]" -S ' = ' pointer && ret=0
+ (( ret )) || return 0
+ done
+ fi
fi
fi
diff --git a/Completion/X/_xutils b/Completion/X/_xutils
index 1818b447f..4eea8ded1 100644
--- a/Completion/X/_xutils
+++ b/Completion/X/_xutils
@@ -8,7 +8,7 @@ xdpyinfo)
;;
xwininfo)
_x_arguments \
- -{help,int,stats,bits,events,size,wm,shape,frame,all,english,metric} \
+ -{help,int,children,tree,stats,bits,events,size,wm,shape,frame,all,english,metric} \
'(-id -name)-root' \
'(-id -root)-name:name: _x_window -n' \
'(-name -root)-id:id: _x_window'
@@ -46,12 +46,33 @@ xev)
'-rv'
;;
xhost)
- local expl type ret=1
+ local expl type ret=1 tmp
if compset -P '-'; then
- _description expl 'disallow access'
- compadd "$expl[@]" -M 'm:{a-z}={A-Z} r:|[:.]=* r:|=*' - \
- "${${(@M)${(@f)$(xhost)}[2,-1]:#LOCAL:*}#INET:}"
+ tmp=(${(f)"$(xhost)"})
+ shift tmp
+ tmp=(${tmp:#LOCAL:|<*>})
+ if [[ "$tmp" = *:* ]]; then
+ if compset -P '(#b)(*):'; then
+ type="$match[1]"
+ _wanted displays &&
+ while _next_label displays expl 'disallow access'; do
+ { compadd "$expl[@]" -M 'm:{a-z}={A-Z} r:|[:.]=* r:|=*' - \
+ ${${(M)tmp:#(#i)$type:*}#(#i)$type:} ||
+ _hosts "$expl[@]" } && return 0
+ done
+ else
+ _alternative \
+ 'types:name family:compadd -S: ${(L)tmp%%:*}' \
+ 'hosts:host:compadd ${(@)tmp#*:}' && ret=0
+ fi
+ else
+ _wanted displays &&
+ while _next_label displays expl 'disallow access'; do
+ { compadd "$expl[@]" -M 'm:{a-z}={A-Z} r:|[:.]=* r:|=*' - $tmp ||
+ _hosts "$expl[@]" } && return 0
+ done
+ fi
else
compset -P +
@@ -66,9 +87,9 @@ xhost)
krb) _message 'Kerberos V5 principal';;
esac
else
- _description expl 'name family'
- compadd -S: - inet dnet nis krb && ret=0
- _hosts && ret=0
+ _alternative \
+ 'types:name family:compadd -S: - inet dnet nis krb' \
+ 'hosts:: _hosts' && ret=0
fi
return ret
fi
@@ -120,7 +141,7 @@ xrdb)
'(-global -all -screens)-screen' \
'(-global -all -screen)-screens' \
'-n[only display on stdout]' \
- '(-nocpp)-cpp:preprocessor program:_files -g \*\(\*\)' \
+ '(-nocpp)-cpp:preprocessor program:_files -g \*\(-\*\)' \
'(-cpp)-nocpp' \
'(-load -override -merge -remove)-query' \
'(-query -override -merge -remove)-load' \
@@ -131,6 +152,7 @@ xrdb)
'-backup:backup extension:' \
'*-D-:symbol to define:' \
'*-U-:symbol to undefine:' \
- '*-I-:include directory:_files -/'
+ '*-I-:include directory:_files -/' \
+ '*:defaults file:_files'
;;
esac
diff --git a/Completion/X/_xwit b/Completion/X/_xwit
index e86443a32..998627869 100644
--- a/Completion/X/_xwit
+++ b/Completion/X/_xwit
@@ -16,8 +16,8 @@ _xwit_guard () {
_xwit_compopts () {
local expl
- _description options expl option
- compadd "$expl[@]" - ${(k)no[(R)*~0]} || compadd "$expl[@]" - ${(k)no}
+ _wanted options expl option compadd - ${(k)no[(R)*~0]} ||
+ _all_labels options expl option compadd - ${(k)no}
}
_regex_arguments _xwit_parse \
@@ -39,8 +39,8 @@ _regex_arguments _xwit_parse \
\| "/iconmove$nul/" "$guard" "/$word/" ":_message x" "/$word/" ":_message y" \
\| "/id$nul/" "$guard" "/$word/" ":_x_window" \
\| "/(no|)keyrepeat$nul/" "$guard" \
- \( "/[0-9]##$nul/" ":_message keycode" \
- \( "/-$nul/" "/[0-9]##$nul/" ":_message 'last keycode'" \| \) \) \# \
+ \( "/[0-9]##$nul/" ":[[ -prefix [0-9]# ]] && _message keycode" \
+ \( "/-$nul/" "/[0-9]##$nul/" ":[[ -prefix [0-9]# ]] && _message 'last keycode'" \| \) \) \# \
\| "/names$nul/" "$guard" "/$word/" ":_x_window -n" \# \
\| "/[]/" ':_xwit_compopts' \
\) \