diff options
Diffstat (limited to 'Completion/Base')
-rw-r--r-- | Completion/Base/_arguments | 285 |
1 files changed, 196 insertions, 89 deletions
diff --git a/Completion/Base/_arguments b/Completion/Base/_arguments index 5925cbc42..c8dceed26 100644 --- a/Completion/Base/_arguments +++ b/Completion/Base/_arguments @@ -5,22 +5,22 @@ setopt localoptions extendedglob -local args rest ws cur nth def nm expl descr action opt arg tmp -local single uns ret=1 soptseq soptseq1 sopts prefix line -local beg optbeg argbeg nargbeg inopt inrest fromrest +local args rest ws cur nth def nm expl descr action opt arg tmp xor +local single uns ret=1 soptseq soptseq1 sopts prefix _line odescr +local beg optbeg argbeg nargbeg inopt inrest fromrest cmd="$words[1]" +local matched curopt # Associative arrays used to collect information about the options. -typeset -A opts dopts odopts -typeset -A oneshot +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,oneshot} - typeset -gA _args_cache_{opts,dopts,odopts,oneshot} + unset _args_cache_{opts,dopts,odopts,odescr,xors} + typeset -gA _args_cache_{opts,dopts,odopts,xors} unset _args_cache_{long,longcmd,single,rest,args,sopts,soptseq,soptseq1} @@ -182,10 +182,29 @@ if [[ "$*" != "$_args_cache_descr" ]]; then # 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\]}" + fi + # Description for both the `-foo' and `+foo' form? if [[ "$1" = (\*|)(-+|+-)* ]]; then @@ -196,12 +215,10 @@ if [[ "$*" != "$_args_cache_descr" ]]; then if [[ "$1" = \** ]]; then tmp="${1[4,-1]%%:*}" [[ "$tmp" = *[-+] ]] && tmp="$tmp[1,-2]" - unset "_args_cache_oneshot[-$tmp]" "_args_cache_oneshot[+$tmp]" else tmp="${1[3,-1]%%:*}" [[ "$tmp" = *[-+] ]] && tmp="$tmp[1,-2]" - _args_cache_oneshot[-$tmp]=yes - _args_cache_oneshot[+$tmp]=yes + xor="$xor -$tmp +$tmp" fi # If the option name ends in a `-', the first argument comes @@ -222,6 +239,12 @@ if [[ "$*" != "$_args_cache_descr" ]]; then _args_cache_opts[-$tmp]='' _args_cache_opts[+$tmp]='' fi + + _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 @@ -230,11 +253,10 @@ if [[ "$*" != "$_args_cache_descr" ]]; then if [[ "$1" = \** ]]; then tmp="${1[2,-1]%%:*}" [[ "$tmp" = *[-+] ]] && tmp="$tmp[1,-2]" - unset "_args_cache_oneshot[$tmp]" else tmp="${1%%:*}" [[ "$tmp" = *[-+] ]] && tmp="$tmp[1,-2]" - _args_cache_oneshot[$tmp]=yes + xor="$xor ${tmp%\=}" fi # If the option name ends in a `-', the first argument comes @@ -251,6 +273,9 @@ if [[ "$*" != "$_args_cache_descr" ]]; then else _args_cache_opts[$tmp]='' 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 @@ -306,7 +331,8 @@ rest="$_args_cache_rest" opts=( "${(@kv)_args_cache_opts}" ) dopts=( "${(@kv)_args_cache_dopts}" ) odopts=( "${(@kv)_args_cache_odopts}" ) -oneshot=( "${(@kv)_args_cache_oneshot}" ) +odescr=( "$_args_cache_odescr[@]" ) +xors=( "${(@kv)_args_cache_xors}" ) single="$_args_cache_single" # Parse the command line... @@ -314,7 +340,7 @@ single="$_args_cache_single" ws=( "${(@)words[2,-1]}" ) cur=$(( CURRENT-2 )) nth=1 -line=( "$words[1]" ) +_line=( "$words[1]" ) beg=2 argbeg=1 optbeg=1 @@ -324,6 +350,14 @@ nargbeg=1 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 + # `def' holds the description for the option we are currently after. # Check if the next argument for the option is optional. @@ -339,6 +373,7 @@ while [[ cur -gt 0 ]]; do if [[ "$def" = \**[^\\]:* && "$ws[1]" = ${~${(M)def#*[^\\]:}[2,-2]} ]]; then def='' + curopt='' shift 1 ws (( cur-- )) (( beg++ )) @@ -353,6 +388,7 @@ while [[ cur -gt 0 ]]; do argbeg="$beg" else def='' + curopt='' fi elif [[ -z "$def" ]]; then @@ -360,6 +396,7 @@ while [[ cur -gt 0 ]]; do opt=yes arg=yes + curopt='' fi if [[ -n "$opt" ]]; then @@ -374,16 +411,23 @@ while [[ cur -gt 0 ]]; do # 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 - [[ -n "$oneshot[$ws[1]]" ]] && unset "opts[$ws[1]]" + if [[ -n "$xors[$ws[1]]" ]]; then + 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" + _options[$curopt]='' optbeg="$beg" argbeg="$beg" inopt=yes @@ -425,10 +469,15 @@ while [[ cur -gt 0 ]]; do opt='' def="$dopts[$tmp[1]]" + curopt="$tmp[1]" + _options[$curopt]="${ws[1]#${tmp[1]}}" optbeg="$beg" argbeg="$beg" inopt=yes - [[ -n "$oneshot[$tmp[1]]" ]] && unset "dopts[$tmp[1]]" + if [[ -n "$xors[$tmp[1]]" ]]; then + odescr=( "${(@)odescr:#(${(j:|:)~${=xors[$tmp[1]]}}):*}" ) + unset {{,d,od}opts,xors}\[${^=xors[$tmp[1]]}\] + fi if [[ "$def" = [^*]*[^\\]:*[^\\]:* ]]; then def="${def#?*[^\\]:*[^\\]:}" else @@ -453,11 +502,28 @@ while [[ cur -gt 0 ]]; do if (( $#tmp )); then opt='' def="$odopts[$tmp[1]]" - [[ -z "$def" ]] && 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 - [[ -n "$oneshot[$tmp[1]]" ]] && unset "odopts[$tmp[1]]" + if [[ -n "$xors[$tmp[1]]" ]]; then + 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 @@ -481,7 +547,7 @@ while [[ cur -gt 0 ]]; do uns="${ws[1][2,-1]}" if [[ -n "$uns" ]]; then - uns="${(j::)${(@k)oneshot[(I)${ws[1][1]}[$uns]]#[-+]}}" + uns="${(@j::)${(v)=xors[(I)${ws[1][1]}[$uns]]}#[-+]}" tmp=( "opts[${(@)^opts[(I)${ws[1][1]}[$uns]]}]" "dopts[${(@)^dopts[(I)${ws[1][1]}[$uns]]}]" @@ -496,7 +562,7 @@ while [[ cur -gt 0 ]]; do if [[ -n "$opt" && -n "$arg" ]]; then def='' - line=( "$line[@]" "$ws[1]" ) + _line=( "$_line[@]" "$ws[1]" ) [[ -n "$inopt" ]] && nargbeg=$(( beg - 1 )) inopt='' if [[ -z "$args[nth]" && "$rest" = \*::* ]]; then @@ -593,7 +659,7 @@ if [[ -z "$def" || "$def" = :* ]]; then uns="${PREFIX[2,-1]}" if [[ -n "$uns" ]]; then - uns="${(j::)${(@k)oneshot[(I)${ws[1][1]}[$uns]]#[-+]}}" + uns="${(@j::)${(v)=xors[(I)${ws[1][1]}[$uns]]}#[-+]}" tmp=( "opts[${(@)^opts[(I)${pre[1]}[$uns]]}]" "dopts[${(@)^dopts[(I)${pre[1]}[$uns]]}]" @@ -657,67 +723,134 @@ while true; do _description expl "$descr" - if [[ "$action" = \ # ]]; then + if [[ "$action" = -\>* ]]; then + line=( "$_line[@]" ) + options=( "${(@kv)_options}" ) + state="${${action[3,-1]##[ ]#}%%[ ]#}" + compstate[restore]='' + return 1 + else + if [[ "${(t)line}" != *local* ]]; then + local line + typeset -A options + fi - # An empty action means that we should just display a message. + line=( "$_line[@]" ) + options=( "${(@kv)_options}" ) - _message "$descr" - break + if [[ "$action" = \ # ]]; then - elif [[ "$action" = \(\(*\)\) ]]; then + # An empty action means that we should just display a message. - # ((...)) contains literal strings with descriptions. + [[ -n "$matched" ]] && compadd -n -Q -S '' -s "$SUFFIX" - "$PREFIX" + _message "$descr" + break - eval ws\=\( "${action[3,-3]}" \) + elif [[ "$action" = \(\(*\)\) ]]; then - compadd -D ws - "${(@)ws%%:*}" + # ((...)) contains literal strings with descriptions. - if (( $#ws )); then - beg=1 - for nth in "$ws[@]"; do - tmp="${#nth%%:*}" - [[ tmp -gt beg ]] && beg="$tmp" - done - tmp='' - for nth in "$ws[@]"; do - tmp="$tmp -${(r:beg:: :)nth%%:*} -- ${nth#*:}" - done - tmp="$tmp[2,-1]" - compadd "$expl[@]" -y tmp - "${(@)ws%%:*}" - else - _message "$descr" - fi - elif [[ "$action" = \(*\) ]]; then + eval ws\=\( "${action[3,-3]}" \) - # Anything inside `(...)' is added directly. + if _display tmp ws -M 'r:|[_-]=* r:|=*'; then + compadd "$expl[@]" -y tmp - "${(@)ws%%:*}" + else + [[ -n "$matched" ]] && compadd -Q -S -s "$SUFFIX" - "$PREFIX" + _message "$descr" + fi + elif [[ "$action" = \(*\) ]]; then - compadd "$expl[@]" - ${=action[2,-2]} - elif [[ "$action" = \{*\} ]]; then + # Anything inside `(...)' is added directly. - # A string in braces is evaluated. + compadd "$expl[@]" - ${=action[2,-2]} + elif [[ "$action" = \{*\} ]]; then - eval "$action[2,-2]" + # A string in braces is evaluated. - elif [[ "$action" = \ * ]]; then + eval "$action[2,-2]" - # If the action starts with a space, we just call it. + elif [[ "$action" = \ * ]]; then - ${(e)=~action} - else + # If the action starts with a space, we just call it. + + ${(e)=~action} + else + + # Otherwise we call it with the description-arguments built above. + + action=( $=action ) + ${(e)action[1]} "$expl[@]" ${(e)~action[2,-1]} + fi + fi + fi - # Otherwise we call it with the description-arguments built above. + # Probably add the option names. + + if [[ -n "$opt" && + ( nm -eq compstate[nmatches] || + -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 + if [[ -n "$compconfig[describe_options]" && + "$compconfig[describe_options]" != *\!${cmd}* ]]; then + _display tmp odescr + else + tmp="( ${(j: :)${(@)${(@M)${=:-${(k)opts} ${(k)dopts} ${(k)odopts}}:#[-+]?(|=)}#?}%=} )" + fi + compadd "$expl[@]" -Q -M 'r:|[_-]=* r:|=*' -y tmp - \ + "${PREFIX}${(@k)^opts[(I)${PREFIX[1]}?]#?}" \ + "${PREFIX}${(@k)^dopts[(I)${PREFIX[1]}?]#?}" \ + "${PREFIX}${(@)^${(@k)odopts[(I)${PREFIX[1]}?(|=)]#?}%=}" && + ret=0 + else + # The last option takes an argument in the next word. - action=( $=action ) - ${(e)action[1]} "$expl[@]" ${(e)~action[2,-1]} + compadd "$expl[@]" -Q -M 'r:|[_-]=* r:|=*' - "${PREFIX}" && ret=0 + fi + else + tmp='' + if [[ -n "$compconfig[describe_options]" && + "$compconfig[describe_options]" != *\!${cmd}* ]]; then + if _display tmp odescr; then + if (( $#dopts )); then + compadd -n "$expl[@]" -QS '' -M 'r:|[_-]=* r:|=*' -y tmp - \ + "${(@k)dopts}" && ret=0 + compadd -n -J option -Q -M 'r:|[_-]=* r:|=*' - \ + "${(@k)opts}" "${(@k)odopts[(I)*[^=]]}" && ret=0 + compadd -n -J option -QqS= -M 'r:|[_-]=* r:|=*' - \ + "${(@k)odopts[(I)*=]%=}" && ret=0 + elif (( ${(@k)#odopts[(I)*=]} )); then + compadd -n "$expl[@]" -QqS= -M 'r:|[_-]=* r:|=*' -y tmp - \ + "${(@k)odopts[(I)*=]%=}" && ret=0 + compadd -n -J option -Q -M 'r:|[_-]=* r:|=*' - \ + "${(@k)opts}" "${(@k)odopts[(I)*[^=]]}" && ret=0 + else + compadd -n "$expl[@]" -Q -M 'r:|[_-]=* r:|=*' -y tmp - \ + "${(@k)opts}" "${(@k)odopts[(I)*[^=]]}" && ret=0 + fi + fi + fi + if [[ -z "$tmp" ]]; then + compadd "$expl[@]" -Q -M 'r:|[_-]=* r:|=*' - \ + "${(@k)opts}" "${(@k)odopts[(I)*[^=]]}" && ret=0 + compadd "$expl[@]" -QqS= -M 'r:|[_-]=* r:|=*' - \ + "${(@k)odopts[(I)*=]%=}" && ret=0 + compadd "$expl[@]" -QS '' -M 'r:|[_-]=* r:|=*' - \ + "${(@k)dopts}" && ret=0 + fi fi fi - if [[ nm -eq compstate[nmatches] && $#_args_cache_long -ne 0 && - "$PREFIX" = --*=* ]]; then + if [[ nm -eq compstate[nmatches] && + ( -z "$single" || + ( $#_args_cache_long -ne 0 && "$PREFIX" = --*=* ) ) ]]; then local suffix - tmp=( "${(@Mk)odopts:#--[^:]#\=}" ) + tmp=( "${(@Mk)odopts:#[^:]#\=}" ) prefix="${PREFIX#*\=}" suffix="$SUFFIX" PREFIX="${PREFIX%%\=*}" @@ -729,40 +862,14 @@ ${(r:beg:: :)nth%%:*} -- ${nth#*:}" PREFIX="$prefix" SUFFIX="$suffix" IPREFIX="$tmp[1]" + matched=yes continue fi fi + break done -# Probably add the option names. - -if [[ -n "$opt" && - ( nm -eq compstate[nmatches] || - -z "$compconfig[option_prefix]" || "$PREFIX" = [-+]* ) ]]; then - _description expl option - if [[ -n "$sopts" && -n "$PREFIX" && - "$PREFIX" = [-+]${~soptseq}[$sopts] ]]; then - if [[ "$PREFIX" = [-+]${~soptseq1} ]]; then - compadd "$expl[@]" -Q -M 'r:|[_-]=* r:|=*' \ - -y "( ${(j: :)${(@)${(@M)${=:-${(k)opts} ${(k)dopts} ${(k)odopts}}:#[-+]?(|=)}#?}%=} )" - \ - "${PREFIX}${(@k)^opts[(I)${PREFIX[1]}?]#?}" \ - "${PREFIX}${(@k)^dopts[(I)${PREFIX[1]}?]#?}" \ - "${PREFIX}${(@)^${(@k)odopts[(I)${PREFIX[1]}?(|=)]#?}%=}" && ret=0 - else - # The last option takes an argument in the next word. - - compadd "$expl[@]" -Q -M 'r:|[_-]=* r:|=*' - "${PREFIX}" && ret=0 - fi - else - compadd "$expl[@]" -Q -M 'r:|[_-]=* r:|=*' - \ - "${(@k)opts}" "${(@k)odopts[(I)*[^=]]}" && ret=0 - compadd "$expl[@]" -Q -M 'r:|[_-]=* r:|=*' -qS= - \ - "${(@k)odopts[(I)*=]%=}" && ret=0 - compadd "$expl[@]" -QS '' -M 'r:|[_-]=* r:|=*' - "${(@k)dopts}" && ret=0 - fi -fi - # Set the return value. [[ nm -ne "$compstate[nmatches]" ]] |