diff options
Diffstat (limited to 'Completion')
-rw-r--r-- | Completion/Base/_arguments | 1022 | ||||
-rw-r--r-- | Completion/Base/_describe | 104 | ||||
-rw-r--r-- | Completion/Base/_values | 339 | ||||
-rw-r--r-- | Completion/Core/compinit | 4 |
4 files changed, 265 insertions, 1204 deletions
diff --git a/Completion/Base/_arguments b/Completion/Base/_arguments index 173a23a73..9875d979b 100644 --- a/Completion/Base/_arguments +++ b/Completion/Base/_arguments @@ -5,904 +5,294 @@ setopt localoptions extendedglob -local args rest ws cur nth def nm expl descr action opt arg tmp xor -local single uns ret=1 aret soptseq soptseq1 sopts prefix _line odescr -local beg optbeg argbeg nargbeg inopt inrest fromrest cmd="$words[1]" -local matched curopt noargs i tmp1 tmp2 tmp3 suffix match +local long cmd="$words[1]" descr -# Associative arrays used to collect information about the options. +long=$argv[(I)--] +if (( long )); then + local name tmp tmpargv -typeset -A opts dopts odopts xors _options - -# Fill the cache if we were called with different arguments. - -if [[ "$*" != "$_args_cache_descr" ]]; then - _args_cache_descr="$*" - - unset _args_cache_{opts,dopts,odopts,odescr,xors} - typeset -gA _args_cache_{opts,dopts,odopts,xors} - - unset _args_cache_{long,longcmd,single,match,rest,args,sopts,soptseq,soptseq1} - - # Default match spec. - - _args_cache_match='r:|[_-]=* r:|=*' - - # See if we are using single-letter options or have a match spec. - - while [[ "$1" = -(s|M*) ]]; do - if [[ "$1" = -s ]]; then - shift - _args_cache_single=yes - elif [[ "$1" = -M?* ]]; then - _args_cache_match="${1[3,-1]}" - shift - else - _args_cache_match="$2" - shift 2 - fi - done - - # See if we support long options, too. - - nth=$argv[(I)--] - if (( nth )); then - local tmpargv + if [[ long -eq 1 ]]; then + tmpargv=() + else + tmpargv=( "${(@)argv[1,long-1]}" ) + fi - if [[ nth -eq 1 ]]; then - tmpargv=() - else - tmpargv=( "${(@)argv[1,nth-1]}" ) - fi + name=${~words[1]} + if [[ "$name" != /* ]]; then + tmp="$PWD/$name" + fi + name="_args_cache_${name}" + name="${name//[^a-zA-Z0-9_]/_}" - tmp=${~words[1]} - if [[ "$tmp" != /* ]]; then - tmp="$PWD/$tmp" - fi + if (( ! ${(P)+name} )); then + local iopts sopts pattern tmpo cur opt cache + typeset -U lopts - if [[ "$tmp" != "$_args_cache_longcmd" ]]; then - local iopts pattern tmpo - typeset -U lopts + cache=() - _args_cache_longcmd="$tmp" + # We have to build a new long-option cache, get the `-i' and + # `-s' options. - # We have to build the long-option cache anew, get the `-i' and - # `-s' options. + set -- "${(@)argv[long+1,-1]}" - set -- "${(@)argv[nth+1,-1]}" + iopts=() + sopts=() + while [[ "$1" = -[is]* ]]; do + if [[ "$1" = -??* ]]; then + tmp="${1[3,-1]}" + cur=1 + else + tmp="$2" + cur=2 + fi + if [[ "$tmp[1]" = '(' ]]; then + tmp=( ${=tmp[2,-2]} ) + else + tmp=( "${(@P)tmp}" ) + fi + if [[ "$1" = -i* ]]; then + iopts=( "$iopts[@]" "$tmp[@]" ) + else + sopts=( "$sopts[@]" "$tmp[@]" ) + fi + shift cur + done - iopts=() - sopts=() - while [[ "$1" = -[is]* ]]; do - if [[ "$1" = -??* ]]; then - tmp="${1[3,-1]}" - cur=1 - else - tmp="$2" - cur=2 - fi - if [[ "$tmp[1]" = '(' ]]; then - tmp=( ${=tmp[2,-2]} ) - else - tmp=( "${(@P)tmp}" ) - fi - if [[ "$1" = -i* ]]; then - iopts=( "$iopts[@]" "$tmp[@]" ) - else - sopts=( "$sopts[@]" "$tmp[@]" ) - fi - shift cur - done - - # 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. - - lopts=("--${(@)^${(@)${(@)${(@M)${(@ps:\n:j:\n:)${(@)${(@M)${(@f)$(${~words[1]} --help 2>&1)//\[--/ + # 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. + + lopts=("--${(@)^${(@)${(@)${(@M)${(@ps:\n:j:\n:)${(@)${(@M)${(@f)$(${~words[1]} --help 2>&1)//\[--/ --}:#[ ]#-*}//,/ }}:#[ ]#--*}#*--}%%[, ]*}:#}") - # Now remove all ignored options ... - - while (( $#iopts )); do - lopts=( ${lopts:#$~iopts[1]} ) - shift iopts - done + # Now remove all ignored options ... - # ... and add "same" options - - while (( $#sopts )); do - lopts=( $lopts ${lopts/$sopts[1]/$sopts[2]} ) - shift 2 sopts - done - - # Then we walk through the descriptions plus a few builtin ones. + while (( $#iopts )); do + lopts=( ${lopts:#$~iopts[1]} ) + shift iopts + done - set -- "$@" '*=FILE*:file:_files' \ - '*=(DIR|PATH)*:directory:_files -/' '*: :' + # ... and add "same" options - while (( $# )); do + while (( $#sopts )); do + lopts=( $lopts ${lopts/$sopts[1]/$sopts[2]} ) + shift 2 sopts + done - # First, we get the pattern and the action to use and take them - # from the positional parameters. + # Then we walk through the descriptions plus a few builtin ones. - pattern="${${${(M)1#*[^\\]:}[1,-2]}//\\\\:/:}" - descr="${1#${pattern}}" - shift + set -- "$@" '*=FILE*:file:_files' \ + '*=(DIR|PATH)*:directory:_files -/' '*: :' - # 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 (( $# )); do - tmp=("${(@M)lopts:##$~pattern}") - lopts=("${(@)lopts:##$~pattern}") + # First, we get the pattern and the action to use and take them + # from the positional parameters. - (( $#tmp )) || continue + pattern="${${${(M)1#*[^\\]:}[1,-2]}//\\\\:/:}" + descr="${1#${pattern}}" + shift - opt='' + # 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. - # If there are option strings with a `[=', we take these get an - # optional argument. + tmp=("${(@M)lopts:##$~pattern}") + lopts=("${(@)lopts:##$~pattern}") - tmpo=("${(@M)tmp:#*\[\=*}") - if (( $#tmpo )); then - tmp=("${(@)tmp:#*\[\=*}") - tmpo=("${(@)${(@)tmpo%%\=*}//[^a-z0-9-]}") + (( $#tmp )) || continue - if [[ "$descr" = ::* ]]; then - _args_cache_long=( "$_args_cache_long[@]" - "${(@)^tmpo}=${descr}" ) - else - _args_cache_long=( "$_args_cache_long[@]" - "${(@)^tmpo}=:${descr}" ) - fi - fi + opt='' - # Descriptions with `=': mandatory argument. + # If there are option strings with a `[=', we take these get an + # optional argument. - tmpo=("${(@M)tmp:#*\=*}") - if (( $#tmpo )); then - tmp=("${(@)tmp:#*\=*}") - tmpo=("${(@)${(@)tmpo%%\=*}//[^a-z0-9-]}") + tmpo=("${(@M)tmp:#*\[\=*}") + if (( $#tmpo )); then + tmp=("${(@)tmp:#*\[\=*}") + tmpo=("${(@)${(@)tmpo%%\=*}//[^a-z0-9-]}") - if [[ "$descr" = ::* ]]; then - _args_cache_long=( "$_args_cache_long[@]" - "${(@)^tmpo}=${descr[2,-1]}" ) - else - _args_cache_long=( "$_args_cache_long[@]" - "${(@)^tmpo}=${descr}" ) - fi + if [[ "$descr" = ::* ]]; then + cache=( "$cache[@]" "${(@)^tmpo}=${descr}" ) + else + cache=( "$cache[@]" "${(@)^tmpo}=:${descr}" ) fi - - # Everything else is just added as a option without arguments. - - if (( $#tmp )); then - tmp=("${(@)tmp//[^a-zA-Z0-9-]}") - _args_cache_long=( "$_args_cache_long[@]" "$tmp[@]" ) - fi - done - fi - _args_cache_long=( "${(@)_args_cache_long:# #}" ) - - set -- "$tmpargv[@]" "$_args_cache_long[@]" - fi - - # Now parse the arguments... - - odescr=() - args=() - nth=1 - while (( $# )); do - - descr='' - xor='' - - # Get the names of other values that are mutually exclusive with - # this one. - - if [[ "$1" = \(*\)* ]]; then - xor="${${1[2,-1]}%%\)*}" - 1="${1#*\)}" - fi - - # Get a description, if any. - - if [[ "$1" = *\[*\](|:*) ]]; then - descr="${${1#*\[}%%\]*}" - 1="${1/\[$descr\]}" - elif [[ -n "$compconfig[autodescribe_options]" && - "$1" = [-+][^:]##:[^:]#[^\\]:[^:]# ]]; then - descr="${${${${(M)${1#*:}#*[^\\]:}[1,-2]}## #}%% #}" - [[ -n "$descr" ]] && descr="${compconfig[autodescribe_options]//\\%d/$descr}" - fi - - # Description for both the `-foo' and `+foo' form? - - if [[ "$1" = (\*|)(-+|+-)[^:]* ]]; then - - # With a `*' at the beginning, the option may appear more than - # once. - - if [[ "$1" = \** ]]; then - tmp="${1[4,-1]%%:*}" - [[ "$tmp" = *[-+] ]] && tmp="$tmp[1,-2]" - else - tmp="${1[3,-1]%%:*}" - [[ "$tmp" = *[-+] ]] && tmp="$tmp[1,-2]" - xor="$xor -$tmp +$tmp" fi - # 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. - - if [[ "$1" = [^:]##-:* ]]; then - _args_cache_dopts[-$tmp]="${1#*:}" - _args_cache_dopts[+$tmp]="${1#*:}" - elif [[ "$1" = [^:]##[+=]:* ]]; then - _args_cache_odopts[-$tmp]="${1#*:}" - _args_cache_odopts[+$tmp]="${1#*:}" - elif [[ "$1" = *:* ]]; then - _args_cache_opts[-$tmp]="${1#*:}" - _args_cache_opts[+$tmp]="${1#*:}" - else - _args_cache_opts[-$tmp]='' - _args_cache_opts[+$tmp]='' - fi + # Descriptions with `=': mandatory argument. - _args_cache_odescr=( "$_args_cache_odescr[@]" {-,+}"${tmp}:$descr" ) - if [[ -n "$xor" ]]; then - _args_cache_xors[-$tmp]="${${xor##[ ]#}%%[ ]#}" - _args_cache_xors[+$tmp]="${${xor##[ ]#}%%[ ]#}" - fi - elif [[ "$1" = (\*|)[-+]* ]]; then - - # With a `*' at the beginning, the option may appear more than - # once. - - if [[ "$1" = \** ]]; then - tmp="${1[2,-1]%%:*}" - [[ "$tmp" = *[-+] ]] && tmp="$tmp[1,-2]" - else - tmp="${1%%:*}" - [[ "$tmp" = [-+]?*[-+] ]] && tmp="$tmp[1,-2]" - xor="$xor ${tmp%\=}" - fi + tmpo=("${(@M)tmp:#*\=*}") + if (( $#tmpo )); then + tmp=("${(@)tmp:#*\=*}") + tmpo=("${(@)${(@)tmpo%%\=*}//[^a-z0-9-]}") - # 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. - - if [[ "$1" = [^:]##-:* ]]; then - _args_cache_dopts[$tmp]="${1#*:}" - elif [[ "$1" = [^:]##[+=]:* ]]; then - _args_cache_odopts[$tmp]="${1#*:}" - elif [[ "$1" = *:* ]]; then - _args_cache_opts[$tmp]="${1#*:}" - else - _args_cache_opts[$tmp]='' + if [[ "$descr" = ::* ]]; then + cache=( "$cache[@]" "${(@)^tmpo}=${descr[2,-1]}" ) + else + cache=( "$cache[@]" "${(@)^tmpo}=${descr}" ) + fi fi - _args_cache_odescr=( "$_args_cache_odescr[@]" "${tmp%\=}:$descr" ) - [[ -n "$xor" ]] && - _args_cache_xors[${tmp%\=}]="${${xor##[ ]#}%%[ ]#}" - elif [[ "$1" = \*::* ]]; then - # This is `*:...', describing `all other arguments', with argument - # range restriction. + # Everything else is just added as a option without arguments. - if [[ "$1" = \*:::* ]]; then - _args_cache_rest="*${1[3,-1]}" - else - _args_cache_rest="$1" + if (( $#tmp )); then + tmp=("${(@)tmp//[^a-zA-Z0-9-]}") + cache=( "$cache[@]" "$tmp[@]" ) fi - elif [[ "$1" = \*:* ]]; then - - # This is `*:...', describing `all other arguments'. - - _args_cache_rest="${1[3,-1]}" - elif [[ "$1" = :* ]]; then - - # This is `:...', describing `the next argument'. - - _args_cache_args[nth++]="${1#*:}" - else - - # And this is `n:...', describing the `n'th argument. - - _args_cache_args[${1%%:*}]="${1#*:}" - nth=$(( ${1%%:*} + 1 )) - fi - shift - done - - if [[ -n "$_args_cache_single" ]]; then - _args_cache_soptseq="${(@j::)${(@M)${(@k)_args_cache_opts[(R)]}:#[-+]?}#[-+]}" - if [[ -n "$_args_cache_soptseq" ]]; then - _args_cache_soptseq="[$_args_cache_soptseq]#" - _args_cache_soptseq1="$_args_cache_soptseq#" - else - _args_cache_soptseq='' - _args_cache_soptseq1='' - fi - _args_cache_sopts="${(@j::)${(@)${(@M)${=:-${(k)_args_cache_opts} ${(k)_args_cache_dopts} ${(k)_args_cache_odopts}}:#[-+]?(|=)}#?}%\=}" - else - _args_cache_soptseq='' - _args_cache_soptseq1='' - _args_cache_sopts='' + done + eval "${name}=( \"\${(@)cache:# #}\" )" fi + set -- "$tmpargv[@]" "${(@P)name}" fi -soptseq="$_args_cache_soptseq" -soptseq1="$_args_cache_soptseq1" -sopts="$_args_cache_sopts" -args=( "$_args_cache_args[@]" ) -rest="$_args_cache_rest" -opts=( "${(@kv)_args_cache_opts}" ) -dopts=( "${(@kv)_args_cache_dopts}" ) -odopts=( "${(@kv)_args_cache_odopts}" ) -odescr=( "$_args_cache_odescr[@]" ) -xors=( "${(@kv)_args_cache_xors}" ) -single="$_args_cache_single" -match="$_args_cache_match" - -# Parse the command line... - -ws=( "${(@)words[2,-1]}" ) -cur=$(( CURRENT-2 )) -nth=1 -_line=( "$words[1]" ) -beg=2 -argbeg=1 -optbeg=1 -nargbeg=1 - -# ...until the current word is reached. - -while [[ cur -gt 0 ]]; do - - if [[ -n "$def" && -n "$curopt" ]]; then - if [[ -n "$_options[$curopt]" ]]; then - _options[$curopt]="$_options[$curopt]:${ws[1]//:/\\:}" - else - _options[$curopt]="${ws[1]//:/\\:}" - fi - fi +if comparguments -i "$compconfig[autodescribe_options]" "$@"; then + local nm="$compstate[nmatches]" action noargs aret expl local + local next direct odirect equal single match matched ws tmp1 tmp2 - # `def' holds the description for the option we are currently after. - # Check if the next argument for the option is optional. - - if [[ "$def" = :* ]]; then - opt=yes - else - opt='' - fi - arg='' - - # See if we are after an option getting n arguments ended by something - # that matches the current word. - - if [[ "$def" = \**[^\\]:* && "$ws[1]" = ${~${(M)def#*[^\\]:}[2,-2]} ]]; then - def='' - curopt='' - shift 1 ws - (( cur-- )) - (( beg++ )) - continue - fi - - # Remove one description/action pair from `def' if that isn't empty. - - if [[ -n "$def" && "$def" != \** ]]; then - if [[ "$def" = ?*[^\\]:*[^\\]:* ]]; then - def="${def#?*[^\\]:*[^\\]:}" - argbeg="$beg" + if ! comparguments -D descr action; then + if comparguments -a; then + noargs='no more arguments' else - def='' - curopt='' + noargs='no arguments' fi - elif [[ -z "$def" ]]; then - - # Make sure we test for options below and handle normal arguments. - - opt=yes - arg=yes - curopt='' fi - if [[ -n "$opt" ]]; then + while true; do - # `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 [[ -z "$noargs" || -n "$matched" ]]; then + _description expl "$descr" - if (( $+opts[$ws[1]] )); then - - # Options that may only be given once are removed from the - # associative array so that we don't offer them again. - - def="$opts[$ws[1]]" - curopt="$ws[1]" - _options[$curopt]='' - optbeg="$beg" - argbeg="$beg" - inopt=yes - if [[ -n "$xors[$ws[1]]" ]]; then - if [[ "$xors[$ws[1]]" = (*\ |):(\ *|) ]]; then - args=() - rest='' - fi - odescr=( "${(@)odescr:#(${(j:|:)~${=xors[$ws[1]]}}):*}" ) - unset {{,d,od}opts,xors}\[${^=xors[$ws[1]]}\] - fi - else - uns='' - if [[ -n "$sopts" && "$ws[1]" = [-+]${~soptseq}[$sopts] ]]; then - tmp="${ws[1][1]}${ws[1][-1]}" - if (( $+opts[$tmp] )); then - def="$opts[$tmp]" - curopt="$tmp" - for i in ${(s::)ws[1][2,-1]}; do - _options[${ws[1][1]}$i]='' - done - optbeg="$beg" - argbeg="$beg" - inopt=yes - uns="${ws[1][2,-1]}" - opt='' - fi - fi - - # 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 two loops looking very much alike. - - if [[ -n "$opt" && $#dopts -ne 0 ]]; then - - # First we get the option names. - - tmp=( "${(@k)dopts}" ) - - # Then we loop over them and see if the current word begins - # with one of the option names. - - while (( $#tmp )); do - if [[ -n "$sopts" && $tmp[1] = [-+]? ]]; then - if [[ "$ws[1]" = ${tmp[1][1]}${~soptseq}${tmp[1][2]}* ]]; then - uns="${ws[1][2,-1]%%${tmp[1][2]}*}${tmp[1][2]}" - break; - fi - elif [[ "$ws[1]" = ${tmp[1]}* ]]; then - break - fi - shift 1 tmp - done - - if (( $#tmp )); then - - # 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. - - opt='' - def="$dopts[$tmp[1]]" - curopt="$tmp[1]" - _options[$curopt]="${ws[1]#${tmp[1]}}" - optbeg="$beg" - argbeg="$beg" - inopt=yes - if [[ -n "$xors[$tmp[1]]" ]]; then - if [[ "$xors[$ws[1]]" = (*\ |):(\ *|) ]]; then - args=() - rest='' - fi - odescr=( "${(@)odescr:#(${(j:|:)~${=xors[$tmp[1]]}}):*}" ) - unset {{,d,od}opts,xors}\[${^=xors[$tmp[1]]}\] - fi - if [[ "$def" = [^*]*[^\\]:*[^\\]:* ]]; then - def="${def#?*[^\\]:*[^\\]:}" - elif [[ "$def" != \** ]]; then - def='' - fi - fi - fi - if [[ -n "$opt" && $#odopts -ne 0 ]]; then - tmp=( "${(@k)odopts%\=}" ) - while (( $#tmp )); do - if [[ -n "$sopts" && $tmp[1] = [-+]? ]]; then - if [[ "$ws[1]" = ${tmp[1][1]}${~soptseq}${tmp[1][2]}* ]]; then - uns="${ws[1][2,-1]%%${tmp[1][2]}*}${tmp[1][2]}" - break; - fi - elif [[ "$ws[1]" = ${tmp[1]}* ]]; then - break - fi - shift 1 tmp - done - - if (( $#tmp )); then - opt='' - def="$odopts[$tmp[1]]" - curopt="$tmp[1]" - if [[ -z "$def" ]]; then - def="$odopts[$tmp[1]=]" - if [[ "$ws[1]" = ${tmp[1]}?* ]]; then - _options[$curopt]="${ws[1]#${tmp[1]}=}" - else - _options[$curopt]='' - fi - else - if [[ "$ws[1]" = ${tmp[1]}?* ]]; then - _options[$curopt]="${ws[1]#${tmp[1]}}" - else - _options[$curopt]='' - fi - fi - optbeg="$beg" - argbeg="$beg" - inopt=yes - if [[ -n "$xors[$tmp[1]]" ]]; then - if [[ "$xors[$ws[1]]" = (*\ |):(\ *|) ]]; then - args=() - rest='' - fi - odescr=( "${(@)odescr:#(${(j:|:)~${=xors[$tmp[1]]}}):*}" ) - unset {{,d,od}opts,xors}\[${^=xors[$tmp[1]]}\] - fi - - # 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 [[ ( -z "$sopts" && ( "$def" = :* || "$ws[1]" != "$tmp[1]" ) ) || - ( -n "$sopts" && ( ( $tmp[1] = [-+]? && ( "$def" = :* || "$ws[1]" != "${tmp[1][1]}"${~soptseq}"${tmp[1][2]}" ) ) || - ( $tmp[1] != [-+]? && ( "$def" = :* || "$ws[1]" != "$tmp[1]" ) ) ) ) ]]; then - if [[ "$def" = [^*]*[^\\]:*[^\\]:* ]]; then - def="${def#?*[^\\]:*[^\\]:}" - optbeg="$beg" - argbeg="$beg" - elif [[ "$def" != \** ]]; then - def='' - fi - fi - fi - fi - - [[ -n "$sopts" && -n "$opt" && "$ws[1]" = [-+]${~soptseq} ]] && \ - uns="${ws[1][2,-1]}" - - if [[ -n "$uns" ]]; then - uns="${(@j::)${(M@)${(v)=xors[(I)${ws[1][1]}[$uns]]}:#??}#[-+]}" - if [[ -n "$uns" ]]; then - tmp=( - "opts[${(@)^opts[(I)${ws[1][1]}[$uns]]}]" - "dopts[${(@)^dopts[(I)${ws[1][1]}[$uns]]}]" - "odopts[${(@)^odopts[(I)${ws[1][1]}[$uns]]}]" - "xors[${(@)^xors[(I)${ws[1][1]}[$uns]]}]" - ) - odescr=( "${(@)odescr:#${ws[1][1]}[$uns]:*}" ) - (( $#tmp )) && unset "$tmp[@]" - 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='' - _line=( "$_line[@]" "$ws[1]" ) - [[ -n "$inopt" ]] && nargbeg=$(( beg - 1 )) - inopt='' - if [[ -z "$args[nth]" && "$rest" = \*::* ]]; then - inrest=yes - break + if [[ "$action" = -\>* ]]; then + comparguments -W line options + state="${${action[3,-1]##[ ]#}%%[ ]#}" + compstate[restore]='' + aret=yes + else + if [[ -z "$local" ]]; then + local line + typeset -A options + local=yes fi - (( nth++ )) - fi - fi - fi - shift 1 ws - (( cur-- )) - (( beg++ )) -done + comparguments -W line options -[[ -n "$inopt" ]] && nargbeg=$(( beg - 1 )) + if [[ "$action" = \ # ]]; then -# Now generate the matches. + # An empty action means that we should just display a message. -nm="$compstate[nmatches]" + [[ -n "$matched" ]] && compadd -n -Q -S '' -s "$SUFFIX" - "$PREFIX" + _message "$descr" + break -if [[ -z "$def" || "$def" = :* ]]; then - local pre="$PREFIX" + elif [[ "$action" = \(\(*\)\) ]]; then - uns='' + # ((...)) contains literal strings with descriptions. - # We either don't have a description for an argument of an option - # or we have a description for a optional argument. + eval ws\=\( "${action[3,-3]}" \) - opt=yes + _describe -c "$cmd" "$descr" ws -M "$match" - if [[ -z "$def" ]]; then - - # If we have none at all, use the one for this argument position. - - def="$args[nth]" - if [[ -z "$def" ]]; then - def="$rest" - optbeg="$nargbeg" - argbeg="$nargbeg" - fromrest=yes - [[ -n "$inrest" ]] && opt='' - fi - if [[ -z "$def" ]]; then - if [[ -z "$args$rest" ]]; then - noargs='no arguments' - else - noargs='no more arguments' - fi - fi - fi + elif [[ "$action" = \(*\) ]]; then - # In any case, we have to complete option names here, but we may - # be in a string that starts with an option name and continues with - # the first argument, test that (again, two loops). - - if [[ -n "$opt" && $#dopts -ne 0 ]]; then - - # Get the option names. - - tmp=( "${(@k)dopts}" ) - prefix="$PREFIX" - while (( $#tmp )); do - if [[ -n "$sopts" && $tmp[1] = [-+]? ]] && compset -P "${tmp[1][1]}${~soptseq}${tmp[1][2]}"; then - def="$dopts[$tmp[1]]" - opt='' - uns="${prefix[2,-1]%%${tmp[1][2]}*}${tmp[1][2]}" - for i in ${(s::)prefix[2,-1]%%${tmp[1][2]}*} ${tmp[1][2]}; do - _options[${prefix[1]}$i]='' - done - noargs='' - break - elif compset -P "$tmp[1]"; then - - # The current string starts with the option name, so ignore - # that and complete the rest of the string. - - def="$dopts[$tmp[1]]" - opt='' - noargs='' - break - fi - shift 1 tmp - done - fi - if [[ -n "$opt" && $#odopts -ne 0 ]]; then - tmp=( "${(@k)odopts}" ) - prefix="$PREFIX" - while (( $#tmp )); do - if [[ -n "$sopts" && $tmp[1] = [-+]?(|=) ]] && compset -P "${tmp[1][1]}${~soptseq}${tmp[1][2]}${tmp[1][3]}"; then - def="$odopts[$tmp[1]]" - opt='' - uns="${prefix[2,-1]%%${tmp[1][2]}*}${tmp[1][2]}" - for i in ${(s::)prefix[2,-1]%%${tmp[1][2]}*} ${tmp[1][2]}; do - _options[${prefix[1]}$i]='' - done - noargs='' - break - elif compset -P "$tmp[1]"; then - def="$odopts[$tmp[1]]" - opt='' - noargs='' - break - fi - shift 1 tmp - done - fi - - [[ -n "$sopts" && -n "$opt" && "$PREFIX" = [-+]${~soptseq}[$sopts] ]] && - uns="${PREFIX[2,-1]}" - - if [[ -n "$uns" ]]; then - uns="${(@j::)${(M@)${(v)=xors[(I)${ws[1][1]}[$uns]]}:#??}#[-+]}" - if [[ -n "$uns" ]]; then - tmp=( - "opts[${(@)^opts[(I)${pre[1]}[$uns]]}]" - "dopts[${(@)^dopts[(I)${pre[1]}[$uns]]}]" - "odopts[${(@)^odopts[(I)${pre[1]}[$uns](|=)]}]" - "xors[${(@)^xors[(I)${pre[1]}[$uns]]}]" - ) - odescr=( "${(@)odescr:#${pre[1]}[$uns]:*}" ) - (( $#tmp )) && unset "$tmp[@]" - fi - fi - - # If we aren't in an argument directly after a option name, all option - # names are possible matches. - - [[ -z "$opt" || ( "$def" = \** && - ( -z "$fromrest" || CURRENT -ne argbeg+1 ) ) ]] && opt='' -else - opt='' -fi + # Anything inside `(...)' is added directly. -# Now add the matches from the description, if any. + compadd "$expl[@]" - ${=action[2,-2]} + elif [[ "$action" = \{*\} ]]; then -while true; do + # A string in braces is evaluated. - if [[ -n "$def" ]]; then + eval "$action[2,-2]" - # Ignore the leading colon or `*...' describing optional arguments. + elif [[ "$action" = \ * ]]; then - if [[ "$def" = :* ]]; then - def="$def[2,-1]" - elif [[ "$def" = \** ]]; then - tmp="${${(M)def#*[^\\]:}[2,-2]}" - def="${def#*[^\\]:}" + # If the action starts with a space, we just call it. - if [[ "$def" = :* ]]; then - if [[ "$def" = ::* ]]; then - def="$def[3,-1]" - beg=$argbeg + ${(e)=~action} else - def="$def[2,-1]" - beg=$optbeg - fi - - [[ beg -ge $#words ]] && beg=$(( $#words - 1 )) - shift beg words - (( CURRENT -= beg )) + # Otherwise we call it with the description-arguments built above. - if [[ -n "$tmp" ]]; then - tmp="$words[(ib:CURRENT:)${~tmp}]" - [[ tmp -le $#words ]] && words=( "${(@)words[1,tmp-1]}" ) + action=( $=action ) + ${(e)action[1]} "$expl[@]" ${(e)~action[2,-1]} fi fi fi - # Get the description and the action. - - descr="${${${(M)def#*[^\\]:}[1,-2]}//\\\\:/:}" - if [[ "$def" = *[^\\]:*[^\\]:* ]]; then - action="${${${(M)${def#*[^\\]:}#*[^\\]:}[1,-2]}//\\\\:/:}" - else - action="${${def#*[^\\]:}//\\\\:/:}" - fi - - _description expl "$descr" - - if [[ "$action" = -\>* ]]; then - line=( "$_line[@]" ) - options=( "${(@kv)_options}" ) - state="${${action[3,-1]##[ ]#}%%[ ]#}" - compstate[restore]='' - aret=yes - else - if [[ "${(t)line}" != *local* ]]; then - local line - typeset -A options - fi - - line=( "$_line[@]" ) - options=( "${(@kv)_options}" ) - - if [[ "$action" = \ # ]]; then - - # An empty action means that we should just display a message. - - [[ -n "$matched" ]] && compadd -n -Q -S '' -s "$SUFFIX" - "$PREFIX" - _message "$descr" - break - - elif [[ "$action" = \(\(*\)\) ]]; then - - # ((...)) contains literal strings with descriptions. - - eval ws\=\( "${action[3,-3]}" \) - - _describe -c "$cmd" "$descr" ws -M "$match" - - elif [[ "$action" = \(*\) ]]; then - - # Anything inside `(...)' is added directly. - - compadd "$expl[@]" - ${=action[2,-2]} - elif [[ "$action" = \{*\} ]]; then + if [[ -z "$matched" ]] && + comparguments -O next direct odirect equal && + [[ ( ( nm -eq compstate[nmatches] || -n "$noargs" ) && -z "$aret" ) || + -z "$compconfig[option_prefix]" || + "$compconfig[option_prefix]" = *\!${cmd}* || + "$PREFIX" = [-+]* ]]; then - # A string in braces is evaluated. + comparguments -M match - eval "$action[2,-2]" + if comparguments -s single; then - elif [[ "$action" = \ * ]]; then + _description expl option - # If the action starts with a space, we just call it. + 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[@]" ) + tmp2=( "${PREFIX}${(@)^tmp1%%:*}" ) - ${(e)=~action} + _describe -o -c "$cmd" option tmp1 tmp2 -Q -S '' + fi + single=yes else - - # Otherwise we call it with the description-arguments built above. - - action=( $=action ) - ${(e)action[1]} "$expl[@]" ${(e)~action[2,-1]} - fi - fi - fi - - # Probably add the option names. - - if [[ -n "$opt" && - ( ( ( nm -eq compstate[nmatches] || -n "$noargs" ) && -z "$aret" ) || - -z "$compconfig[option_prefix]" || - "$compconfig[option_prefix]" = *\!${cmd}* || - "$PREFIX" = [-+]* ) ]]; then - _description expl option - if [[ -n "$sopts" && -n "$PREFIX" && - "$PREFIX" = [-+]${~soptseq}[$sopts] ]]; then - if [[ "$PREFIX" = [-+]${~soptseq1} ]]; then - tmp1=( "${(@Mo)odescr:#[-+]?:*}" ) - tmp2=( - "${PREFIX}${(@k)^opts[(I)${PREFIX[1]}?]#?}" \ - "${PREFIX}${(@k)^dopts[(I)${PREFIX[1]}?]#?}" \ - "${PREFIX}${(@)^${(@k)odopts[(I)${PREFIX[1]}?(|=)]#?}%=}" - ) - tmp2=( "${(@o)tmp2}" ) - + next=( "$next[@]" "$odirect[@]" ) _describe -o -c "$cmd" option \ - tmp1 tmp2 -Q -M 'r:|[_-]=* r:|=*' - else - # The last option takes an argument in the next word. - - compadd "$expl[@]" -Q -M "$match" - "${PREFIX}" && ret=0 + next -Q -M "$match" -- \ + direct -QS '' -M "$match" -- \ + equal -QqS= -M "$match" fi - else - tmp1=( "${(@k)opts}" "${(@k)odopts[(I)*[^=]]}" ) - tmp1=( "${(@M)odescr:#(${(j:|:)~tmp1}):*}" ) - tmp2=( "${(@M)odescr:#(${(kj:|:)~dopts}):*}" ) - tmp3=( "${(@M)odescr:#(${(kj:|:)~odopts[(I)*=]%=}):*}" ) - _describe -o -c "$cmd" option \ - tmp1 -Q -M "$match" -- \ - tmp2 -QS '' -M "$match" -- \ - tmp3 -QqS= -M "$match" - fi - fi - if [[ nm -eq compstate[nmatches] && - ( ( -z "$single" && "$PREFIX" = [-+]*\=* ) || - ( $#_args_cache_long -ne 0 && "$PREFIX" = --*\=* ) ) ]]; then - tmp=( "${(@Mk)odopts:#[^:]#\=}" ) - prefix="${PREFIX#*\=}" - suffix="$SUFFIX" - PREFIX="${PREFIX%%\=*}" - SUFFIX='' - compadd -M "$match" -D tmp - "${(@)tmp%\=}" - - if [[ $#tmp -eq 1 ]]; then - def="$odopts[$tmp[1]]" - PREFIX="$prefix" - SUFFIX="$suffix" - IPREFIX="$tmp[1]" - matched=yes - continue + if [[ nm -eq compstate[nmatches] && -z "$aret" && + ( ( -z "$single" && "$PREFIX" = [-+]*\=* ) || + "$PREFIX" = --* ) ]]; then + + local prefix suffix + + prefix="${PREFIX#*\=}" + suffix="$SUFFIX" + PREFIX="${PREFIX%%\=*}" + SUFFIX='' + compadd -M "$match" -D equal - "${(@)equal%%:*}" + + if [[ $#equal -eq 1 ]]; then + PREFIX="$prefix" + SUFFIX="$suffix" + IPREFIX="${IPREFIX}${equal[1]%%:*}=" + matched=yes + comparguments -L "$equal[1]" descr action + continue + fi + fi fi - fi + break + done - break -done + [[ -n "$aret" ]] && return 300 -[[ -n "$aret" ]] && return 300 + [[ -n "$noargs" ]] && _message "$noargs" -[[ -n "$noargs" ]] && _message "$noargs" + # Set the return value. -# Set the return value. + [[ nm -ne "$compstate[nmatches]" ]] -[[ nm -ne "$compstate[nmatches]" ]] +else + return 1 +fi diff --git a/Completion/Base/_describe b/Completion/Base/_describe index c95674121..c0b3d7174 100644 --- a/Completion/Base/_describe +++ b/Completion/Base/_describe @@ -4,8 +4,7 @@ setopt localoptions extendedglob -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 +local isopt cmd opt expl tmps tmpd tmpmd tmpms ret=1 showd _nm hide cmd="$words[1]" @@ -45,101 +44,22 @@ else "$compconfig[describe_values]" != *\!${cmd}* ]] && showd=yes fi -gdescr="$1" +_description expl "$1" shift -# Now interpret the arguments. - -nsets=0 -adescr=() -descrs=() -matches=() -while (( $# )); do - (( nsets++ )) - descr="$1" - [[ -n "$showd" ]] && adescr=( "$adescr[@]" "${(@PM)^descr:#*:?*},$nsets" ) - if [[ $# = 1 || "$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=() - else - shift tmp - 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. +if [[ -n "$showd" ]]; then + compdescribe -I ' -- ' "$@" +else + compdescribe -i ' -- ' "$@" +fi - descrs[nsets]="$descr" - matches[nsets]="$match" - typeset -a _descr_opts_$nsets - eval "_descr_opts_${nsets}=( \"\$opt[@]\" )" -done +[[ -n "$isopt" && "$compconfig[option_prefix]" = hide* ]] && hide=yes -(( nsets )) || return 1 - -# Build the display strings if needed. - -[[ -n "$showd" ]] && _display disps "$adescr[@]" -_description expl "$gdescr" - -# 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]" ) - 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 +while compdescribe -g args tmpd tmpmd tmps tmpms; do # See if we should remove the option prefix characters. - if [[ -n "$isopt" && "$compconfig[option_prefix]" = hide* ]]; then + if [[ -n "$hide" ]]; then if [[ "$PREFIX" = --* ]]; then tmpd=( "${(@)tmpd#--}" ) tmps=( "${(@)tmps#--}" ) @@ -148,8 +68,8 @@ while [[ ++i -le nsets ]]; do tmps=( "${(@)tmps#[-+]}" ) fi fi - compadd "${(@P)name}" "$expl[@]" -ld tmpd - "$tmpmd[@]" && ret=0 - compadd "${(@P)name}" "$expl[@]" -d tmps - "$tmpms[@]" && ret=0 + compadd "$args[@]" "$expl[@]" -ld tmpd - "$tmpmd[@]" && ret=0 + compadd "$args[@]" "$expl[@]" -d tmps - "$tmpms[@]" && ret=0 done return ret diff --git a/Completion/Base/_values b/Completion/Base/_values index 5b413313b..aff2f92d8 100644 --- a/Completion/Base/_values +++ b/Completion/Base/_values @@ -2,328 +2,71 @@ setopt localoptions extendedglob -local name arg def descr xor str tmp ret=1 expl nm="$compstate[nmatches]" -local snames odescr gdescr sep esep spat tmp1 tmp2 tmp3 opts -typeset -A names onames xors _values +if compvalues -i "$@"; then -# Probably fill our cache. + local noargs args opts descr action expl sep -if [[ "$*" != "$_vals_cache_args" ]]; then - _vals_cache_args="$*" + if ! compvalues -D descr action; then + compvalues -V noargs args opts - unset _vals_cache_{sep,esep,descr,names,onames,snames,xors,odescr} - - typeset -gA _vals_cache_{names,onames,xors} - _vals_cache_snames=() - _vals_cache_odescr=() - - # Get the separator, if any. - - if [[ "$1" = -s ]]; then - _vals_cache_sep="$2" - [[ -z "$2" ]] && _vals_cache_esep=yes - 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 - - # 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" -esep="$_vals_cache_esep" - -if [[ -n "$sep$esep" ]]; 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. - - if [[ -n "$esep" ]]; then - spat='?*' - else - spat="*${sep}*" - fi - - while [[ "$PREFIX" = $~spat ]]; do - - # Get one part, remove it from PREFIX and put it into IPREFIX. - - if [[ -n "$esep" ]]; then - tmp="$PREFIX[1]" - IPREFIX="${IPREFIX}${tmp}" - PREFIX="${PREFIX[2,-1]}" - else - tmp="${PREFIX%%${sep}*}" - PREFIX="${PREFIX#*${sep}}" - IPREFIX="${IPREFIX}${tmp}${sep}" - fi - - # 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}\[$name\] - fi - done - if [[ "$SUFFIX" = $~spat ]]; then - - # The same for the suffix. - - if [[ -n "$esep" ]]; then - str='' - else - str="${SUFFIX%%${sep}*}" - SUFFIX="${SUFFIX#*${sep}}" - fi + if [[ "$PREFIX" = *\=* ]]; then + local name - while [[ -n "$SUFFIX" ]]; do - if [[ -n "$esep" ]]; then - tmp="$SUFFIX[-1]" - ISUFFIX="${SUFFIX[-1]}$ISUFFIX" - SUFFIX="$SUFFIX[1,-2]" + name="${PREFIX%%\=*}" + if compvalues -L "$name" descr action; then + IPREFIX="${IPREFIX}${name}=" + PREFIX="${PREFIX#*\=}" else - tmp="${SUFFIX##*${sep}}" - if [[ "$SUFFIX" = *${sep}* ]]; then - SUFFIX="${SUFFIX%${sep}*}" - else - SUFFIX='' - fi - ISUFFIX="${sep}${tmp}${ISUFFIX}" - fi + local prefix suffix - name="${tmp%%\=*}" + prefix="${PREFIX#*\=}" + suffix="$SUFFIX" + PREFIX="$name" + SUFFIX='' + args=( "$args[@]" "$opts[@]" ) + compadd -M 'r:|[_-]=* r:|=*' -D args - "${(@)args[@]%%:*}" - if [[ "$tmp" = *\=* ]]; then - _values[$name]="${tmp#*\=}" - else - _values[$name]='' - fi + [[ $#args -ne 1 ]] && return 1 - if [[ -n "$xors[$name]" ]]; then - snames=( "${(@)snames:#(${(j:|:)~${=xors[$name]}})}" ) - odescr=( "${(@)odescr:#(${(j:|:)~${=xors[$name]}}):*}" ) - unset {names,onames,xors}\[$name\] + PREFIX="$prefix" + SUFFIX="$suffix" + IPREFIX="${IPREFIX}${args[1]%%:*}=" + compvalues -L "${args[1]%%:*}" descr action 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 - - # Gets an optional argument, same as previous case. - - def="$onames[$name]" - if ! compset -P '*\='; then - IPREFIX="${IPREFIX}${name}=" - PREFIX="$arg" - SUFFIX='' - 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. + compvalues -d descr + if [[ ${#noargs}+${#args}+${#opts} -ne 1 ]] && compvalues -s sep; then + sep=( "-qQS$sep" ) + else + sep=() + fi - IPREFIX="${IPREFIX}${tmp[1]}=" - PREFIX="$pre" - SUFFIX="$suf" + _describe "$descr" \ + noargs "$sep[@]" -M 'r:|[_-]=* r:|=*' -- \ + args -S= -M 'r:|[_-]=* r:|=*' -- \ + opts -qS= -M 'r:|[_-]=* r:|=*' - 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 + return fi fi -else - - # No `=', just complete value names. - - if [[ -n "$sep" && ${#snames}+${#names}+${#onames} -ne 1 ]]; then - opts=( "-qS$sep" ) - else - opts=() - fi - - tmp1=( "${(@M)odescr:#(${(j:|:)~snames}):*}" ) - tmp2=( "${(@M)odescr:#(${(kj:|:)~names}):*}" ) - tmp3=( "${(@M)odescr:#(${(kj:|:)~onames}):*}" ) - - _describe "$gdescr" \ - tmp1 "$opts[@]" -M 'r:|[_-]=* r:|=*' -- \ - tmp2 -S= "$opts[@]" -M 'r:|[_-]=* r:|=*' -- \ - tmp3 -qS= "$opts[@]" -M 'r:|[_-]=* r:|=*' - - 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" # 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 values state="${${action[3,-1]##[ ]#}%%[ ]#}" compstate[restore]='' return 1 else typeset -A values - values=( "${(@kv)_values}" ) + compvalues -v values if [[ "$action" = \ # ]]; then @@ -341,7 +84,7 @@ else if [[ -n "$compconfig[describe_values]" && "$compconfig[describe_values]" != *\!${cmd}* ]] && - _display tmp "$ws[@]"; then + compdisplay tmp ' -- ' "$ws[@]"; then compadd "$expl[@]" -M 'r:|[_-]=* r:|=*' -ld tmp - "${(@)ws%%:*}" else compadd "$expl[@]" - "${(@)ws%%:*}" @@ -370,6 +113,10 @@ else ${(e)action[1]} "$expl[@]" ${(e)~action[2,-1]} fi fi -fi -[[ nm -ne "$compstate[nmatches]" ]] + [[ nm -ne "$compstate[nmatches]" ]] + return + +else + return 1; +fi diff --git a/Completion/Core/compinit b/Completion/Core/compinit index 020727624..83f24b9a9 100644 --- a/Completion/Core/compinit +++ b/Completion/Core/compinit @@ -78,6 +78,10 @@ while [[ $# -gt 0 && $1 = -[dDf] ]]; do fi done +# Load the helper module. + +zmodload computil + # The associative array containing the definitions for the commands. # Definitions for patterns will be stored in the normal arrays `_patcomps' # and `_postpatcomps'. |