diff options
-rw-r--r-- | Completion/Base/_describe | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/Completion/Base/_describe b/Completion/Base/_describe new file mode 100644 index 000000000..e01c77509 --- /dev/null +++ b/Completion/Base/_describe @@ -0,0 +1,155 @@ +#autoload + +# This can be used to add options or values with descriptions as matches. + +setopt localoptions extendedglob + +local gdescr isopt cmd opt nsets tmp descr match descrs matches adescr i +local disps disp expl tmps tmpd tmpmd tmpms name ret=1 showd _nm + +cmd="$words[1]" + +# Get the options. + +while getopts 'oc:' opt; do + if [[ "$opt" = o ]]; then + isopt=yes + else + cmd="$OPTARG" + fi +done +shift OPTIND-1 + +# Do the tests. `showd' is set if the descriptions should be shown. + +if [[ -n "$isopt" ]]; then + + # We take the value to test the number of patches from a non-local + # parameter `nm' if that exists and contains only digits. It's a hack. + + if [[ "$nm" = [0-9]## ]]; then + _nm="$nm" + else + _nm=0 + fi + [[ -n "$compconfig[option_prefix]" && + "$compconfig[option_prefix]" != *\!${cmd}* && + "$PREFIX" != [-+]* && + ( "$compconfig[option_prefix]" = *nodefault* || + _nm -ne compstate[nmatches] ) ]] && return 1 + + [[ -n "$compconfig[describe_options]" && + "$compconfig[describe_options]" != *\!${cmd}* ]] && showd=yes +else + [[ -n "$compconfig[describe_values]" && + "$compconfig[describe_values]" != *\!${cmd}* ]] && showd=yes +fi + +gdescr="$1" +shift + +# Now interpret the arguments. + +nsets=0 +adescr=() +descrs=() +matches=() +while (( $# )); do + (( nsets++ )) + descr="$1" + [[ -n "$showd" ]] && adescr=( "$adescr[@]" "${(@PM)^descr:#*:?*},$nsets" ) + if [[ "$2" = -* ]]; then + match='' + shift + else + match="$2" + shift 2 + fi + tmp=$argv[(i)--] + if [[ tmp -eq 1 ]]; then + opt=() + else + opt=( "${(@)argv[1,tmp-1]}" ) + fi + if [[ tmp -gt $# ]]; then + argv=() + else + shift tmp + fi + + # `descr' and `matches' collect the names of the arrays containing the + # possible matches with descriptions and the matches to add. + # The options to give to `compadd' are stored in local arrays. + + descrs[nsets]="$descr" + matches[nsets]="$match" + typeset -a _descr_opts_$nsets + eval "_descr_opts_${nsets}=( \"\$opt[@]\" )" +done + +(( nsets )) || return 1 + +# Build the display strings if needed. + +[[ -n "$showd" ]] && _display disps "$adescr[@]" +_description expl "$gdescr" + +# Loop through the array/option sets we have. + +i=0 +while [[ ++i -le nsets ]]; do + name=_descr_opts_$i + [[ -n "$showd" ]] && disp=( "${(@)${(@M)disps:#*,${i}}%,*}" ) + descr=( "${(@P)descrs[i]}" ) + + # We collect the strings to display in `tmpd' (one string per line) + # and `tmps' (in columns) and the matches to add in `tmpmd' and `tmpms'. + + tmpd=() + tmps=() + tmpmd=() + tmpms=() + if [[ -n "$matches[i]" ]]; then + match=( "${(@P)matches[i]}" ) + while (( $#match )); do + if [[ -n "$showd" && "$descr[1]" = *:?* ]]; then + tmpd=( "$tmpd[@]" "$disp[1]" ) + tmpmd=( "$tmpmd[@]" "$match[1]" ) + shift 1 disp + else + tmps=( "$tmps[@]" "${descr[1]%%:*}" ) + tmpms=( "$tmpms[@]" "$match[1]" ) + fi + shift 1 match + shift 1 descr + done + else + while (( $#descr )); do + if [[ -n "$showd" && "$descr[1]" = *:?* ]]; then + tmpd=( "$tmpd[@]" "$disp[1]" ) + tmpmd=( "$tmpmd[@]" "${descr[1]%%:*}" ) + shift 1 disp + else + tmps=( "$tmps[@]" "${descr[1]%%:*}" ) + tmpms=( "$tmpms[@]" "${descr[1]%%:*}" ) + fi + shift 1 descr + done + fi + + # See if we should remove the option prefix characters. + + if [[ -n "$isopt" && "$compconfig[option_prefix]" = hide* ]]; then + if [[ "$PREFIX" = --* ]]; then + tmpd=( "${(@)tmpd#--}" ) + tmps=( "${(@)tmps#--}" ) + elif [[ "$PREFIX" = [-+]* ]]; then + tmpd=( "${(@)tmpd#[-+]}" ) + tmps=( "${(@)tmps#[-+]}" ) + fi + fi + compadd "${(@P)name}" "$expl[@]" -ld tmpd - "$tmpmd[@]" && ret=0 + compadd "${(@P)name}" "$expl[@]" -d tmps - "$tmpms[@]" && ret=0 +done + +return ret |