summaryrefslogtreecommitdiff
path: root/Completion/Base/_values
diff options
context:
space:
mode:
Diffstat (limited to 'Completion/Base/_values')
-rw-r--r--Completion/Base/_values367
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]" ]]