diff options
Diffstat (limited to 'Completion/Base')
-rw-r--r-- | Completion/Base/_arguments | 571 | ||||
-rw-r--r-- | Completion/Base/_default | 30 | ||||
-rw-r--r-- | Completion/Base/_describe | 164 | ||||
-rw-r--r-- | Completion/Base/_jobs | 80 | ||||
-rw-r--r-- | Completion/Base/_subscript | 58 | ||||
-rw-r--r-- | Completion/Base/_tilde | 55 | ||||
-rw-r--r-- | Completion/Base/_values | 383 |
7 files changed, 575 insertions, 766 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 |