summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Completion/Base/Widget/_next_tags140
1 files changed, 140 insertions, 0 deletions
diff --git a/Completion/Base/Widget/_next_tags b/Completion/Base/Widget/_next_tags
new file mode 100644
index 000000000..29196a14d
--- /dev/null
+++ b/Completion/Base/Widget/_next_tags
@@ -0,0 +1,140 @@
+#compdef -k complete-word \C-xn
+
+# Main widget.
+
+_next_tags() {
+ setopt localoptions ${_comp_options[@]}
+
+ 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 "$@"