#compdef -k complete-word \C-xn # Main widget. _next_tags() { local comp if [[ -z $compstate[old_list] ]]; then comp=() else comp=(_complete) fi (( $+_sort_tags )) || _next_tags_not= _sort_tags=_next_tags_sort _next_tags_pre="${LBUFFER%${PREFIX}}" _next_tags_not="$_next_tags_not $_lastcomp[tags]" _main_complete "$comp[@]" [[ $compstate[insert] = automenu ]] && compstate[insert]=automenu-unambiguous compstate[insert]='' compstate[list]='list force' compprefuncs=( "$compprefuncs[@]" _next_tags_pre ) } # Pre-completion function. _next_tags_pre() { # Probably `remove' our sort function. 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 [[ $_next_tags_pre != ${LBUFFER%${PREFIX}} ]]; then unset _sort_tags else compprefuncs=( "$compprefuncs[@]" _next_tags_pre ) fi } # Helper function for sorting tags. Most of this is copied from _tags. _next_tags_sort() { local order tags tag nodef if ! zstyle -a ":completion:${curcontext}:" tag-order order; then if (( $+_comp_default_tags )); then order=( "$_comp_default_tags[@]" ) else order=( 'arguments values' options ) fi fi # But we also remove the tags we've already tried... tags=( "${(@)order:#(${(j:|:)~${=_next_tags_not}})}" ) # ... unless that would remove all offered tags. [[ $#tags -ne $#order && "$tags" != *(${(j:|:)~argv})* ]] && tags=( $order ) _next_tags_not= for tag in $tags; do case $tag in -) nodef=yes;; *\(\)) "${${tag%%[ ]#\(\)}##[ ]#}" "$@";; \!*) comptry "${(@)argv:#(${(j:|:)~${=tag[2,-1]}})}";; ?*) comptry ${=tag};; esac done [[ -z "$nodef" ]] && comptry "$@" } [[ -o kshautoload ]] || _next_tags "$@"