From 97f02ffe63909c84cb9771d20a73ebec55f49589 Mon Sep 17 00:00:00 2001 From: Tanaka Akira Date: Wed, 3 Nov 1999 13:47:39 +0000 Subject: zsh-workers/8520 --- Completion/Base/_arguments | 176 +++++++++++++++++++++-------------------- Completion/Base/_describe | 35 +++----- Completion/Base/_values | 13 ++- Completion/Builtins/_kill | 23 ++++-- Completion/Builtins/_wait | 22 ++++-- Completion/Core/_files | 54 ++++++------- Completion/Core/_main_complete | 17 +++- Completion/Core/_tags | 81 +++++++++++++++++++ Completion/Core/compinit | 76 ++++++++++++++++++ 9 files changed, 340 insertions(+), 157 deletions(-) create mode 100644 Completion/Core/_tags diff --git a/Completion/Base/_arguments b/Completion/Base/_arguments index ca8f42c61..04d588c49 100644 --- a/Completion/Base/_arguments +++ b/Completion/Base/_arguments @@ -154,122 +154,127 @@ fi if comparguments -i "$compconfig[autodescribe_options]" "$@"; then local nm="$compstate[nmatches]" action noargs aret expl local local next direct odirect equal single match matched ws tmp1 tmp2 + local prios tags opts - if ! comparguments -D descr action; then + if comparguments -D descr action; then + if comparguments -O next direct odirect equal; then + opts=yes + _tags -f "$funcstack[2]" argument option + else + _tags -f "$funcstack[2]" argument + fi + else if comparguments -a; then noargs='no more arguments' else noargs='no arguments' fi - fi + comparguments -O next direct odirect equal || return 1 - while true; do + opts=yes + _tags -f "$funcstack[2]" option + fi - if [[ -z "$noargs" || -n "$matched" ]]; then - _description expl "$descr" + while _tags; do + while true; do + if [[ "$tags" = *:argument* ]]; then + _description expl "$descr" - if [[ "$action" = -\>* ]]; then - comparguments -W line opt_args - state="${${action[3,-1]##[ ]#}%%[ ]#}" - compstate[restore]='' - aret=yes - else - if [[ -z "$local" ]]; then - local line - typeset -A opt_args - local=yes - fi + if [[ "$action" = -\>* ]]; then + comparguments -W line opt_args + state="${${action[3,-1]##[ ]#}%%[ ]#}" + compstate[restore]='' + aret=yes + else + if [[ -z "$local" ]]; then + local line + typeset -A opt_args + local=yes + fi - comparguments -W line opt_args + comparguments -W line opt_args - if [[ "$action" = \ # ]]; then + if [[ "$action" = \ # ]]; then - # An empty action means that we should just display a message. + # An empty action means that we should just display a message. - [[ -n "$matched" ]] && compadd -n -Q -S '' -s "$SUFFIX" - "$PREFIX" - mesg="$descr" + [[ -n "$matched" ]] && compadd -n -Q -S '' -s "$SUFFIX" - "$PREFIX" + mesg="$descr" - elif [[ "$action" = \(\(*\)\) ]]; then + elif [[ "$action" = \(\(*\)\) ]]; then - # ((...)) contains literal strings with descriptions. + # ((...)) contains literal strings with descriptions. - eval ws\=\( "${action[3,-3]}" \) + eval ws\=\( "${action[3,-3]}" \) - _describe -c "$cmd" "$descr" ws -M "$match" + _describe -c "$cmd" -f "$funcstack[2]" "$descr" ws -M "$match" - elif [[ "$action" = \(*\) ]]; then + elif [[ "$action" = \(*\) ]]; then - # Anything inside `(...)' is added directly. + # Anything inside `(...)' is added directly. - compadd "$expl[@]" - ${=action[2,-2]} - elif [[ "$action" = \{*\} ]]; then + compadd "$expl[@]" - ${=action[2,-2]} + elif [[ "$action" = \{*\} ]]; then - # A string in braces is evaluated. + # A string in braces is evaluated. - eval "$action[2,-2]" + eval "$action[2,-2]" - elif [[ "$action" = \ * ]]; then + elif [[ "$action" = \ * ]]; then - # If the action starts with a space, we just call it. + # If the action starts with a space, we just call it. - ${(e)=~action} - else + ${(e)=~action} + else - # Otherwise we call it with the description-arguments built above. + # Otherwise we call it with the description-arguments built above. - action=( $=action ) - ${(e)action[1]} "$expl[@]" ${(e)~action[2,-1]} + action=( $=action ) + ${(e)action[1]} "$expl[@]" ${(e)~action[2,-1]} + fi fi fi - fi - - if [[ -z "$matched" ]] && - comparguments -O next direct odirect equal && - [[ ( ( nm -eq compstate[nmatches] || -n "$noargs" ) && - -z "$aret" && -z "$mesg" ) || - -z "$compconfig[option_prefix]" || - "$compconfig[option_prefix]" = *\!${cmd}* || - "$PREFIX" = [-+]* ]]; then - - comparguments -M match - - if comparguments -s single; then - - _description 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}" + if [[ "$tags" = *:option* && + ( "$tags" != *\[*prefix*\]* || "$PREFIX" = [-+]* ) ]]; then + comparguments -M match + + if comparguments -s single; then + + _description 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[@]" ) + tmp1=( "${(M@)tmp1:#[-+]?(|:*)}" ) + tmp2=( "${PREFIX}${(@M)^${(@)${(@)tmp1%%:*}#[-+]}:#?}" ) + + _describe -o -c "$cmd" -f "$funcstack[2]" option \ + tmp1 tmp2 -Q -S '' + fi + single=yes else - tmp1=( "$next[@]" "$direct[@]" "$odirect[@]" "$equal[@]" ) - tmp1=( "${(M@)tmp1:#[-+]?(|:*)}" ) - tmp2=( "${PREFIX}${(@M)^${(@)${(@)tmp1%%:*}#[-+]}:#?}" ) - - _describe -o -c "$cmd" option tmp1 tmp2 -Q -S '' + next=( "$next[@]" "$odirect[@]" ) + _describe -o -c "$cmd" -f "$funcstack[2]" option \ + next -Q -M "$match" -- \ + direct -QS '' -M "$match" -- \ + equal -QqS= -M "$match" fi - single=yes - else - next=( "$next[@]" "$odirect[@]" ) - _describe -o -c "$cmd" option \ - next -Q -M "$match" -- \ - direct -QS '' -M "$match" -- \ - equal -QqS= -M "$match" fi - - if [[ nm -eq compstate[nmatches] && -z "$aret" && - ( ( -z "$single" && "$PREFIX" = [-+]*\=* ) || - "$PREFIX" = --* ) ]]; then + if [[ -n "$opts" && -z "$aret$matched" && nm -ne compstate[nmatches] && + "$tags" = *:argument* ]]; then local prefix suffix - prefix="${PREFIX#*\=}" - suffix="$SUFFIX" - PREFIX="${PREFIX%%\=*}" - SUFFIX='' - compadd -M "$match" -D equal - "${(@)equal%%:*}" + prefix="${PREFIX#*\=}" + suffix="$SUFFIX" + PREFIX="${PREFIX%%\=*}" + SUFFIX='' + compadd -M "$match" -D equal - "${(@)equal%%:*}" if [[ $#equal -eq 1 ]]; then PREFIX="$prefix" @@ -277,11 +282,13 @@ if comparguments -i "$compconfig[autodescribe_options]" "$@"; then IPREFIX="${IPREFIX}${equal[1]%%:*}=" matched=yes comparguments -L "$equal[1]" descr action + tags=argument continue - fi + fi fi - fi - break + break + done + [[ -n "$aret" || nm -ne compstate[nmatches] ]] && break done [[ -n "$aret" ]] && return 300 @@ -292,7 +299,6 @@ if comparguments -i "$compconfig[autodescribe_options]" "$@"; then # Set the return value. [[ nm -ne "$compstate[nmatches]" ]] - else return 1 fi diff --git a/Completion/Base/_describe b/Completion/Base/_describe index e59dc1593..5355e4d7f 100644 --- a/Completion/Base/_describe +++ b/Completion/Base/_describe @@ -2,15 +2,19 @@ # This can be used to add options or values with descriptions as matches. -local isopt cmd opt expl tmps tmpd tmpmd tmpms ret=1 showd _nm hide +local cmd func opt expl tmps tmpd tmpmd tmpms ret=1 showd _nm hide +local prios tags type=value cmd="$words[1]" +func="$funcstack[2]" # Get the options. -while getopts 'oc:' opt; do +while getopts 'oc:f:' opt; do if [[ "$opt" = o ]]; then - isopt=yes + type=option + elif [[ "$opt" = f ]]; then + func="$OPTARG" else cmd="$OPTARG" fi @@ -19,28 +23,11 @@ shift OPTIND-1 # Do the tests. `showd' is set if the descriptions should be shown. -if [[ -n "$isopt" ]]; then +_tags -c "$cmd" -f "$func" "$type" - # We take the value to test the number of matches from a non-local - # parameter `nm' if that exists and contains only digits. It's a hack. +_tags || return 1 - 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 +[[ "$tags" = *:${type}\[*describe*\]* ]] && showd=yes _description expl "$1" shift @@ -51,7 +38,7 @@ else compdescribe -i "$@" fi -[[ -n "$isopt" && "$compconfig[option_prefix]" = hide* ]] && hide=yes +[[ "$type" = option && "$tags" = *:option\[*hide*\]* ]] && hide=yes while compdescribe -g args tmpd tmpmd tmps tmpms; do diff --git a/Completion/Base/_values b/Completion/Base/_values index e4ef8af68..34a5c4097 100644 --- a/Completion/Base/_values +++ b/Completion/Base/_values @@ -2,9 +2,13 @@ if compvalues -i "$@"; then - local noargs args opts descr action expl sep + local tags prios noargs args opts descr action expl sep if ! compvalues -D descr action; then + + _tags value + _tags || return 1 + compvalues -V noargs args opts if [[ "$PREFIX" = *\=* ]]; then @@ -39,7 +43,7 @@ if compvalues -i "$@"; then sep=() fi - _describe "$descr" \ + _describe -f "$funcstack[2]" "$descr" \ noargs "$sep[@]" -M 'r:|[_-]=* r:|=*' -- \ args -S= -M 'r:|[_-]=* r:|=*' -- \ opts -qS= -M 'r:|[_-]=* r:|=*' @@ -48,6 +52,9 @@ if compvalues -i "$@"; then fi fi + _tags argument + _tags || return 1 + _description expl "$descr" # We add the separator character as a autoremovable suffix unless @@ -80,7 +87,7 @@ if compvalues -i "$@"; then eval ws\=\( "${action[3,-3]}" \) - _describe "$descr" ws -M 'r:|[_-]=* r:|=*' + _describe -f "$funcstack[2]" "$descr" ws -M 'r:|[_-]=* r:|=*' elif [[ "$action" = \(*\) ]]; then diff --git a/Completion/Builtins/_kill b/Completion/Builtins/_kill index 2af168f3f..a3efbef41 100644 --- a/Completion/Builtins/_kill +++ b/Completion/Builtins/_kill @@ -6,14 +6,21 @@ if compset -P 1 -; then _description expl signal compadd "$expl[@]" $signals[1,-3] else - local ret=1 - - _jobs && ret=0 - - list=("${(@M)${(f@)$(ps ${=compconfig[ps_listargs]:-$=compconfig[ps_args]} 2>/dev/null)}[2,-1]:#[ ]#${PREFIX}[0-9]#${SUFFIX}[ ]*}") - _description expl 'process ID' - compadd "$expl[@]" -ld list - ${${${(f)"$(ps $=compconfig[ps_args] 2>/dev/null)"}[2,-1]## #}%% *} && - ret=0 + local prios tags ret=1 + + _tags job process + + while _tags; do + [[ "$tags" = *:job:* ]] && _jobs && ret=0 + if [[ "$tags" = *:process:* ]]; then + list=("${(@M)${(f@)$(ps ${=compconfig[ps_listargs]:-$=compconfig[ps_args]} 2>/dev/null)}[2,-1]:#[ ]#${PREFIX}[0-9]#${SUFFIX}[ ]*}") + _description expl 'process ID' + compadd "$expl[@]" -ld list - \ + ${${${(f)"$(ps $=compconfig[ps_args] 2>/dev/null)"}[2,-1]## #}%% *} && + ret=0 + fi + (( ret )) || break + done return ret fi diff --git a/Completion/Builtins/_wait b/Completion/Builtins/_wait index b659532e7..0f096355f 100644 --- a/Completion/Builtins/_wait +++ b/Completion/Builtins/_wait @@ -1,11 +1,19 @@ #compdef wait -local list ret=1 expl - -_jobs && ret=0 - -list=("${(@M)${(f)$(ps ${=compconfig[ps_listargs]:-$=compconfig[ps_args]} 2>/dev/null)}[2,-1]:#[ ]#${PREFIX}[0-9]#${SUFFIX}[ ]*}") -_description expl 'process ID' -compadd "$expl[@]" -ld list - ${${${(f)"$(ps $=compconfig[ps_args] 2>/dev/null)"}[2,-1]## #}%% *} && ret=0 +local prios tags list ret=1 expl + +_tags job process + +while _tags; do + [[ "$tags" = *:job:* ]] && _jobs && ret=0 + if [[ "$tags" = *:process:* ]]; then + list=("${(@M)${(f@)$(ps ${=compconfig[ps_listargs]:-$=compconfig[ps_args]} 2>/dev/null)}[2,-1]:#[ ]#${PREFIX}[0-9]#${SUFFIX}[ ]*}") + _description expl 'process ID' + compadd "$expl[@]" -ld list - \ + ${${${(f)"$(ps $=compconfig[ps_args] 2>/dev/null)"}[2,-1]## #}%% *} && + ret=0 + fi + (( ret )) || break +done return ret diff --git a/Completion/Core/_files b/Completion/Core/_files index 38eafd196..e667289c5 100644 --- a/Completion/Core/_files +++ b/Completion/Core/_files @@ -1,31 +1,27 @@ #autoload -# Utility function for completing files of a given type or any file. -# In many cases you will want to call this one instead of `_path_files'. - -local nm=$compstate[nmatches] ret=1 - -_path_files "$@" && ret=0 - -if [[ $# -ne 0 && compstate[nmatches] -eq nm ]]; then - local opt opts - - # We didn't get any matches for those types of files described by - # the `-g' or `-/' option. Now we try it again accepting all files. - # First we get those options that we have to use even then. If we - # find out that the `-f' option was given, we already accepted all - # files and give up immediatly. - - opts=() - while getopts "P:S:qr:R:W:F:J:V:X:f/g:M:" opt; do - case "$opt" in - f) return;; - [PSrRWFJVXM]) opts=("$opts[@]" "-$opt" "$OPTARG");; - q) opts=("$opts[@]" -q);; - esac - done - - _path_files "$opts[@]" && ret=0 -fi - -return ret +local opts opt type=file prios tags + +opts=() +while getopts "P:S:qr:R:W:F:J:V:X:f/g:M:" opt; do + case "$opt" in + /) [[ "$type" = file ]] && type=dir ;; + g) [[ "$type" = (file|dir) ]] && type="$OPTARG" ;; + q) opts=("$opts[@]" -q ) ;; + [^f]) opts=("$opts[@]" "-$opt" "$OPTARG") ;; + esac +done + +case "$type" in +file) _tags -f "$funcstack[2]" file ;; +dir) _tags -f "$funcstack[2]" path file ;; +*) _tags -f "$funcstack[2]" glob path file ;; +esac + +while _tags; do + [[ "$tags" = *:file:* ]] && { _path_files "$opts[@]" -f ; return } + [[ "$tags" = *:path:* ]] && _path_files "$opts[@]" -/ && return 0 + [[ "$tags" = *:glob:* ]] && _path_files "$opts[@]" -g "$type" && return 0 +done + +return 1 diff --git a/Completion/Core/_main_complete b/Completion/Core/_main_complete index 72233a59b..877a975b3 100644 --- a/Completion/Core/_main_complete +++ b/Completion/Core/_main_complete @@ -17,7 +17,12 @@ # state than the global one for which you are completing. -local comp post ret=1 _compskip +local comp post ret=1 _compskip prios tags +typeset -U _offered_tags _tried_tags _failed_tags _used_tags _unused_tags + +_offered_tags=() +_tried_tags=() +_failed_tags=() typeset -U _lastdescr @@ -46,6 +51,11 @@ for comp; do fi done +# See which tags were or were not used. + +_used_tags=( "${(@)_tried_tags:#${(j:|:)~${(@)_failed_tags//\[/\\[}//\]/\\]}}" ) +_unused_tags=( "${(@)_offered_tags:#${(j:|:)~${(@)_used_tags//\[/\\[}//\]/\\]}}" ) + # Now call the post-functions. for post in "$comppostfuncs[@]"; do @@ -82,5 +92,10 @@ _lastcomp[iprefix]="$IPREFIX" _lastcomp[isuffix]="$ISUFFIX" _lastcomp[qiprefix]="$QIPREFIX" _lastcomp[qisuffix]="$QISUFFIX" +_lastcomp[offered_tags]="${(j.:.)_offered_tags}" +_lastcomp[tried_tags]="${(j.:.)_tried_tags}" +_lastcomp[failed_tags]="${(j.:.)_failed_tags}" +_lastcomp[unused_tags]="${(j.:.)_unused_tags}" +_lastcomp[used_tags]="${(j.:.)_used_tags}" return ret diff --git a/Completion/Core/_tags b/Completion/Core/_tags new file mode 100644 index 000000000..af8dc21dd --- /dev/null +++ b/Completion/Core/_tags @@ -0,0 +1,81 @@ +#autoload + +if (( $# )); then + local cmd="$words[1]" func="$funcstack[2]" defs i tags tag pat style prio + + while getopts 'c:f:' i; do + if [[ "$i" = c ]]; then + cmd="$OPTARG" + else + func="$OPTARG" + fi + done + + shift OPTIND-1 + + defs=( "${(@M)argv:#${(kj:|:)~override_tags[(R)(|+*)]}}" ) + (( $#defs )) && set -- "$defs[@]" + + _offered_tags=( "$_offered_tags[@]" "$@" ) + _last_tags=() + + defs=() + for i; do + if [[ -n ${override_tags[$i]} && ${override_tags[$i]} != (\[|+\[)* ]]; then + if [[ ${override_tags[$i]} = *\[* ]]; then + prio=( "${i}:*=${override_tags[$i]#+}" ) + else + prio=( "${i}:${(@v)^comptags[(I)(|*:)${i}(|:*)]}" ) + (( $#prio )) || prio=( "${i}:${comptags[any]}" ) + prio="${${${prio[(r)(|*:)\*=[^:]#\[*\](|:*)]}##(|*:)\*}%%:*}" + prio=( "${i}:*=${override_tags[$i]#+}${(M)prio%%\[*\]}" ) + fi + else + prio=( "${i}:${(@v)^comptags[(I)(|*:)${i}(|:*)]}" ) + (( $#prio )) || prio=( "${i}:${comptags[any]}" ) + fi + defs=( "$defs[@]" "$prio[@]" ) + done + + tags=() + for i in "$defs[@]"; do + tag="${i%%:*}" + for pat in "${(s.:.)i#*:}"; do + if [[ ( "$pat" = _* && "$func" = ${~pat%%\=*} ) || + "$cmd" = ${~pat%%\=*} ]]; then + prio="${pat#*\=}" + [[ "$prio" = -* ]] && continue 2 + + if [[ "$prio" = *\[*\] ]]; then + style="${(M)prio%%\[*}" + prio="${prio%%\[*}" + else + style='' + fi + [[ ${override_tags[$tag]} = (|+)\[* ]] && + style="${override_tags[$tag]#+}" + + (( prio++ )) + + tags[$prio]="${tags[$prio]}:${tag}${style}" + break + fi + done + done + + prios=( "${(@)tags:#}" ) + + return 0 +fi + +_failed_tags=( "$_failed_tags[@]" "$_last_tags[@]" ) + +(( $#prios )) || return 1 + +tags="${prios[1]}:" +shift 1 prios + +_last_tags=( "${(@s.:.)${${tags#:}%:}}" ) +_tried_tags=( "$_tried_tags[@]" "$_last_tags[@]" ) + +return 0 diff --git a/Completion/Core/compinit b/Completion/Core/compinit index 3569014c6..3d316fac8 100644 --- a/Completion/Core/compinit +++ b/Completion/Core/compinit @@ -108,6 +108,14 @@ fi compconfig[correct_prompt]='correct to:' (( ${+compconfig[completer]} )) || compconfig[completer]=_complete +# This holds the tag/priority definitions. + +typeset -gA comptags + +(( ${+comptags[any]} )) || comptags[any]='*=100' + +typeset -gA override_tags + # This can hold names of functions that are to be called after all # matches have been generated. @@ -370,6 +378,74 @@ compconf() { fi } +# Function to set tags and priorities. + +comptag() { + local i opt list tag val + + while getopts "lL" opt; do + if [[ "$opt" = l ]]; then + [[ -z "$list" ]] && list=yes + else + list=long + fi + done + shift OPTIND-1 + + if (( $# )); then + if [[ -n $list ]]; then + for i; do + if [[ $list = long ]]; then + (( ${+comptags[$i]} )) && print "comptag $i='$comptags[$i]'" + else + print $comptags[$i] + fi + done + else + for i; do + tag="${i%%([-+]|)\=*}" + val="${${i#*(|[-+])\=}#+}" + case "$i" in + *+\=*) + if [[ -n "$comptags[$tag]" ]]; then + comptags[$tag]="${val}:${comptags[$tag]}" + else + comptags[$tag]="$val" + fi + ;; + *\=+*) + if [[ -n "$comptags[$tag]" ]]; then + comptags[$tag]="${comptags[$tag]}:${val}" + else + comptags[$tag]="$val" + fi + ;; + *-\=*) + if [[ -n "$comptags[$tag]" ]]; then + comptags[$tag]="${${${comptags[$tag]//:${val}\=[^:]##}#${val}\=*:}%:${val}\=[^:]##}" + [[ "$comptags[$tag]" = ${val}\=* ]] && unset "comptags[$tag]" + fi + ;; + *\=*) + comptags[${i%%\=*}]="${i#*\=}" + ;; + *) + unset "compconfig[$i]" + ;; + esac + done + fi + else + for i in ${(ok)comptags}; do + if [[ $list = long ]]; then + print "comptag $i='$comptags[$i]'" + else + print ${(r:25:)i} "$comptags[$i]" + fi + done + fi +} + # Utility function to call a function if it exists. # # Usage: funcall [ ... ] -- cgit 1.4.1