diff options
Diffstat (limited to 'Completion/Commands')
-rw-r--r-- | Completion/Commands/_next_tags | 168 |
1 files changed, 97 insertions, 71 deletions
diff --git a/Completion/Commands/_next_tags b/Completion/Commands/_next_tags index d9a5f08d8..a308b307c 100644 --- a/Completion/Commands/_next_tags +++ b/Completion/Commands/_next_tags @@ -3,30 +3,103 @@ # Main widget. _next_tags() { - local comp ins + local ins ops="$PREFIX$SUFFIX" - if [[ -z $compstate[old_list] ]]; then - comp=() + unfunction _all_labels _next_label + + _all_labels() { + local gopt=-J len tmp pre suf ret=1 descr spec + + if [[ "$1" = -([12]|)[VJ] ]]; then + gopt="$1" + shift + fi + + tmp=${argv[(ib:4:)-]} + len=$# + if [[ tmp -lt len ]]; then + pre=$(( tmp-1 )) + suf=$tmp + elif [[ tmp -eq $# ]]; then + pre=-2 + suf=$(( len+1 )) + else + pre=4 + suf=5 + fi + + while comptags -A "$1" curtag spec; do + [[ "$_next_tags_not" = *\ ${spec}\ * ]] && continue + _comp_tags="$_comp_tags $spec " + if [[ "$curtag" = *:* ]]; then + zformat -f descr "${curtag#*:}" "d:$3" + _description "$gopt" "${curtag%:*}" "$2" "$descr" + curtag="${curtag%:*}" + + "$4" "${(P@)2}" "${(@)argv[5,-1]}" + else + _description "$gopt" "$curtag" "$2" "$3" + + "${(@)argv[4,pre]}" "${(P@)2}" "${(@)argv[suf,-1]}" && ret=0 + fi + done + + return ret + } + + _next_label() { + local gopt=-J descr spec + + if [[ "$1" = -([12]|)[VJ] ]]; then + gopt="$1" + shift + fi + + if comptags -A "$1" curtag spec; then + [[ "$_next_tags_not" = *\ ${spec}\ * ]] && continue + _comp_tags="$_comp_tags $spec " + if [[ "$curtag" = *:* ]]; then + zformat -f descr "${curtag#*:}" "d:$3" + _description "$gopt" "${curtag%:*}" "$2" "$descr" + curtag="${curtag%:*}" + eval "${2}=( \${(P)2} \$argv[4,-1] )" + else + _description "$gopt" "$curtag" "$2" "$3" + eval "${2}=( \$argv[4,-1] \${(P)2} )" + fi + + return 0 + fi + + return 1 + } + + if [[ "${LBUFFER%${PREFIX}}" = "$_next_tags_pre" ]]; then + PREFIX="$_next_tags_pfx" + SUFFIX="$_next_tags_sfx" else - comp=(_complete) + _next_tags_pre="${LBUFFER%${PREFIX}}" + if [[ "$LASTWIDGET" = (_next_tags|list-*|*complete*) ]]; then + PREFIX="$_lastcomp[prefix]" + SUFFIX="$_lastcomp[suffix]" + fi fi - (( $+_sort_tags )) || _next_tags_not= - - _sort_tags=_next_tags_sort - _next_tags_pre="${LBUFFER%${PREFIX}}" _next_tags_not="$_next_tags_not $_lastcomp[tags]" + _next_tags_pfx="$PREFIX" + _next_tags_sfx="$SUFFIX" if [[ -n "$compstate[old_insert]" ]]; then - PREFIX="$_lastcomp[prefix]" - SUFFIX="$_lastcomp[suffix]" ins=1 + else + ins=unambiguous fi - _main_complete "$comp[@]" + _main_complete _complete _next_tags_completer - [[ $compstate[insert] = automenu ]] && - compstate[insert]=automenu-unambiguous + [[ $compstate[insert] = automenu ]] && compstate[insert]=automenu-unambiguous + [[ $compstate[insert] = *unambiguous && -n "$ops" && + -z "$_lastcomp[unambiguous]" ]] && compadd -Uns "$SUFFIX" - "$PREFIX" compstate[insert]="$ins" compstate[list]='list force' @@ -34,11 +107,19 @@ _next_tags() { compprefuncs=( "$compprefuncs[@]" _next_tags_pre ) } +# Completer, for wrap-around. + +_next_tags_completer() { + _next_tags_not= + + _complete +} + # Pre-completion function. _next_tags_pre() { - # Probably `remove' our sort function. A better test would be nice, but + # Probably `remove' our label functions. A better test would be nice, but # I think one should still be able to edit the current word between # attempts to complete it. @@ -47,65 +128,10 @@ _next_tags_pre() { compstate[insert]=menu:2 return 0 elif [[ ${LBUFFER%${PREFIX}} != ${_next_tags_pre}* ]]; then - unset _sort_tags + unfunction _all_labels _next_label + autoload -U _all_labels _next_label else compprefuncs=( "$compprefuncs[@]" _next_tags_pre ) - [[ -n "$compstate[old_list]" && -n "$_next_tags_reset" ]] && - _next_tags_not= _next_tags_reset= - fi -} - -# Helper function for sorting tags. Most of this is copied from _tags. - -_next_tags_sort() { - local order tags tag nodef tmp - - zstyle -a ":completion:${curcontext}:" tag-order order || - order=('arguments values' options) - - # But we also remove the tags we've already tried... - - tags=( "${(@)order:#(${(j:|:)~${=_next_tags_not}})(|:*)}" ) - - # ... unless that would remove all offered tags. - - if [[ $funcstack[4] = _files ]]; then - if zstyle -a ":completion:${curcontext}:" file-patterns tmp; then - [[ "$tags" = *${${tmp[-1]##[^\\]:}%:*}* ]] && - tags=( $order ) _next_tags_reset=yes - else - [[ "$tags" = *all-files* ]] && tags=( $order ) _next_tags_reset=yes - fi - else - [[ $#tags -ne $#order && "$tags" != *(${(j:|:)~argv})* ]] && - tags=( $order ) _next_tags_reset=yes - fi - for tag in $tags; do - case $tag in - -) nodef=yes;; - *\(\)) "${${tag%%[ ]#\(\)}##[ ]#}" "$@";; - \!*) comptry "${(@)argv:#(${(j:|:)~${=~tag[2,-1]}})}";; - ?*) comptry -m "$tag";; - esac - done - - if [[ -z "$nodef" ]]; then - if [[ $funcstack[4] = _files ]]; then - if zstyle -a ":completion:${curcontext}:" file-patterns tmp; then - [[ "$argv" = *${${tmp[-1]#*[^\\]:}%:*}* ]] && _next_tags_reset=yes - else - [[ "$argv" = *all-files* ]] && _next_tags_reset=yes - fi - fi - tmp=( "${(@)argv:#(${(j:|:)~${=_next_tags_not}})(|:*)}" ) - - # $prev is set in _tags! - - if [[ -n "$prev" && ( $#tmp -ne 0 || $funcstack[4] = _files ) ]]; then - comptry "$tmp[@]" - else - comptry "$argv[@]" - fi fi } |