about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTanaka Akira <akr@users.sourceforge.net>1999-11-03 13:47:39 +0000
committerTanaka Akira <akr@users.sourceforge.net>1999-11-03 13:47:39 +0000
commit97f02ffe63909c84cb9771d20a73ebec55f49589 (patch)
tree997db6027bc486992bdab800ed53404512446919
parent3eeb83f1a0a01a16f137cef2dfc2c9d8c1626875 (diff)
downloadzsh-97f02ffe63909c84cb9771d20a73ebec55f49589.tar.gz
zsh-97f02ffe63909c84cb9771d20a73ebec55f49589.tar.xz
zsh-97f02ffe63909c84cb9771d20a73ebec55f49589.zip
zsh-workers/8520
-rw-r--r--Completion/Base/_arguments176
-rw-r--r--Completion/Base/_describe35
-rw-r--r--Completion/Base/_values13
-rw-r--r--Completion/Builtins/_kill23
-rw-r--r--Completion/Builtins/_wait22
-rw-r--r--Completion/Core/_files54
-rw-r--r--Completion/Core/_main_complete17
-rw-r--r--Completion/Core/_tags81
-rw-r--r--Completion/Core/compinit76
9 files changed, 340 insertions, 157 deletions
diff --git a/Completion/Base/_arguments b/Completion/Base/_arguments
index ca8f42c61..04d588c49 100644
--- a/Completion/Base/_arguments
+++ b/Completion/Base/_arguments
@@ -154,122 +154,127 @@ fi
 if comparguments -i "$compconfig[autodescribe_options]" "$@"; then
   local nm="$compstate[nmatches]" action noargs aret expl local
   local next direct odirect equal single match matched ws tmp1 tmp2
+  local prios tags opts
 
-  if ! comparguments -D descr action; then
+  if comparguments -D descr action; then
+    if comparguments -O next direct odirect equal; then
+      opts=yes
+      _tags -f "$funcstack[2]" argument option
+    else
+      _tags -f "$funcstack[2]" argument
+    fi
+  else
     if comparguments -a; then
       noargs='no more arguments'
     else
       noargs='no arguments'
     fi
-  fi
+    comparguments -O next direct odirect equal || return 1
 
-  while true; do
+    opts=yes
+    _tags -f "$funcstack[2]" option
+  fi
 
-    if [[ -z "$noargs" || -n "$matched" ]]; then
-      _description expl "$descr"
+  while _tags; do
+    while true; do
+      if [[ "$tags" = *:argument* ]]; then
+        _description expl "$descr"
 
-      if [[ "$action" = -\>* ]]; then
-        comparguments -W line opt_args
-        state="${${action[3,-1]##[ 	]#}%%[ 	]#}"
-        compstate[restore]=''
-        aret=yes
-      else
-        if [[ -z "$local" ]]; then
-          local line
-          typeset -A opt_args
-          local=yes
-        fi
+        if [[ "$action" = -\>* ]]; then
+          comparguments -W line opt_args
+          state="${${action[3,-1]##[ 	]#}%%[ 	]#}"
+          compstate[restore]=''
+          aret=yes
+        else
+          if [[ -z "$local" ]]; then
+            local line
+            typeset -A opt_args
+            local=yes
+          fi
 
-        comparguments -W line opt_args
+          comparguments -W line opt_args
 
