diff options
Diffstat (limited to 'Completion/Core')
-rw-r--r-- | Completion/Core/_alternative | 70 | ||||
-rw-r--r-- | Completion/Core/_files | 23 | ||||
-rw-r--r-- | Completion/Core/_main_complete | 4 | ||||
-rw-r--r-- | Completion/Core/_requested | 9 | ||||
-rw-r--r-- | Completion/Core/_style | 45 | ||||
-rw-r--r-- | Completion/Core/_tags | 43 | ||||
-rw-r--r-- | Completion/Core/compinit | 171 |
7 files changed, 336 insertions, 29 deletions
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 <return> <name> [ <args> ... ] |