From c615397157e5efd7a81c8ce11b3f77fd7ccb5a19 Mon Sep 17 00:00:00 2001 From: Tanaka Akira Date: Tue, 9 Nov 1999 13:14:59 +0000 Subject: zsh-workers/8603 --- Completion/Base/_arguments | 26 +++---- Completion/Base/_describe | 15 ++-- Completion/Base/_values | 10 +-- Completion/Builtins/_kill | 16 +--- Completion/Builtins/_wait | 12 +-- Completion/Core/_alternative | 70 +++++++++++++++++ Completion/Core/_files | 23 ++++-- Completion/Core/_main_complete | 4 +- Completion/Core/_requested | 9 +++ Completion/Core/_style | 45 +++++++++++ Completion/Core/_tags | 43 ++++++----- Completion/Core/compinit | 171 +++++++++++++++++++++++++++++++++++++++++ 12 files changed, 364 insertions(+), 80 deletions(-) create mode 100644 Completion/Core/_alternative create mode 100644 Completion/Core/_requested create mode 100644 Completion/Core/_style diff --git a/Completion/Base/_arguments b/Completion/Base/_arguments index 31713750f..68b52eef4 100644 --- a/Completion/Base/_arguments +++ b/Completion/Base/_arguments @@ -154,14 +154,14 @@ 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 tags opts + local opts if comparguments -D descr action; then if comparguments -O next direct odirect equal; then opts=yes - _tags -f "$funcstack[2]" argument option + _tags argument option else - _tags -f "$funcstack[2]" argument + _tags argument fi else if comparguments -a; then @@ -172,12 +172,12 @@ if comparguments -i "$compconfig[autodescribe_options]" "$@"; then comparguments -O next direct odirect equal || return 1 opts=yes - _tags -f "$funcstack[2]" option + _tags option fi while _tags; do while true; do - if [[ "$tags" = *:argument* ]]; then + if [[ -n "$matched" ]] || _requested argument; then _description expl "$descr" if [[ "$action" = -\>* ]]; then @@ -207,7 +207,7 @@ if comparguments -i "$compconfig[autodescribe_options]" "$@"; then eval ws\=\( "${action[3,-3]}" \) - _describe -c "$cmd" -f "$funcstack[2]" "$descr" ws -M "$match" + _describe -c "$cmd" "$descr" ws -M "$match" elif [[ "$action" = \(*\) ]]; then @@ -234,8 +234,8 @@ if comparguments -i "$compconfig[autodescribe_options]" "$@"; then fi fi fi - if [[ "$tags" = *:option* && - ( "$tags" != *\[*prefix*\]* || "$PREFIX" = [-+]* ) ]]; then + if [[ -z "$matched" ]] && _requested option && + { ! _style option prefix || [[ "$PREFIX" = [-+]* ]] } ; then comparguments -M match if comparguments -s single; then @@ -253,20 +253,21 @@ if comparguments -i "$compconfig[autodescribe_options]" "$@"; then tmp1=( "${(M@)tmp1:#[-+]?(|:*)}" ) tmp2=( "${PREFIX}${(@M)^${(@)${(@)tmp1%%:*}#[-+]}:#?}" ) - _describe -o -c "$cmd" -f "$funcstack[2]" option \ + _describe -o -c "$cmd" option \ tmp1 tmp2 -Q -S '' fi single=yes else next=( "$next[@]" "$odirect[@]" ) - _describe -o -c "$cmd" -f "$funcstack[2]" option \ + _describe -o -c "$cmd" option \ next -Q -M "$match" -- \ direct -QS '' -M "$match" -- \ equal -QqS= -M "$match" fi fi - if [[ -n "$opts" && -z "$aret$matched" && nm -ne compstate[nmatches] && - "$tags" = *:argument* ]]; then + if [[ -n "$opts" && -z "$aret$matched" && + nm -ne compstate[nmatches] ]] && + _requested argument; then local prefix suffix @@ -282,7 +283,6 @@ if comparguments -i "$compconfig[autodescribe_options]" "$@"; then IPREFIX="${IPREFIX}${equal[1]%%:*}=" matched=yes comparguments -L "$equal[1]" descr action - tags=argument continue fi fi diff --git a/Completion/Base/_describe b/Completion/Base/_describe index ddd35f0e7..41c2ba8e5 100644 --- a/Completion/Base/_describe +++ b/Completion/Base/_describe @@ -2,19 +2,16 @@ # This can be used to add options or values with descriptions as matches. -local cmd func opt expl tmps tmpd tmpmd tmpms ret=1 showd _nm hide -local tags type=value +local cmd opt expl tmps tmpd tmpmd tmpms ret=1 showd _nm hide +local type=value cmd="$words[1]" -func="$funcstack[2]" # Get the options. -while getopts 'oc:f:' opt; do +while getopts 'oc:' opt; do if [[ "$opt" = o ]]; then type=option - elif [[ "$opt" = f ]]; then - func="$OPTARG" else cmd="$OPTARG" fi @@ -23,9 +20,9 @@ shift OPTIND-1 # Do the tests. `showd' is set if the descriptions should be shown. -_tags -i -c "$cmd" -f "$func" "$type" || return 1 +_tags -c "$cmd" "$type" || return 1 -[[ "$tags" = *:${type}\[*describe*\]* ]] && showd=yes +_style "$type" describe && showd=yes _description expl "$1" shift @@ -36,7 +33,7 @@ else compdescribe -i "$@" fi -[[ "$type" = option && "$tags" = *:option\[*hide*\]* ]] && hide=yes +[[ "$type" = option ]] && _style option hide && hide=yes while compdescribe -g args tmpd tmpmd tmps tmpms; do diff --git a/Completion/Base/_values b/Completion/Base/_values index 9d89c7ea9..aac8b392d 100644 --- a/Completion/Base/_values +++ b/Completion/Base/_values @@ -2,11 +2,11 @@ if compvalues -i "$@"; then - local tags noargs args opts descr action expl sep + local noargs args opts descr action expl sep if ! compvalues -D descr action; then - _tags -i value || return 1 + _tags value || return 1 compvalues -V noargs args opts @@ -42,7 +42,7 @@ if compvalues -i "$@"; then sep=() fi - _describe -f "$funcstack[2]" "$descr" \ + _describe "$descr" \ noargs "$sep[@]" -M 'r:|[_-]=* r:|=*' -- \ args -S= -M 'r:|[_-]=* r:|=*' -- \ opts -qS= -M 'r:|[_-]=* r:|=*' @@ -51,7 +51,7 @@ if compvalues -i "$@"; then fi fi - _tags -i argument || return 1 + _tags argument || return 1 _description expl "$descr" @@ -85,7 +85,7 @@ if compvalues -i "$@"; then eval ws\=\( "${action[3,-3]}" \) - _describe -f "$funcstack[2]" "$descr" ws -M 'r:|[_-]=* r:|=*' + _describe "$descr" ws -M 'r:|[_-]=* r:|=*' elif [[ "$action" = \(*\) ]]; then diff --git a/Completion/Builtins/_kill b/Completion/Builtins/_kill index bb198b7a4..43ff40838 100644 --- a/Completion/Builtins/_kill +++ b/Completion/Builtins/_kill @@ -1,23 +1,13 @@ #compdef kill -local tags list expl +local list expl if compset -P 1 -; then - _tags -i signal || return 1 + _tags signal || return 1 _description expl signal compadd "$expl[@]" $signals[1,-3] else - local ret=1 - - _tags job process - - while _tags; do - [[ "$tags" = *:job:* ]] && _jobs && ret=0 - [[ "$tags" = *:process:* ]] && _pids && ret=0 - (( ret )) || break - done - - return ret + _alternative 'job:: _jobs' 'process:: _pids' fi diff --git a/Completion/Builtins/_wait b/Completion/Builtins/_wait index b03aac6e0..c1022a25f 100644 --- a/Completion/Builtins/_wait +++ b/Completion/Builtins/_wait @@ -1,13 +1,3 @@ #compdef wait -local tags ret=1 - -_tags job process - -while _tags; do - [[ "$tags" = *:job:* ]] && _jobs && ret=0 - [[ "$tags" = *:process:* ]] && _pids && ret=0 - (( ret )) || break -done - -return ret +_alternative 'job:: _jobs' 'process:: _pids' diff --git a/Completion/Core/_alternative b/Completion/Core/_alternative new file mode 100644 index 000000000..158f3a07a --- /dev/null +++ b/Completion/Core/_alternative @@ -0,0 +1,70 @@ +#autoload + +local tags def expl descr action mesgs nm="$compstack[nmatches]" +local context + +if [[ "$1" = -C?* ]]; then + context="${1[3,-1]}" + shift +elif [[ "$1" = -C ]]; then + context="$2" + shift 2 +fi + +mesgs=() + +_tags -C "$context" "${(@)argv%%:*}" + +while _tags; do + for def; do + if _requested "${def%%:*}"; then + descr="${${def#*:}%%:*}" + action="${def#*:*:}" + + _description expl "$descr" + + if [[ "$action" = \ # ]]; then + + # An empty action means that we should just display a message. + + mesgs=( "$mesgs[@]" "$descr") + elif [[ "$action" = \(\(*\)\) ]]; then + local ws + + # ((...)) contains literal strings with descriptions. + + eval ws\=\( "${action[3,-3]}" \) + + _describe "$descr" ws -M 'r:|[_-]=* r:|=*' + 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 + done + [[ nm -ne compstate[nmatches] ]] && return 0 +done + +for descr in "$mesgs[@]"; do + _message "$descr" +done + +return 1 diff --git a/Completion/Core/_files b/Completion/Core/_files index 4adae0f73..eb1ec3559 100644 --- a/Completion/Core/_files +++ b/Completion/Core/_files @@ -1,6 +1,6 @@ #autoload -local opts opt type=file tags +local opts opt type=file opts=() while getopts "P:S:qr:R:W:F:J:V:X:f/g:M:" opt; do @@ -13,15 +13,24 @@ while getopts "P:S:qr:R:W:F:J:V:X:f/g:M:" opt; do done case "$type" in -file) _tags -f "$funcstack[2]" file ;; -dir) _tags -f "$funcstack[2]" path file ;; -*) _tags -f "$funcstack[2]" glob path file ;; +file) _tags file ;; +dir) _tags path file ;; +*) _tags 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 + if _requested file; then + _path_files "$opts[@]" -f + return + elif _requested path; then + if _requested glob; then + _path_files "$opts[@]" -/g "$type" && return 0 + else + _path_files "$opts[@]" -/g "$type" && return 0 + fi + elif _requested glob; then + _path_files "$opts[@]" -g "$type" && return 0 + fi done return 1 diff --git a/Completion/Core/_main_complete b/Completion/Core/_main_complete index d1d75de7f..e4ee2879b 100644 --- a/Completion/Core/_main_complete +++ b/Completion/Core/_main_complete @@ -17,9 +17,9 @@ # state than the global one for which you are completing. -local comp post ret=1 _compskip tags _prio_num=1 +local comp post ret=1 _compskip _prio_num=1 typeset -U _offered_tags _tried_tags _failed_tags _used_tags _unused_tags -typeset -A _prio_names +typeset -A _prio_names _cur_tags _offered_tags=() _tried_tags=() diff --git a/Completion/Core/_requested b/Completion/Core/_requested new file mode 100644 index 000000000..082c45820 --- /dev/null +++ b/Completion/Core/_requested @@ -0,0 +1,9 @@ +#autoload + +local tag tname="$funcstack[2,-1]" + +for tag; do + [[ "${_cur_tags[${tname}]}" = *:${tag}(:|\[*\]:)* ]] && return 0 +done + +return 1 diff --git a/Completion/Core/_style b/Completion/Core/_style new file mode 100644 index 000000000..b0cbd7b00 --- /dev/null +++ b/Completion/Core/_style @@ -0,0 +1,45 @@ +#autoload + +local tags get i + +if [[ "$1" = -g ]]; then + get=yes + shift +fi + +if (( ${+_cur_tags[${funcstack[2,-1]}]} )); then + tags="${_cur_tags[${funcstack[2,-1]}]}" +else + tags="${_cur_tags[${funcstack[3,-1]}]}" +fi + +if [[ "$tags" = *:${1}\[*\]:* ]]; then + + tags="${${tags#*:${1}\[}%%\]*}" + + if [[ $# -eq 2 ]]; then + if [[ -n "$get" ]]; then + eval "${2}=\"$tags\"" + return 0 + fi + + [[ "$tags" = (|*,)${2}(|,*) ]] + return + fi + + [[ "$tags" = (|*,)${2}(|(\=|,)*) ]] || return 1 + + if [[ -n "$get" ]]; then + if [[ "$tags" = (|*,)${2}\=* ]]; then + eval "${3}=\"${${tags#(|*,)${2}\=}%%,*}\"" + else + eval "${3}=''" + fi + return 0 + fi + + [[ "$tags" = (|*,)${2}\=(|[^,]#,)${3}(|,*) ]] + return +fi + +return 1 diff --git a/Completion/Core/_tags b/Completion/Core/_tags index 9b9ce96b4..7b1254325 100644 --- a/Completion/Core/_tags +++ b/Completion/Core/_tags @@ -1,19 +1,21 @@ #autoload +local tname="$funcstack[2,-1]" + if (( $# )); then - local cmd="$words[1]" func="$funcstack[2]" defs i ttags tag pat style prio - local trynow - - while getopts 'c:f:i' i; do - case "$i" in - c) cmd="$OPTARG" ;; - f) func="$OPTARG" ;; - i) trynow=yes ;; - esac - done + local cmd="$words[1]" defs i ttags tag pat style prio context opt + while getopts 'c:C:' opt; do + if [[ "$opt" = c ]]; then + cmd="$OPTARG" + else + context="$OPTARG" + fi + done shift OPTIND-1 + [[ -n "$context" ]] && context="/$context" + defs=( "${(@M)argv:#${(kj:|:)~override_tags[(R)(|+*)]}}" ) (( $#defs )) && set -- "$defs[@]" @@ -42,8 +44,7 @@ if (( $# )); then for i in "$defs[@]"; do tag="${i%%:*}" for pat in "${(s.:.)i#*:}"; do - if [[ ( "$pat" = _* && "$func" = ${~pat%%\=*} ) || - "$cmd" = ${~pat%%\=*} ]]; then + if [[ "$cmd$context" = ${~pat%%\=*} ]]; then prio="${pat#*\=}" [[ "$prio" = -* ]] && continue 2 @@ -65,22 +66,24 @@ if (( $# )); then done prio="_prio_arr$(( _prio_num++ ))" - _prio_names[$funcstack]="$prio" - eval "${prio}=( \"\${(@)ttags:#}\" )" + _prio_names[$tname]="$prio" + ttags=( "${(@)ttags:#}" ) + eval "${prio}=( \"\$ttags[@]\" )" - [[ -z "$trynow" ]] && return 0 + return \!$#ttags fi -local prios="$_prio_names[$funcstack]" +local prios="$_prio_names[$tname]" -_failed_tags=( "$_failed_tags[@]" "$_last_tags[@]" ) +_failed_tags=( "$_failed_tags[@]" "$_last_tags" ) (( ${(P)#prios} )) || return 1 -tags="${${(@P)prios}[1]}:" -shift 1 "$prios" +_cur_tags[$tname]="${(@)${(@P)prios}[1]}:" -_last_tags=( "${(@s.:.)${${tags#:}%:}}" ) +_last_tags=( "${(@)${(@s.:.)${(@P)prios}[1]}:#}" ) _tried_tags=( "$_tried_tags[@]" "$_last_tags[@]" ) +shift 1 "$prios" + return 0 diff --git a/Completion/Core/compinit b/Completion/Core/compinit index 3d316fac8..1b88cc8f0 100644 --- a/Completion/Core/compinit +++ b/Completion/Core/compinit @@ -446,6 +446,177 @@ comptag() { fi } +# First suggested function for new configuration interface. +# +# Example: +# +# conf1 \ +# argument = 1 \ +# value = 1 with describe \ +# option = 2 with describe and hide \ +# file = 3 \ +# path in '*dvi*' = 1 \ +# else = 2 \ +# glob = 1 \ +# job = never + +conf1() { + local tag pat prio + + while (( $# )); do + + tag="$1" + shift + + while (( $# )); do + + if [[ "$1" = in ]]; then + pat="$2" + shift 2 + else + pat='*' + [[ "$1" = else ]] && shift + fi + + style='' + + if [[ "$1" = is ]]; then + prio=0 + style="[${2}]" + shift 2 + elif [[ "$1" = \= ]]; then + if [[ "$2" = n(o|ever) ]]; then + prio=-1 + shift 2 + else + prio="$2" + shift 2 + + if [[ "$1" = with ]]; then + while [[ "$1" = (with|and) ]]; do + style="${style},${2}" + shift 2 + done + style="[${style[2,-1]}]" + fi + fi + else + echo "$0: missing priority: $1" + return 1 + fi + if [[ -n "$comptags[$tag]" ]]; then + comptags[$tag]="${comptags[$tag]}:${pat}=${prio}${style}" + else + comptags[$tag]="${pat}=${prio}${style}" + fi + + [[ "$1" = (in|else|\=) ]] || break + + done + done + + return 0 +} + +# Second suggested function for new configuration interface. +# +# Example: +# +# conf2 \ +# for '*dvi*' do \ +# glob and path or \ +# file \ +# else do \ +# glob or \ +# path or \ +# file \ +# for '*p[bgpn]m*' do \ +# argument and option with describe and with hide \ +# else do \ +# argument or \ +# value with describe or \ +# option with describe \ +# for 'kill' do \ +# no job but \ +# process \ +# else do \ +# process and job + +conf2() { + local pat prio tag style + + while (( $# )); do + + if [[ "$1" = for ]]; then + pat="$2" + shift 2 + elif [[ "$1" = (else|always) ]]; then + pat="*" + shift + else + echo "$0: missing context: $1" + return 1 + fi + + shift 1 + + prio=1 + + while (( $# )); do + + if [[ "$1" = no ]]; then + while [[ "$1" != (but|for|else|always) ]]; do + if [[ -n "$comptags[$2]" ]]; then + comptags[$2]="${comptags[$2]}:${pat}=-1" + else + comptags[$2]="${pat}=-1" + fi + + shift 2 + done + + [[ "$1" != but ]] && break + + shift + fi + + while (( $# )); do + + tag="$1" + shift + + style='' + if [[ "$1" = with ]]; then + shift + while true; do + style="${style},${1}" + [[ "$2" != and || "$3" != with ]] && break + shift 3 + done + shift + fi + + [[ -n "$style" ]] && style="[${style[2,-1]}]" + + if [[ -n "$comptags[$tag]" ]]; then + comptags[$tag]="${comptags[$tag]}:${pat}=${prio}${style}" + else + comptags[$tag]="${pat}=${prio}${style}" + fi + + [[ "$1" != and ]] && break + + shift + done + + [[ "$1" != or ]] && break + + (( prio++ )) + shift + done + done +} + # Utility function to call a function if it exists. # # Usage: funcall [ ... ] -- cgit 1.4.1