-        if [[ "$action" = \ # ]]; then
+          if [[ "$action" = \ # ]]; then
 
-          # An empty action means that we should just display a message.
+            # An empty action means that we should just display a message.
 
-          [[ -n "$matched" ]] && compadd -n -Q -S '' -s "$SUFFIX" - "$PREFIX"
-          mesg="$descr"
+            [[ -n "$matched" ]] && compadd -n -Q -S '' -s "$SUFFIX" - "$PREFIX"
+            mesg="$descr"
 
-        elif [[ "$action" = \(\(*\)\) ]]; then
+          elif [[ "$action" = \(\(*\)\) ]]; then
 
-          # ((...)) contains literal strings with descriptions.
+            # ((...)) contains literal strings with descriptions.
 
-          eval ws\=\( "${action[3,-3]}" \)
+            eval ws\=\( "${action[3,-3]}" \)
 
-          _describe -c "$cmd" "$descr" ws -M "$match"
+            _describe -c "$cmd" -f "$funcstack[2]" "$descr" ws -M "$match"
 
-        elif [[ "$action" = \(*\) ]]; then
+          elif [[ "$action" = \(*\) ]]; then
 
-          # Anything inside `(...)' is added directly.
+            # Anything inside `(...)' is added directly.
 
-          compadd "$expl[@]" - ${=action[2,-2]}
-        elif [[ "$action" = \{*\} ]]; then
+            compadd "$expl[@]" - ${=action[2,-2]}
+          elif [[ "$action" = \{*\} ]]; then
 
-          # A string in braces is evaluated.
+            # A string in braces is evaluated.
 
-          eval "$action[2,-2]"
+            eval "$action[2,-2]"
 
-        elif [[ "$action" = \ * ]]; then
+          elif [[ "$action" = \ * ]]; then
 
-          # If the action starts with a space, we just call it.
+            # If the action starts with a space, we just call it.
 
-          ${(e)=~action}
-        else
+            ${(e)=~action}
+          else
 
-          # Otherwise we call it with the description-arguments built above.
+            # Otherwise we call it with the description-arguments built above.
 
-          action=( $=action )
-          ${(e)action[1]} "$expl[@]" ${(e)~action[2,-1]}
+            action=( $=action )
+            ${(e)action[1]} "$expl[@]" ${(e)~action[2,-1]}
+          fi
         fi
       fi
-    fi
-
-    if [[ -z "$matched" ]] &&
-       comparguments -O next direct odirect equal &&
-       [[ ( ( nm -eq compstate[nmatches] || -n "$noargs" ) &&
-            -z "$aret" && -z "$mesg" ) ||
-          -z "$compconfig[option_prefix]" || 
-          "$compconfig[option_prefix]" = *\!${cmd}* ||
-          "$PREFIX" = [-+]* ]]; then
-
-      comparguments -M match
-
-      if comparguments -s single; then
-
-        _description expl option
-
-        if [[ "$single" = direct ]]; then
-	  compadd "$expl[@]" -QS '' - "${PREFIX}${SUFFIX}"
-        elif [[ "$single" = next ]]; then
-	  compadd "$expl[@]" -Q - "${PREFIX}${SUFFIX}"
-        elif [[ "$single" = equal ]]; then
-	  compadd "$expl[@]" -QqS= - "${PREFIX}${SUFFIX}"
+      if [[ "$tags" = *:option* &&
+            ( "$tags" != *\[*prefix*\]* || "$PREFIX" = [-+]* ) ]]; then
+        comparguments -M match
+
+        if comparguments -s single; then
+
+          _description expl option
+
+          if [[ "$single" = direct ]]; then
+	    compadd "$expl[@]" -QS '' - "${PREFIX}${SUFFIX}"
+          elif [[ "$single" = next ]]; then
+	    compadd "$expl[@]" -Q - "${PREFIX}${SUFFIX}"
+          elif [[ "$single" = equal ]]; then
+	    compadd "$expl[@]" -QqS= - "${PREFIX}${SUFFIX}"
+          else
+	    tmp1=( "$next[@]" "$direct[@]" "$odirect[@]" "$equal[@]" )
+	    tmp1=( "${(M@)tmp1:#[-+]?(|:*)}" )
+	    tmp2=( "${PREFIX}${(@M)^${(@)${(@)tmp1%%:*}#[-+]}:#?}" )
+
+            _describe -o -c "$cmd" -f "$funcstack[2]" option \
+                      tmp1 tmp2 -Q -S ''
+          fi
+          single=yes
         else
-	  tmp1=( "$next[@]" "$direct[@]" "$odirect[@]" "$equal[@]" )
-	  tmp1=( "${(M@)tmp1:#[-+]?(|:*)}" )
-	  tmp2=( "${PREFIX}${(@M)^${(@)${(@)tmp1%%:*}#[-+]}:#?}" )
-
-          _describe -o -c "$cmd" option tmp1 tmp2 -Q -S ''
+          next=( "$next[@]" "$odirect[@]" )
+          _describe -o -c "$cmd" -f "$funcstack[2]" option \
+            next -Q -M "$match" -- \
+            direct -QS '' -M "$match" -- \
+            equal -QqS= -M "$match"
         fi
-        single=yes
-      else
-        next=( "$next[@]" "$odirect[@]" )
-        _describe -o -c "$cmd" option \
-          next -Q -M "$match" -- \
-          direct -QS '' -M "$match" -- \
-          equal -QqS= -M "$match"
       fi
-
-      if [[ nm -eq compstate[nmatches] && -z "$aret" &&
-            ( ( -z "$single" && "$PREFIX" = [-+]*\=* ) ||
-              "$PREFIX" = --* ) ]]; then
+      if [[ -n "$opts" && -z "$aret$matched" && nm -ne compstate[nmatches] &&
+            "$tags" = *:argument* ]]; then
 
         local prefix suffix
 
-	prefix="${PREFIX#*\=}"
-	suffix="$SUFFIX"
-	PREFIX="${PREFIX%%\=*}"
-	SUFFIX=''
-	compadd -M "$match" -D equal - "${(@)equal%%:*}"
+        prefix="${PREFIX#*\=}"
+        suffix="$SUFFIX"
+        PREFIX="${PREFIX%%\=*}"
+        SUFFIX=''
+        compadd -M "$match" -D equal - "${(@)equal%%:*}"
 
         if [[ $#equal -eq 1 ]]; then
 	  PREFIX="$prefix"
@@ -277,11 +282,13 @@ if comparguments -i "$compconfig[autodescribe_options]" "$@"; then
 	  IPREFIX="${IPREFIX}${equal[1]%%:*}="
 	  matched=yes
 	  comparguments -L "$equal[1]" descr action
+	  tags=argument
 	  continue
-	fi
+        fi
       fi
-    fi
-    break
+      break
+    done
+    [[ -n "$aret" || nm -ne compstate[nmatches] ]] && break
   done
 
   [[ -n "$aret" ]] && return 300
@@ -292,7 +299,6 @@ if comparguments -i "$compconfig[autodescribe_options]" "$@"; then
   # Set the return value.
 
   [[ nm -ne "$compstate[nmatches]" ]]
-
 else
   return 1
 fi
diff --git a/Completion/Base/_describe b/Completion/Base/_describe
index e59dc1593..5355e4d7f 100644
--- a/Completion/Base/_describe
+++ b/Completion/Base/_describe
@@ -2,15 +2,19 @@
 
 # This can be used to add options or values with descriptions as matches.
 
-local isopt cmd opt expl tmps tmpd tmpmd tmpms ret=1 showd _nm hide
+local cmd func opt expl tmps tmpd tmpmd tmpms ret=1 showd _nm hide
+local prios tags type=value
 
 cmd="$words[1]"
+func="$funcstack[2]"
 
 # Get the options.
 
-while getopts 'oc:' opt; do
+while getopts 'oc:f:' opt; do
   if [[ "$opt" = o ]]; then
-    isopt=yes
+    type=option
+  elif [[ "$opt" = f ]]; then
+    func="$OPTARG"
   else
     cmd="$OPTARG"
   fi
@@ -19,28 +23,11 @@ shift OPTIND-1
 
 # Do the tests. `showd' is set if the descriptions should be shown.
 
-if [[ -n "$isopt" ]]; then
+_tags -c "$cmd" -f "$func" "$type"
 
-  # We take the value to test the number of matches from a non-local
-  # parameter `nm' if that exists and contains only digits. It's a hack.
+_tags || return 1
 
-  if [[ "$nm" = [0-9]## ]]; then
-    _nm="$nm"
-  else
-    _nm=0
-  fi
-  [[ -n "$compconfig[option_prefix]" &&
-     "$compconfig[option_prefix]" != *\!${cmd}* &&
-     "$PREFIX" != [-+]* &&
-     ( "$compconfig[option_prefix]" = *nodefault* ||
-       _nm -ne compstate[nmatches] ) ]] && return 1
-
-  [[ -n "$compconfig[describe_options]" &&
-     "$compconfig[describe_options]" != *\!${cmd}* ]] && showd=yes
-else
-  [[ -n "$compconfig[describe_values]" &&
-     "$compconfig[describe_values]" != *\!${cmd}* ]] && showd=yes
-fi
+[[ "$tags" = *:${type}\[*describe*\]* ]] && showd=yes
 
 _description expl "$1"
 shift
@@ -51,7 +38,7 @@ else
   compdescribe -i "$@"
 fi
 
-[[ -n "$isopt" && "$compconfig[option_prefix]" = hide* ]] && hide=yes
+[[ "$type" = option && "$tags" = *:option\[*hide*\]* ]] && hide=yes
 
 while compdescribe -g args tmpd tmpmd tmps tmpms; do
 
diff --git a/Completion/Base/_values b/Completion/Base/_values
index e4ef8af68..34a5c4097 100644
--- a/Completion/Base/_values
+++ b/Completion/Base/_values
@@ -2,9 +2,13 @@
 
 if compvalues -i "$@"; then
 
-  local noargs args opts descr action expl sep
+  local tags prios noargs args opts descr action expl sep
 
   if ! compvalues -D descr action; then
+
+    _tags value
+    _tags || return 1
+
     compvalues -V noargs args opts
 
     if [[ "$PREFIX" = *\=* ]]; then
@@ -39,7 +43,7 @@ if compvalues -i "$@"; then
         sep=()
       fi
 
-      _describe "$descr" \
+      _describe -f "$funcstack[2]" "$descr" \
         noargs "$sep[@]" -M 'r:|[_-]=* r:|=*' -- \
         args -S= -M 'r:|[_-]=* r:|=*' -- \
         opts -qS= -M 'r:|[_-]=* r:|=*'
@@ -48,6 +52,9 @@ if compvalues -i "$@"; then
     fi
   fi
 
+  _tags argument
+  _tags || return 1
+
   _description expl "$descr"
 
   # We add the separator character as a autoremovable suffix unless
@@ -80,7 +87,7 @@ if compvalues -i "$@"; then
 
       eval ws\=\( "${action[3,-3]}" \)
 
-      _describe "$descr" ws -M 'r:|[_-]=* r:|=*'
+      _describe -f "$funcstack[2]" "$descr" ws -M 'r:|[_-]=* r:|=*'
 
     elif [[ "$action" = \(*\) ]]; then
 
diff --git a/Completion/Builtins/_kill b/Completion/Builtins/_kill
index 2af168f3f..a3efbef41 100644
--- a/Completion/Builtins/_kill
+++ b/Completion/Builtins/_kill
@@ -6,14 +6,21 @@ if compset -P 1 -; then
   _description expl signal
   compadd "$expl[@]" $signals[1,-3]
 else
-  local ret=1
-
-  _jobs && ret=0
-
-  list=("${(@M)${(f@)$(ps ${=compconfig[ps_listargs]:-$=compconfig[ps_args]} 2>/dev/null)}[2,-1]:#[ 	]#${PREFIX}[0-9]#${SUFFIX}[ 	]*}")
-  _description expl 'process ID'
-  compadd "$expl[@]" -ld list - ${${${(f)"$(ps $=compconfig[ps_args] 2>/dev/null)"}[2,-1]## #}%% *} &&
-    ret=0
+  local prios tags ret=1
+  
+  _tags job process
+  
+  while _tags; do
+    [[ "$tags" = *:job:* ]] && _jobs && ret=0
+    if [[ "$tags" = *:process:* ]]; then
+      list=("${(@M)${(f@)$(ps ${=compconfig[ps_listargs]:-$=compconfig[ps_args]} 2>/dev/null)}[2,-1]:#[ 	]#${PREFIX}[0-9]#${SUFFIX}[ 	]*}")
+      _description expl 'process ID'
+      compadd "$expl[@]" -ld list - \
+        ${${${(f)"$(ps $=compconfig[ps_args] 2>/dev/null)"}[2,-1]## #}%% *} &&
+          ret=0
+    fi
+    (( ret )) || break
+  done
 
   return ret
 fi
diff --git a/Completion/Builtins/_wait b/Completion/Builtins/_wait
index b659532e7..0f096355f 100644
--- a/Completion/Builtins/_wait
+++ b/Completion/Builtins/_wait
@@ -1,11 +1,19 @@
 #compdef wait
 
-local list ret=1 expl
-
-_jobs && ret=0
-
-list=("${(@M)${(f)$(ps ${=compconfig[ps_listargs]:-$=compconfig[ps_args]} 2>/dev/null)}[2,-1]:#[ 	]#${PREFIX}[0-9]#${SUFFIX}[ 	]*}")
-_description expl 'process ID'
-compadd "$expl[@]" -ld list - ${${${(f)"$(ps $=compconfig[ps_args] 2>/dev/null)"}[2,-1]## #}%% *} && ret=0
+local prios tags list ret=1 expl
+  
+_tags job process
+  
+while _tags; do
+  [[ "$tags" = *:job:* ]] && _jobs && ret=0
+  if [[ "$tags" = *:process:* ]]; then
+    list=("${(@M)${(f@)$(ps ${=compconfig[ps_listargs]:-$=compconfig[ps_args]} 2>/dev/null)}[2,-1]:#[ 	]#${PREFIX}[0-9]#${SUFFIX}[ 	]*}")
+    _description expl 'process ID'
+    compadd "$expl[@]" -ld list - \
+      ${${${(f)"$(ps $=compconfig[ps_args] 2>/dev/null)"}[2,-1]## #}%% *} &&
+        ret=0
+  fi
+  (( ret )) || break
+done
 
 return ret
diff --git a/Completion/Core/_files b/Completion/Core/_files
index 38eafd196..e667289c5 100644
--- a/Completion/Core/_files
+++ b/Completion/Core/_files
@@ -1,31 +1,27 @@
 #autoload
 
-# Utility function for completing files of a given type or any file.
-# In many cases you will want to call this one instead of `_path_files'.
-
-local nm=$compstate[nmatches] ret=1
-
-_path_files "$@" && ret=0
-
-if [[ $# -ne 0 && compstate[nmatches] -eq nm ]]; then
-  local opt opts
-
-  # We didn't get any matches for those types of files described by
-  # the `-g' or `-/' option. Now we try it again accepting all files.
-  # First we get those options that we have to use even then. If we
-  # find out that the `-f' option was given, we already accepted all
-  # files and give up immediatly.
-
-  opts=()
-  while getopts "P:S:qr:R:W:F:J:V:X:f/g:M:" opt; do
-    case "$opt" in
-    f)            return;;
-    [PSrRWFJVXM]) opts=("$opts[@]" "-$opt" "$OPTARG");;
-    q)            opts=("$opts[@]" -q);;
-    esac
-  done
-
-  _path_files "$opts[@]" && ret=0
-fi
-
-return ret
+local opts opt type=file prios tags
+
+opts=()
+while getopts "P:S:qr:R:W:F:J:V:X:f/g:M:" opt; do
+  case "$opt" in
+  /)    [[ "$type" = file       ]] && type=dir       ;;
+  g)    [[ "$type" = (file|dir) ]] && type="$OPTARG" ;;
+  q)    opts=("$opts[@]" -q               )          ;;
+  [^f]) opts=("$opts[@]" "-$opt" "$OPTARG")          ;;
+  esac
+done
+
+case "$type" in
+file) _tags -f "$funcstack[2]" file           ;;
+dir)  _tags -f "$funcstack[2]" path file      ;;
+*)    _tags -f "$funcstack[2]" glob path file ;;
+esac
+
+while _tags; do
+  [[ "$tags" = *:file:* ]] && { _path_files "$opts[@]" -f         ;  return   }
+  [[ "$tags" = *:path:* ]] &&   _path_files "$opts[@]" -/         && return 0
+  [[ "$tags" = *:glob:* ]] &&   _path_files "$opts[@]" -g "$type" && return 0
+done
+
+return 1
diff --git a/Completion/Core/_main_complete b/Completion/Core/_main_complete
index 72233a59b..877a975b3 100644
--- a/Completion/Core/_main_complete
+++ b/Completion/Core/_main_complete
@@ -17,7 +17,12 @@
 # state than the global one for which you are completing.
 
 
-local comp post ret=1 _compskip
+local comp post ret=1 _compskip prios tags
+typeset -U _offered_tags _tried_tags _failed_tags _used_tags _unused_tags
+
+_offered_tags=()
+_tried_tags=()
+_failed_tags=()
 
 typeset -U _lastdescr
 
@@ -46,6 +51,11 @@ for comp; do
   fi
 done
 
+# See which tags were or were not used.
+
+_used_tags=( "${(@)_tried_tags:#${(j:|:)~${(@)_failed_tags//\[/\\[}//\]/\\]}}" )
+_unused_tags=( "${(@)_offered_tags:#${(j:|:)~${(@)_used_tags//\[/\\[}//\]/\\]}}" )
+
 # Now call the post-functions.
 
 for post in "$comppostfuncs[@]"; do
@@ -82,5 +92,10 @@ _lastcomp[iprefix]="$IPREFIX"
 _lastcomp[isuffix]="$ISUFFIX"
 _lastcomp[qiprefix]="$QIPREFIX"
 _lastcomp[qisuffix]="$QISUFFIX"
+_lastcomp[offered_tags]="${(j.:.)_offered_tags}"
+_lastcomp[tried_tags]="${(j.:.)_tried_tags}"
+_lastcomp[failed_tags]="${(j.:.)_failed_tags}"
+_lastcomp[unused_tags]="${(j.:.)_unused_tags}"
+_lastcomp[used_tags]="${(j.:.)_used_tags}"
 
 return ret
diff --git a/Completion/Core/_tags b/Completion/Core/_tags
new file mode 100644
index 000000000..af8dc21dd
--- /dev/null
+++ b/Completion/Core/_tags
@@ -0,0 +1,81 @@
+#autoload
+
+if (( $# )); then
+  local cmd="$words[1]" func="$funcstack[2]" defs i tags tag pat style prio
+
+  while getopts 'c:f:' i; do
+    if [[ "$i" = c ]]; then
+      cmd="$OPTARG"
+    else
+      func="$OPTARG"
+    fi
+  done
+
+  shift OPTIND-1
+
+  defs=( "${(@M)argv:#${(kj:|:)~override_tags[(R)(|+*)]}}" )
+  (( $#defs )) && set -- "$defs[@]"
+
+  _offered_tags=( "$_offered_tags[@]" "$@" )
+  _last_tags=()
+
+  defs=()
+  for i; do
+    if [[ -n ${override_tags[$i]} && ${override_tags[$i]} != (\[|+\[)* ]]; then
+      if [[ ${override_tags[$i]} = *\[* ]]; then
+        prio=( "${i}:*=${override_tags[$i]#+}" )
+      else
+        prio=( "${i}:${(@v)^comptags[(I)(|*:)${i}(|:*)]}" )
+        (( $#prio )) || prio=( "${i}:${comptags[any]}" )
+        prio="${${${prio[(r)(|*:)\*=[^:]#\[*\](|:*)]}##(|*:)\*}%%:*}"
+        prio=( "${i}:*=${override_tags[$i]#+}${(M)prio%%\[*\]}" )
+      fi
+    else
+      prio=( "${i}:${(@v)^comptags[(I)(|*:)${i}(|:*)]}" )
+      (( $#prio )) || prio=( "${i}:${comptags[any]}" )
+    fi
+    defs=( "$defs[@]" "$prio[@]" )
+  done
+
+  tags=()
+  for i in "$defs[@]"; do
+    tag="${i%%:*}"
+    for pat in "${(s.:.)i#*:}"; do
+      if [[ ( "$pat" = _* && "$func" = ${~pat%%\=*} ) ||
+            "$cmd" = ${~pat%%\=*} ]]; then
+        prio="${pat#*\=}"
+	[[ "$prio" = -* ]] && continue 2
+
+	if [[ "$prio" = *\[*\] ]]; then
+	  style="${(M)prio%%\[*}"
+	  prio="${prio%%\[*}"
+        else
+	  style=''
+        fi
+	[[ ${override_tags[$tag]} = (|+)\[* ]] &&
+	    style="${override_tags[$tag]#+}"
+
+	(( prio++ ))
+
+        tags[$prio]="${tags[$prio]}:${tag}${style}"
+        break
+      fi
+    done
+  done
+
+  prios=( "${(@)tags:#}" )
+
+  return 0
+fi
+
+_failed_tags=( "$_failed_tags[@]" "$_last_tags[@]" )
+
+(( $#prios )) || return 1
+
+tags="${prios[1]}:"
+shift 1 prios
+
+_last_tags=( "${(@s.:.)${${tags#:}%:}}" )
+_tried_tags=( "$_tried_tags[@]" "$_last_tags[@]" )
+
+return 0
diff --git a/Completion/Core/compinit b/Completion/Core/compinit
index 3569014c6..3d316fac8 100644
--- a/Completion/Core/compinit
+++ b/Completion/Core/compinit
@@ -108,6 +108,14 @@ fi
   compconfig[correct_prompt]='correct to:'
 (( ${+compconfig[completer]} )) || compconfig[completer]=_complete
 
+# This holds the tag/priority definitions.
+
+typeset -gA comptags
+
+(( ${+comptags[any]} )) || comptags[any]='*=100'
+
+typeset -gA override_tags
+
 # This can hold names of functions that are to be called after all
 # matches have been generated.
 
@@ -370,6 +378,74 @@ compconf() {
   fi
 }
 
+# Function to set tags and priorities.
+
+comptag() {
+  local i opt list tag val
+
+  while getopts "lL" opt; do
+    if [[ "$opt" = l ]]; then
+      [[ -z "$list" ]] && list=yes
+    else
+      list=long
+    fi
+  done
+  shift OPTIND-1
+
+  if (( $# )); then
+    if [[ -n $list ]]; then
+      for i; do
+        if [[ $list = long ]]; then
+	  (( ${+comptags[$i]} )) && print "comptag $i='$comptags[$i]'"
+	else
+          print $comptags[$i]
+	fi
+      done
+    else
+      for i; do
+        tag="${i%%([-+]|)\=*}"
+	val="${${i#*(|[-+])\=}#+}"
+        case "$i" in
+	*+\=*)
+	  if [[ -n "$comptags[$tag]" ]]; then
+	    comptags[$tag]="${val}:${comptags[$tag]}"
+	  else
+	    comptags[$tag]="$val"
+          fi
+	  ;;
+	*\=+*)
+	  if [[ -n "$comptags[$tag]" ]]; then
+	    comptags[$tag]="${comptags[$tag]}:${val}"
+	  else
+	    comptags[$tag]="$val"
+          fi
+	  ;;
+	*-\=*)
+	  if [[ -n "$comptags[$tag]" ]]; then
+	    comptags[$tag]="${${${comptags[$tag]//:${val}\=[^:]##}#${val}\=*:}%:${val}\=[^:]##}"
+	    [[ "$comptags[$tag]" = ${val}\=* ]] && unset "comptags[$tag]"
+          fi
+          ;;
+        *\=*)
+          comptags[${i%%\=*}]="${i#*\=}"
+	  ;;
+        *)
+          unset "compconfig[$i]"
+	  ;;
+        esac
+      done
+    fi
+  else
+    for i in ${(ok)comptags}; do
+      if [[ $list = long ]]; then
+	print "comptag $i='$comptags[$i]'"
+      else
+        print ${(r:25:)i} "$comptags[$i]"
+      fi
+    done
+  fi
+}
+
 # Utility function to call a function if it exists.
 #
 # Usage: funcall <return> <name> [ <args> ... ]