about summary refs log tree commit diff
path: root/Completion/Commands/_next_tags
diff options
context:
space:
mode:
Diffstat (limited to 'Completion/Commands/_next_tags')
-rw-r--r--Completion/Commands/_next_tags168
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
 }