#compdef -k complete-word \C-xn # Main widget. _next_tags() { eval "$_comp_setup" local ins ops="$PREFIX$SUFFIX" 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%:*}" 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="$_next_tags_not $_lastcomp[tags]" _next_tags_pfx="$PREFIX" _next_tags_sfx="$SUFFIX" if [[ -n "$compstate[old_insert]" ]]; then ins=1 else ins=unambiguous fi _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=( "$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 -U _all_labels _next_label else compprefuncs=( "$compprefuncs[@]" _next_tags_pre ) fi } _next_tags "$@"