diff options
Diffstat (limited to 'Completion/Base/_arguments')
-rw-r--r-- | Completion/Base/_arguments | 289 |
1 files changed, 150 insertions, 139 deletions
diff --git a/Completion/Base/_arguments b/Completion/Base/_arguments index 120c50934..86cd1c498 100644 --- a/Completion/Base/_arguments +++ b/Completion/Base/_arguments @@ -6,7 +6,7 @@ setopt localoptions extendedglob local long args rest ws cur nth def nm expl descr action opt arg tmp -local single uns ret=1 soptseq soptseq1 sopts prefix +local single uns ret=1 soptseq soptseq1 sopts prefix line # Associative arrays used to collect information about the options. @@ -117,182 +117,185 @@ else sopts='' fi -if [[ $#long -ne 0 && "$PREFIX" = --* ]]; then - - # If the current words starts with `--' and we should use long - # options, just call... +# Parse the command line... - _long_options "$long[@]" -else +ws=( "${(@)words[2,-1]}" ) +cur=$(( CURRENT-2 )) +nth=1 +liine=( "$words[1]" ) - # Otherwise parse the command line... +# ...until the current word is reached. - ws=( "${(@)words[2,-1]}" ) - cur=$(( CURRENT-2 )) - nth=1 +while [[ cur -gt 0 ]]; do - # ...until the current word is reached. + # `def' holds the description for the option we are currently after. + # Check if the next argument for the option is optional. - while [[ cur -gt 0 ]]; do + if [[ "$def" = :* ]]; then + opt=yes + else + opt='' + fi + arg='' - # `def' holds the description for the option we are currently after. - # Check if the next argument for the option is optional. + # Remove one description/action pair from `def' if that isn't empty. - if [[ "$def" = :* ]]; then - opt=yes + if [[ -n "$def" ]]; then + if [[ "$def" = ?*:*:* ]]; then + def="${def#?*:*:}" else - opt='' + def='' fi - arg='' + else - # Remove one description/action pair from `def' if that isn't empty. + # 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. - if [[ -n "$def" ]]; then - if [[ "$def" = ?*:*:* ]]; then - def="${def#?*:*:}" - else - def='' - fi + if [[ $#long -eq 0 || "$ws[1]" != --* ]]; then + opt=yes + arg=yes else + def='' + fi + fi - # 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. + if [[ -n "$opt" ]]; then - if [[ $#long -eq 0 || "$ws[1]" != --* ]]; then - opt=yes - arg=yes - else - def='' - fi - fi + # `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 [[ -n "$opt" ]]; then + if (( $+opts[$ws[1]] )); 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. + # Options that may only be given once are removed from the + # associative array so that we don't offer them again. - if (( $+opts[$ws[1]] )); then + def="$opts[$ws[1]]" + [[ -n "$oneshot[$ws[1]]" ]] && unset "opts[$ws[1]]" + else + uns='' + if [[ -n "$sopts" && "$ws[1]" = [-+]${~soptseq}[$sopts] ]]; then + tmp="${ws[1][1]}${ws[1][-1]}" + if (( $+opts[$tmp] )); then + def="$opts[$tmp]" + uns="${ws[1][2,-1]}" + opt='' + fi + fi - # Options that may only be given once are removed from the - # associative array so that we don't offer them again. + # 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. - def="$opts[$ws[1]]" - [[ -n "$oneshot[$ws[1]]" ]] && unset "opts[$ws[1]]" - else - uns='' - if [[ -n "$sopts" && "$ws[1]" = [-+]${~soptseq}[$sopts] ]]; then - tmp="${ws[1][1]}${ws[1][-1]}" - if (( $+opts[$tmp] )); then - def="$opts[$tmp]" - uns="${ws[1][2,-1]}" - opt='' - fi - fi + if [[ -n "$opt" && $#dopts -ne 0 ]]; then - # 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. + # First we get the option names. - if [[ -n "$opt" && $#dopts -ne 0 ]]; then + tmp=( "${(@k)dopts}" ) - # First we get the option names. + # Then we loop over them and see if the current word begins + # with one of the option names. - tmp=( "${(@k)dopts}" ) + 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 - # Then we loop over them and see if the current word begins - # with one of the option names. + if (( $#tmp )); then - 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 + # 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]]" + [[ -n "$oneshot[$tmp[1]]" ]] && unset "dopts[$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 + 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 - shift 1 tmp - done + elif [[ "$ws[1]" = ${tmp[1]}* ]]; then + break + fi + shift 1 tmp + done - if (( $#tmp )); then + if (( $#tmp )); then + opt='' + def="$odopts[$tmp[1]]" + [[ -n "$oneshot[$tmp[1]]" ]] && unset "odopts[$tmp[1]]" - # 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. + # 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. - opt='' - def="$dopts[$tmp[1]]" - [[ -n "$oneshot[$tmp[1]]" ]] && unset "dopts[$tmp[1]]" + if [[ ( -z "$sopts" && "$ws[1]" != "$tmp[1]" ) || + ( -n "$sopts" && ( ( $tmp[1] = [-+]? && "$ws[1]" != "${tmp[1][1]}"${~soptseq}"${tmp[1][2]}" ) || + ( $tmp[1] != [-+]? && "$ws[1]" != "$tmp[1]" ) ) ) ]]; then if [[ "$def" = ?*:*:* ]]; then def="${def#?*:*:}" else 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]]" - [[ -n "$oneshot[$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 [[ ( -z "$sopts" && "$ws[1]" != "$tmp[1]" ) || - ( -n "$sopts" && ( ( $tmp[1] = [-+]? && "$ws[1]" != "${tmp[1][1]}"${~soptseq}"${tmp[1][2]}" ) || - ( $tmp[1] != [-+]? && "$ws[1]" != "$tmp[1]" ) ) ) ]]; then - if [[ "$def" = ?*:*:* ]]; then - def="${def#?*:*:}" - else - def='' - fi - fi - fi + fi + fi fi + fi - [[ -n "$sopts" && -n "$opt" && "$ws[1]" = [-+]${~soptseq} ]] && \ - uns="${ws[1][2,-1]}" + [[ -n "$sopts" && -n "$opt" && "$ws[1]" = [-+]${~soptseq} ]] && \ + uns="${ws[1][2,-1]}" - if [[ -n "$uns" ]]; then - uns="${(j::)${(@k)oneshot[(I)${ws[1][1]}[$uns]]#[-+]}}" - unset "opts[${(@)^opts[(I)${ws[1][1]}[$uns]]}]" \ - "dopts[${(@)^dopts[(I)${ws[1][1]}[$uns]]}]" \ - "odopts[${(@)^odopts[(I)${ws[1][1]}[$uns]]}]" - fi + if [[ -n "$uns" ]]; then + uns="${(j::)${(@k)oneshot[(I)${ws[1][1]}[$uns]]#[-+]}}" + unset "opts[${(@)^opts[(I)${ws[1][1]}[$uns]]}]" \ + "dopts[${(@)^dopts[(I)${ws[1][1]}[$uns]]}]" \ + "odopts[${(@)^odopts[(I)${ws[1][1]}[$uns]]}]" + 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 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 + if [[ -n "$opt" && -n "$arg" ]]; then + def='' + line=( "$line[@]" "$ws[1]" ) + (( nth++ )) fi fi + fi - shift 1 ws - (( cur-- )) - done + shift 1 ws + (( cur-- )) +done + +# Now generate the matches. + +if [[ $#long -ne 0 && "$PREFIX" = --* ]]; then - # Now generate the matches. + # If the current words starts with `--' and we should use long + # options, just call... + + _long_options "$long[@]" + +else nm="$compstate[nmatches]" @@ -379,9 +382,11 @@ else _description expl option if [[ -n "$sopts" && -n "$PREFIX" && "$PREFIX" = [-+]${~soptseq}[$sopts] ]]; then if [[ "$PREFIX" = [-+]${~soptseq1} ]]; then - compadd "$expl[@]" -Q - "${PREFIX}${(@k)^opts[(I)${PREFIX[1]}?]#?}" \ - "${PREFIX}${(@k)^dopts[(I)${PREFIX[1]}?]#?}" \ - "${PREFIX}${(@k)^odopts[(I)${PREFIX[1]}?]#?}" && ret=0 + compadd "$expl[@]" -Q \ + -y "( ${(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 next word. compadd "$expl[@]" -Q - "${PREFIX}" && ret=0 @@ -418,11 +423,17 @@ else # An empty action means that we should just display a message. _message "$descr" return ret - elif [[ "$action[1]" = \( ]]; then + elif [[ "$action[1]" = \(*\) ]]; then # Anything inside `(...)' is added directly. compadd "$expl[@]" - ${=action[2,-2]} + elif [[ "$action" = \{*\} ]]; then + + # A string in braces is evaluated. + + eval "$action[2,-2]" + elif [[ "$action" = \ * ]]; then # If the action starts with a space, we just call it. |