From bc9e764f4e9b95ec4c2a855c4118f6afb994e904 Mon Sep 17 00:00:00 2001 From: Tanaka Akira Date: Wed, 15 Sep 1999 14:35:16 +0000 Subject: zsh-workers/7844 --- Completion/Base/_arguments | 73 ++++++-------------- Completion/Base/_describe | 155 +++++++++++++++++++++++++++++++++++++++++++ Completion/Base/_subscript | 4 +- Completion/Base/_tilde | 4 +- Completion/Base/_values | 41 ++++-------- Completion/Builtins/_cd | 2 +- Completion/Builtins/_kill | 4 +- Completion/Builtins/_wait | 2 +- Completion/Core/_approximate | 15 ++++- Completion/Core/_expand | 45 ++++++++++--- Completion/User/_gdb | 2 +- Doc/Zsh/compsys.yo | 46 +++++++++++-- Etc/completion-style-guide | 4 +- Src/Zle/complist.c | 8 +-- Src/Zle/zle_tricky.c | 35 ++++++++-- 15 files changed, 327 insertions(+), 113 deletions(-) create mode 100644 Completion/Base/_describe diff --git a/Completion/Base/_arguments b/Completion/Base/_arguments index a8e272cac..df01ba6a4 100644 --- a/Completion/Base/_arguments +++ b/Completion/Base/_arguments @@ -8,7 +8,7 @@ setopt localoptions extendedglob local args rest ws cur nth def nm expl descr action opt arg tmp xor local single uns ret=1 aret soptseq soptseq1 sopts prefix _line odescr local beg optbeg argbeg nargbeg inopt inrest fromrest cmd="$words[1]" -local matched curopt noargs i +local matched curopt noargs i tmp1 tmp2 tmp3 suffix # Associative arrays used to collect information about the options. @@ -793,13 +793,8 @@ while true; do eval ws\=\( "${action[3,-3]}" \) - if [[ -n "$compconfig[describe_values]" && - "$compconfig[describe_values]" != *\!${cmd}* ]] && - _display tmp "$ws[@]"; then - compadd "$expl[@]" -M 'r:|[_-]=* r:|=*' -ld tmp - "${(@)ws%%:*}" - else - compadd "$expl[@]" - "${(@)ws%%:*}" - fi + _describe -c "$cmd" "$descr" ws -M 'r:|[_-]=* r:|=*' + elif [[ "$action" = \(*\) ]]; then # Anything inside `(...)' is added directly. @@ -837,62 +832,36 @@ while true; do if [[ -n "$sopts" && -n "$PREFIX" && "$PREFIX" = [-+]${~soptseq}[$sopts] ]]; then if [[ "$PREFIX" = [-+]${~soptseq1} ]]; then - if [[ -z "$compconfig[describe_options]" || - "$compconfig[describe_options]" = *\!${cmd}* ]]; then - tmp=( "${PREFIX[1]}${(@)^${(@)${(@M)${=:-${(k)opts} ${(k)dopts} ${(k)odopts}}:#[-+]?(|=)}#?}%=}" ) - compadd "$expl[@]" -Q -M 'r:|[_-]=* r:|=*' -d tmp - \ - "${PREFIX}${(@k)^opts[(I)${PREFIX[1]}?]#?}" \ - "${PREFIX}${(@k)^dopts[(I)${PREFIX[1]}?]#?}" \ - "${PREFIX}${(@)^${(@k)odopts[(I)${PREFIX[1]}?(|=)]#?}%=}" && - ret=0 - elif _display tmp "${(@Mo)odescr:#[-+]?:*}"; then - compadd "$expl[@]" -Q -M 'r:|[_-]=* r:|=*' -ld tmp - \ - "${PREFIX}${(@)^${(@)${(@Mo)odescr:#[-+]?:*}%%:*}#?}" && ret=0 - else - compadd "$expl[@]" -Q -M 'r:|[_-]=* r:|=*' -d tmp - \ - "${PREFIX}${(@)^${(@)${(@Mo)odescr:#[-+]?:*}%%:*}#?}" && ret=0 - fi + tmp1=( "${(@Mo)odescr:#[-+]?:*}" ) + tmp2=( + "${PREFIX}${(@k)^opts[(I)${PREFIX[1]}?]#?}" \ + "${PREFIX}${(@k)^dopts[(I)${PREFIX[1]}?]#?}" \ + "${PREFIX}${(@)^${(@k)odopts[(I)${PREFIX[1]}?(|=)]#?}%=}" + ) + tmp2=( "${(@o)tmp2}" ) + + _describe -o -c "$cmd" option \ + tmp1 tmp2 -Q -M 'r:|[_-]=* r:|=*' else # The last option takes an argument in the next word. compadd "$expl[@]" -Q -M 'r:|[_-]=* r:|=*' - "${PREFIX}" && ret=0 fi else - if [[ -n "$compconfig[describe_options]" && - "$compconfig[describe_options]" != *\!${cmd}* ]] && - _display descr "$odescr[@]"; then - ws=( "${(k)opts[@]}" "${(@k)odopts[(I)*[^=]]}" ) - if (( $#ws )); then - tmp=( "${(@M)descr:#(${(j:|:)~ws}) *}" ) - compadd "$expl[@]" -Q -M 'r:|[_-]=* r:|=*' -ld tmp - \ - "$ws[@]" && ret=0 - fi - if (( $#dopts )); then - tmp=( "${(@M)descr:#(${(kj:|:)~dopts}) *}" ) - compadd "$expl[@]" -QS '' -M 'r:|[_-]=* r:|=*' -ld tmp - \ - "${(@k)dopts}" && ret=0 - fi - if (( ${(@k)#odopts[(I)*=]} )); then - tmp=( "${(@M)descr:#(${(kj:|:)~odopts[(I)*=]}) *}" ) - compadd "$expl[@]" -QqS= -M 'r:|[_-]=* r:|=*' -ld tmp - \ - "${(@k)odopts[(I)*=]%=}" && ret=0 - fi - else - compadd "$expl[@]" -Q -M 'r:|[_-]=* r:|=*' - \ - "${(@k)opts}" "${(@k)odopts[(I)*[^=]]}" && ret=0 - compadd "$expl[@]" -QqS= -M 'r:|[_-]=* r:|=*' - \ - "${(@k)odopts[(I)*=]%=}" && ret=0 - compadd "$expl[@]" -QS '' -M 'r:|[_-]=* r:|=*' - \ - "${(@k)dopts}" && ret=0 - fi + tmp1=( "${(k)opts[@]}" "${(@k)odopts[(I)*[^=]]}" ) + tmp1=( "${(@M)odescr:#(${(kj:|:)~tmp1}):*}" ) + tmp2=( "${(@M)odescr:#(${(kj:|:)~dopts}):*}" ) + tmp3=( "${(@M)odescr:#(${(kj:|:)~odopts[(I)*=]}):*}" ) + _describe -o -c "$cmd" option \ + tmp1 -Q -M 'r:|[_-]=* r:|=*' -- \ + tmp2 -QS '' -M 'r:|[_-]=* r:|=*' -- \ + tmp3 -QqS= -M 'r:|[_-]=* r:|=*' fi fi if [[ nm -eq compstate[nmatches] && ( -z "$single" || ( $#_args_cache_long -ne 0 && "$PREFIX" = --*=* ) ) ]]; then - local suffix - tmp=( "${(@Mk)odopts:#[^:]#\=}" ) prefix="${PREFIX#*\=}" suffix="$SUFFIX" 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 diff --git a/Completion/Base/_subscript b/Completion/Base/_subscript index 76644bafb..803893912 100644 --- a/Completion/Base/_subscript +++ b/Completion/Base/_subscript @@ -26,9 +26,9 @@ elif [[ ${(Pt)${compstate[parameter]}} = array* ]]; then done if [[ "$RBUFFER" = \]* ]]; then - compadd "$expl[@]" -S '' -V default -y list - "$ind[@]" + compadd "$expl[@]" -S '' -V default -d list - "$ind[@]" else - compadd "$expl[@]" -S ']' -V default -y list - "$ind[@]" + compadd "$expl[@]" -S ']' -V default -d list - "$ind[@]" fi else _compalso -math- diff --git a/Completion/Base/_tilde b/Completion/Base/_tilde index b8d639074..95d342538 100644 --- a/Completion/Base/_tilde +++ b/Completion/Base/_tilde @@ -9,7 +9,7 @@ setopt localoptions extendedglob -local d s dirs list +local d s dirs list lines if [[ "$SUFFIX" = */* ]]; then ISUFFIX="/${SUFFIX#*/}$ISUFFIX" @@ -36,7 +36,7 @@ if [[ -prefix [-+] ]]; then compset -P '[-+]' _description d 'directory stack' - compadd "$d[@]" -d lines -Q - "$list[@]" + compadd "$d[@]" -ld lines -Q - "$list[@]" else if (( $# )); then d=( "$@" ) diff --git a/Completion/Base/_values b/Completion/Base/_values index 21f6908cc..5b413313b 100644 --- a/Completion/Base/_values +++ b/Completion/Base/_values @@ -3,7 +3,7 @@ setopt localoptions extendedglob local name arg def descr xor str tmp ret=1 expl nm="$compstate[nmatches]" -local snames odescr gdescr sep esep spat +local snames odescr gdescr sep esep spat tmp1 tmp2 tmp3 opts typeset -A names onames xors _values # Probably fill our cache. @@ -280,34 +280,21 @@ else # No `=', just complete value names. - _description expl "$gdescr" - - [[ -n "$sep" && ${#snames}+${#names}+${#onames} -ne 1 ]] && - expl=( "-qS$sep" "$expl[@]" ) - - if [[ -n "$compconfig[describe_values]" && - "$compconfig[describe_values]" != *\!${words[1]}* ]] && - _display descr "$odescr[@]"; then - if (( $#snames )); then - tmp=( "${(@M)descr:#(${(j:|:)~snames}) *}" ) - compadd "$expl[@]" -ld tmp -M 'r:|[_-]=* r:|=*' - \ - "${(@)tmp%% *}" && ret=0 - fi - if (( $#names )); then - tmp=( "${(@M)descr:#(${(kj:|:)~names}) *}" ) - compadd -S= "$expl[@]" -ld tmp -M 'r:|[_-]=* r:|=*' - \ - "${(@)tmp%% *}" && ret=0 - fi - if (( $#onames )); then - tmp=( "${(@M)descr:#(${(kj:|:)~onames}) *}" ) - compadd -qS= "$expl[@]" -ld tmp -M 'r:|[_-]=* r:|=*' - \ - "${(@)tmp%% *}" && ret=0 - fi + if [[ -n "$sep" && ${#snames}+${#names}+${#onames} -ne 1 ]]; then + opts=( "-qS$sep" ) else - 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 + opts=() fi + + tmp1=( "${(@M)odescr:#(${(j:|:)~snames}):*}" ) + tmp2=( "${(@M)odescr:#(${(kj:|:)~names}):*}" ) + tmp3=( "${(@M)odescr:#(${(kj:|:)~onames}):*}" ) + + _describe "$gdescr" \ + tmp1 "$opts[@]" -M 'r:|[_-]=* r:|=*' -- \ + tmp2 -S= "$opts[@]" -M 'r:|[_-]=* r:|=*' -- \ + tmp3 -qS= "$opts[@]" -M 'r:|[_-]=* r:|=*' + return ret fi diff --git a/Completion/Builtins/_cd b/Completion/Builtins/_cd index e4502459c..35940d1fe 100644 --- a/Completion/Builtins/_cd +++ b/Completion/Builtins/_cd @@ -55,7 +55,7 @@ elif [[ $PREFIX = [-+]* ]]; then # get the array of numbers only list=(${lines%% *}) _description expl 'directory stack index' - compadd "$expl[@]" -d lines -Q - "$list[@]" && ret=0 + compadd "$expl[@]" -ld lines -Q - "$list[@]" && ret=0 [[ -z $compstate[list] ]] && compstate[list]=list && ret=0 [[ -n $compstate[insert] ]] && compstate[insert]=menu && ret=0 diff --git a/Completion/Builtins/_kill b/Completion/Builtins/_kill index 264253e0a..d909bef76 100644 --- a/Completion/Builtins/_kill +++ b/Completion/Builtins/_kill @@ -10,9 +10,9 @@ else _description expl job compgen "$expl[@]" -P '%' -j && ret=0 - list=("${(@Mr:COLUMNS-1:)${(f)$(ps ${compconfig[ps_listargs]:-$compconfig[ps_args]} 2>/dev/null)}[2,-1]:#[ ]#${PREFIX}[0-9]#${SUFFIX}[ ]*}") + list=("${(@Mr:COLUMNS-1:)${(f@)$(ps ${compconfig[ps_listargs]:-$compconfig[ps_args]} 2>/dev/null)}[2,-1]:#[ ]#${PREFIX}[0-9]#${SUFFIX}[ ]*}") _description expl 'process ID' - compadd "$expl[@]" -y list - ${${${(f)"$(ps $compconfig[ps_args] 2>/dev/null)"}[2,-1]## #}%% *} && + compadd "$expl[@]" -ld list - ${${${(f)"$(ps $compconfig[ps_args] 2>/dev/null)"}[2,-1]## #}%% *} && ret=0 return ret diff --git a/Completion/Builtins/_wait b/Completion/Builtins/_wait index bcd39963f..7b20aaa10 100644 --- a/Completion/Builtins/_wait +++ b/Completion/Builtins/_wait @@ -17,6 +17,6 @@ _description expl job compgen "$expl[@]" -P '%' -j && ret=0 list=("${(@Mr:COLUMNS-1:)${(f)$(ps ${compconfig[ps_listargs]:-$compconfig[ps_args]} 2>/dev/null)}[2,-1]:#[ ]#${PREFIX}[0-9]#${SUFFIX}[ ]*}") _description expl 'process ID' -compadd "$expl[@]" -y list - ${${${(f)"$(ps $compconfig[ps_args] 2>/dev/null)"}[2,-1]## #}%% *} && ret=0 +compadd "$expl[@]" -ld list - ${${${(f)"$(ps $compconfig[ps_args] 2>/dev/null)"}[2,-1]## #}%% *} && ret=0 return ret diff --git a/Completion/Core/_approximate b/Completion/Core/_approximate index 61f21c5b9..667f9919d 100644 --- a/Completion/Core/_approximate +++ b/Completion/Core/_approximate @@ -168,10 +168,21 @@ while [[ _comp_correct -le comax ]]; do "${#compstate[unambiguous]}" -ge "${#:-$PREFIX$SUFFIX}" ]]; then compstate[pattern_insert]=unambiguous elif [[ compstate[nmatches] -gt 1 || "$cfgorig" = *always* ]]; then + local expl + + if [[ "$cfgorig" = *show* ]]; then + if [[ -n "$compconfig[description_format]" ]]; then + expl=(-X "${compconfig[description_format]//\\%d/original}") + else + expl=() + fi + else + expl=(-n) + fi if [[ "$cfgorig" = *last* ]]; then - builtin compadd -U -V _correct_original -nQ - "$PREFIX$SUFFIX" + builtin compadd "$expl[@]" -U -V _correct_original -Q - "$PREFIX$SUFFIX" elif [[ -n "$cfgorig" ]]; then - builtin compadd -U -nQ - "$PREFIX$SUFFIX" + builtin compadd "$expl[@]" -U -Q - "$PREFIX$SUFFIX" fi # If you always want to see the list of possible corrections, diff --git a/Completion/Core/_expand b/Completion/Core/_expand index 778293a8b..0b8083845 100644 --- a/Completion/Core/_expand +++ b/Completion/Core/_expand @@ -30,7 +30,7 @@ # # expand_menu # If this is unset or set to the empty string, the words resulting -# from expansion (if any) will simply be inserted in the ommand line, +# from expansion (if any) will simply be inserted in the command line, # replacing the original string. However, if this key is set to an # non-empty string, the user can cycle through the expansion as in # a menucompletion. Unless the value contains the sub-string `only', @@ -56,7 +56,8 @@ # contain the control sequences `%n', `%B', etc. Also, the sequence # `%o' in this string will be replaced by the original string. -local exp word="$PREFIX$SUFFIX" group=-V +local exp word="$PREFIX$SUFFIX" group=-V expl expl2 disp + # Do this only for the first global matcher. [[ "$compstate[matcher]" -le 1 ]] || return 1 @@ -89,6 +90,34 @@ exp=("$word") [[ $#exp -eq 0 || ( $#exp -eq 1 && "$exp[1]" = "$word"(|\(N\)) ) ]] && return 1 +# Get the options for adding the original string and `all'-string. + +if [[ "$compconfig[expand_original]" = *show* ]]; then + if [[ -n "$compconfig[description_format]" ]]; then + expl=(-X "${compconfig[description_format]//\\%d/original}") + else + expl=() + fi +else + expl=(-n) +fi + +if [[ -n "$compconfig[expand_menu]" && + "$compconfig[expand_menu]" != *only* && + "$compconfig[expand_menu]" = *showall* ]]; then + if [[ -n "$compconfig[description_format]" ]]; then + expl2=(-ld disp -X "${compconfig[description_format]//\\%d/all words}") + else + expl2=(-ld disp ) + fi + disp=( "$exp" ) + if [[ ${#disp[1]} -gt COLUMNS-5 ]]; then + disp=( "${disp[1][1,COLUMNS-5]}..." ) + fi +else + expl2=(-n) +fi + # We have expansions, should we menucomplete them? if [[ -z "$compconfig[expand_menu]" ]]; then @@ -102,13 +131,13 @@ if [[ -z "$compconfig[expand_menu]" ]]; then else [[ -n "$compconfig[expand_original]" && "$compconfig[expand_original]" != *last* ]] && - compadd -UnQ -V _expand_original - "$word" + compadd "$expl[@]" -UQ -V _expand_original - "$word" compadd -UQ -V _expand - "$exp" [[ -n "$compconfig[expand_original]" && "$compconfig[expand_original]" = *last* ]] && - compadd -UnQ -V _expand_original - "$word" + compadd "$expl[@]" -UQ -V _expand_original - "$word" compstate[insert]=menu fi @@ -122,11 +151,11 @@ else [[ -n "$compconfig[expand_original]" && "$compconfig[expand_original]" != *last* ]] && - compadd -UnQ -V _expand_original - "$word" + compadd "$expl[@]" -UQ -V _expand_original - "$word" [[ "$compconfig[expand_menu]" = *last* && "$compconfig[expand_menu]" != *only* ]] && - compadd -UnQ -V _expand_all - "$exp" + compadd "$expl2[@]" -UQ -V _expand_all - "$exp" if [[ -z "$compconfig[expand_prompt]" ]]; then compadd -UQ $group _expand - "$exp[@]" @@ -136,11 +165,11 @@ else fi [[ "$compconfig[expand_menu]" != *last* && "$compconfig[expand_menu]" != *only* ]] && - compadd -UnQ -V _expand_all - "$exp" + compadd "$expl2[@]" -UQ -V _expand_all - "$exp" [[ -n "$compconfig[expand_original]" && "$compconfig[expand_original]" = *last* ]] && - compadd -UnQ -V _expand_original - "$word" + compadd "$expl[@]" -UQ -V _expand_original - "$word" compstate[insert]=menu fi diff --git a/Completion/User/_gdb b/Completion/User/_gdb index 1f64f0c1f..b16d18fb7 100644 --- a/Completion/User/_gdb +++ b/Completion/User/_gdb @@ -49,7 +49,7 @@ else _description expl 'process ID' list=("${(F)${(@Mr:COLUMNS-1:)${(f)$(ps ${compconfig[ps_listargs]:-$compconfig[ps_args]} 2>/dev/null)}[2,-1]:#[ ]#${PREFIX}[0-9]#${SUFFIX}[ ]*${w[1]:t}}} ") - compadd "$expl[@]" -y list - ${${${(M)${(f)"$(ps $compconfig[ps_args] 2>/dev/null)"}:#*${w[1]:t}*}## #}%% *} && ret=0 + compadd "$expl[@]" -ld list - ${${${(M)${(f)"$(ps $compconfig[ps_args] 2>/dev/null)"}:#*${w[1]:t}*}## #}%% *} && ret=0 return ret else diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo index 2f228d3ff..267617b15 100644 --- a/Doc/Zsh/compsys.yo +++ b/Doc/Zsh/compsys.yo @@ -595,6 +595,36 @@ array built is stored in it. The return value of tt(_display) is zero if there was at least one match with a description non-zero otherwise. ) +item(tt(_describe))( +This function can be used to add options or values with descriptions +as matches. The first argument is taken as a string to display above +the matches if the tt(description_format) configuration key is set. + +After this one or two names of arrays followed by options to give +to tt(compadd) must be given. The first array contains the possible +completions with their descriptions (with the description separated +by a colon from the completion string). If the second array is given, +it should have the same number of elements as the first one and these +elements are added as possible completions instead of the strings from +the first array. In any case, however, the completion list will show +the strings from the first array. + +Any number of array/option sequences may be given separated by +`tt(-)tt(-)'. This allows one to display matches together that need +to be added with different options for tt(compadd). + +Before the first argument, two options may be given. A `tt(-o)' says +that the matches added are option names. This will make tt(_describe) +use the tt(option_prefix) and tt(describe_options) configuration keys +to find out if the strings should be added at all and if the +descriptions should be shown. Without the `tt(-o)' option, the +tt(describe_values) key is used. + +The `tt(-c)' option, followed by a string, may be used to give the +name of the current command for testing the configuration keys. If the +first element of the tt(words) special array contains the correct +command name, this option need not be used. +) item(tt(_multi_parts))( This function gets two arguments: a separator character and an array. As usual, the array may be either the @@ -1147,7 +1177,9 @@ possible matches when no other completions could be found or if the string on the line begins with a option prefix character (a minus or a plus sign). This value may also contain strings of the form `tt(!)var(command)' which makes options be always completed for all -var(command)s given in this way. +var(command)s given in this way. Finally, if the value of this key +begins with `tt(hide)', the prefix characters `tt(-)', `tt(+)', or +`tt(-)tt(-)' will not be shown in the list. ) item(tt(last_prompt))( If this is set to tt(always), the cursor will always be moved back to @@ -1199,7 +1231,9 @@ corrected strings. If the value for this key contains the substring that it appears just before wrapping around to the first corrected string again. Also, if the value contains the substring `tt(always)', the original string will always be included; normally it is -included only if more than one possible correction was generated. +included only if more than one possible correction was generated. And +finally, if the value contains the substring `tt(show)', the original +string will be shown in the list of corrections. ) item(tt(approximate_prompt))( This can be set to a string to be displayed on top of the @@ -1246,9 +1280,11 @@ menucompletion. Unless the value contains the substring `tt(only)', the user will still be offered all expansions at once as one of the strings to insert in the command line; normally, this possibility is offered first, but if the value contains the -substring `tt(last)', it is offered last. Finally, if the value contains +substring `tt(last)', it is offered last. Also, if the value contains the substring `tt(sort)', the expansions will be sorted alphabetically, normally they are kept in the order the expansion produced them in. +And finally, if the value contains the substring `tt(showall)', the +string of all words will be shown in the list of expansions. ) item(tt(expand_original))( If this is set to an non-empty string, the original string from the @@ -1256,7 +1292,9 @@ line will be included in the list of strings the user can cycle through as in a menucompletion. If the value contains the substring `tt(last)', the original string will appear as the last string, with other values it is inserted as the first one (so that the command line -does not change immediately). +does not change immediately). Also, if the value contains the +substring `tt(show)', the original string will be shown in the list of +expansions. ) item(tt(expand_prompt))( This may be set to a string that should be displayed before the diff --git a/Etc/completion-style-guide b/Etc/completion-style-guide index 5bc289b9b..286cb2a71 100644 --- a/Etc/completion-style-guide +++ b/Etc/completion-style-guide @@ -74,8 +74,8 @@ For now this is just a list of things one should or shouldn't do. fi Finally, it is good style to display descriptions for options that - aren't self-explanatory. See the `_display' function and its use - in `_arguments'. + aren't self-explanatory. See the `_display' and `_describe' functions + and their uses in `_arguments'. All this should make it look like a really good idea to just use the supplied `_arguments' function to complete options. diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c index 913a5e592..af034efab 100644 --- a/Src/Zle/complist.c +++ b/Src/Zle/complist.c @@ -375,7 +375,7 @@ complistmatches(Hookdef dummy, Chdata dat) if (m->flags & CMF_DISPLINE) { nlines += 1 + printfmt(m->disp, 0, 0, 0); g->flags |= CGF_HASDL; - } else if ((l = strlen(m->disp)) > longest) + } else if ((l = niceztrlen(m->disp)) > longest) longest = l; nlist++; } else if (!(m->flags & CMF_NOLIST)) { @@ -395,7 +395,7 @@ complistmatches(Hookdef dummy, Chdata dat) } } longest += 2 + of; - if ((ncols = (columns + 1) / longest)) { + if ((ncols = columns / longest)) { for (g = amatches; g; g = g->next) nlines += (g->lcount - g->llcount + ncols - 1) / ncols; } else { @@ -417,7 +417,7 @@ complistmatches(Hookdef dummy, Chdata dat) if (m->flags & CMF_DISPLINE) nlines += 1 + printfmt(m->disp, 0, 0, 0); else - nlines += 1 + ((1 + niceztrlen(m->disp)) / columns); + nlines += 1 + (niceztrlen(m->disp) / columns); } else if (!(m->flags & CMF_NOLIST)) nlines += 1 + ((1 + niceztrlen(m->str)) / columns); } @@ -678,7 +678,7 @@ complistmatches(Hookdef dummy, Chdata dat) putc(' ', shout); } a = longest - niceztrlen(m->disp ? m->disp : m->str) - 2 - of; - while (a--) + while (a-- > 0) putc(' ', shout); if (col.cols[COL_EC]) tputs(col.cols[COL_EC], 1, putshout); diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c index ecbfc123e..51d331f4a 100644 --- a/Src/Zle/zle_tricky.c +++ b/Src/Zle/zle_tricky.c @@ -3925,7 +3925,8 @@ addmatches(Cadata dat, char **argv) aign = get_user_var(dat->ign); /* Get the display strings. */ if (dat->disp) - disp = get_user_var(dat->disp) - 1; + if ((disp = get_user_var(dat->disp))) + disp--; /* Get the contents of the completion variables if we have * to perform matching. */ if (dat->aflags & CAF_MATCH) { @@ -8194,6 +8195,16 @@ printfmt(char *fmt, int n, int dopr, int doesc) } else { cc++; if (*p == '\n') { + if (dopr) { + if (tccan(TCCLEAREOL)) + tcout(TCCLEAREOL); + else { + int s = columns - 1 - (cc % columns); + + while (s-- > 0) + putc(' ', shout); + } + } l += 1 + (cc / columns); cc = 0; } @@ -8201,7 +8212,16 @@ printfmt(char *fmt, int n, int dopr, int doesc) putc(*p, shout); } } + if (dopr) { + if (tccan(TCCLEAREOL)) + tcout(TCCLEAREOL); + else { + int s = columns - 1 - (cc % columns); + while (s-- > 0) + putc(' ', shout); + } + } return l + (cc / columns); } @@ -8291,7 +8311,7 @@ ilistmatches(Hookdef dummy, Chdata dat) if (m->flags & CMF_DISPLINE) { nlines += 1 + printfmt(m->disp, 0, 0, 0); g->flags |= CGF_HASDL; - } else if ((l = strlen(m->disp)) > longest) + } else if ((l = niceztrlen(m->disp)) > longest) longest = l; nlist++; } else if (!(m->flags & CMF_NOLIST)) { @@ -8310,7 +8330,7 @@ ilistmatches(Hookdef dummy, Chdata dat) } } longest += 2 + of; - if ((ncols = (columns + 1) / longest)) { + if ((ncols = columns / longest)) { for (g = amatches; g; g = g->next) nlines += (g->lcount + ncols - 1) / ncols; } else { @@ -8328,7 +8348,12 @@ ilistmatches(Hookdef dummy, Chdata dat) } } else for (p = g->matches; (m = *p); p++) - if (!(m->flags & CMF_NOLIST)) + if (m->disp) { + if (m->flags & CMF_DISPLINE) + nlines += 1 + printfmt(m->disp, 0, 0, 0); + else + nlines += 1 + (niceztrlen(m->disp) / columns); + } else if (!(m->flags & CMF_NOLIST)) nlines += 1 + ((1 + niceztrlen(m->str)) / columns); } } @@ -8476,7 +8501,7 @@ ilistmatches(Hookdef dummy, Chdata dat) a--; } - if (i && !opl) + if (i && !opl && a > 0) while (a--) putc(' ', shout); if (--n) -- cgit 1.4.1