#compdef -k list-choices \C-xn # Main widget. _next_tags() { eval "$_comp_setup" local ins ops="$PREFIX$SUFFIX" unfunction _all_labels _next_label _all_labels() { local __gopt __len __tmp __pre __suf __ret=1 __descr __spec __prev if [[ "$1" = - ]]; then __prev=- shift fi __gopt=() zparseopts -D -a __gopt 1 2 V J x __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$__prev" "$1" curtag __spec; do (( $#funcstack > _tags_level )) && _comp_tags="${_comp_tags% * }" _tags_level=$#funcstack [[ "$_next_tags_not" = *\ ${__spec}\ * ]] && continue _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]}" && __ret=0 else _description "$__gopt[@]" "$curtag" "$2" "$3" "${(@)argv[4,__pre]}" "${(P@)2}" "${(@)argv[__suf,-1]}" && __ret=0 fi done return __ret } _next_label() { local __gopt __descr __spec __gopt=() zparseopts -D -a __gopt 1 2 V J x if comptags -A "$1" curtag __spec; then (( $#funcstack > _tags_level )) && _comp_tags="${_comp_tags% * }" _tags_level=$#funcstack [[ "$_next_tags_not" = *\ ${__spec}\ * ]] && continue _comp_tags+=" $__spec " if [[ "$curtag" = *[^\\]:* ]]; then zformat -f __descr "${curtag#*:}" "d:$3" _description "$__gopt[@]" "${curtag%:*}" "$2" "$__descr" curtag="${curtag%:*}" set -A $2 "${(P@)2}" "${(@)argv[4,-1]}" else _description "$__gopt[@]" "$curtag" "$2" "$3" set -A $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 _next_tags_pre="${LBUFFER%${PREFIX}}" if [[ "$LASTWIDGET" = (_next_tags|list-*|*complete*) ]]; then PREFIX="$_lastcomp[prefix]" SUFFIX="$_lastcomp[suffix]" fi fi _next_tags_not+=" $_lastcomp[tags]" _next_tags_pfx="$PREFIX" _next_tags_sfx="$SUFFIX" ins="${compstate[old_insert]:+1}" _main_complete _complete _next_tags_completer [[ $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' compprefuncs+=( _next_tags_pre ) } # Completer, for wrap-around. _next_tags_completer() { _next_tags_not= _complete } # Pre-completion function. _next_tags_pre() { # 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. if [[ -n $compstate[old_insert] && $WIDGET != _next_tags ]]; then compstate[old_list]=keep compstate[insert]=menu:2 return 0 elif [[ ${LBUFFER%${PREFIX}} != ${_next_tags_pre}* ]]; then unfunction _all_labels _next_label autoload -Uz _all_labels _next_label else compprefuncs+=( _next_tags_pre ) fi } _next_tags "$@"