diff options
Diffstat (limited to 'Completion/Base')
-rw-r--r-- | Completion/Base/_values | 367 |
1 files changed, 367 insertions, 0 deletions
diff --git a/Completion/Base/_values b/Completion/Base/_values new file mode 100644 index 000000000..4be3e8203 --- /dev/null +++ b/Completion/Base/_values @@ -0,0 +1,367 @@ +#autoload + +setopt localoptions extendedglob + +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 + +# Probably fill our cache. + +if [[ "$*" != "$_vals_cache_args" ]]; then + _vals_cache_args="$*" + + unset _vals_cache_{sep,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" + 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" + +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. + + str="${SUFFIX%%${sep}*}" + SUFFIX="${SUFFIX#*${sep}}" + while [[ -n "$SUFFIX" ]]; do + tmp="${PREFIX%%${sep}*}" + if [[ "$SUFFIX" = *${sep}* ]]; then + SUFFIX="${SUFFIX#*${sep}}" + else + SUFFIX='' + fi + PREFIX="${PREFIX#*${sep}}" + IPREFIX="${IPREFIX}${tmp}${sep}" + + name="${tmp%%\=*}" + + if [[ "$tmp" = *\=* ]]; then + _values[$name]="${tmp#*\=}" + else + _values[$name]='' + 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 + + # 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. + + 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 + 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 + 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" + + # We add the separator character as a autoremovable suffix unless + # we have only one possible value left. + + [[ -n "$sep" && ${#snames}+${#names}+${#onames} -ne 1 ]] && + expl=( "-qS$sep" "$expl[@]" ) + + if [[ "$action" = -\>* ]]; then + values=( "${(@kv)_values}" ) + state="${${action[3,-1]##[ ]#}%%[ ]#}" + compstate[restore]='' + return 1 + else + typeset -A values + + values=( "${(@kv)_values}" ) + + if [[ "$action" = \ # ]]; then + + # An empty action means that we should just display a message. + + _message "$descr" + return 1 + + elif [[ "$action" = \(\(*\)\) ]]; then + local ws + + # ((...)) contains literal strings with descriptions. + + eval ws\=\( "${action[3,-3]}" \) + + if _display tmp ws; then + compadd "$expl[@]" -y tmp - "${(@)ws%%:*}" + else + _message "$descr" + return 1 + fi + elif [[ "$action" = \(*\) ]]; 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. + + ${(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 + +[[ nm -ne "$compstate[nmatches]" ]] |