From e025336f2f6d9f107ee1e03b9900f04af0544ba9 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sat, 1 Apr 2000 20:43:43 +0000 Subject: Updated from list as far as 10376 --- Completion/Base/_arguments | 571 +++++++++++++++++++++------------------------ 1 file changed, 265 insertions(+), 306 deletions(-) (limited to 'Completion/Base/_arguments') 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 -- cgit 1.4.1