about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTanaka Akira <akr@users.sourceforge.net>2000-03-23 04:19:26 +0000
committerTanaka Akira <akr@users.sourceforge.net>2000-03-23 04:19:26 +0000
commit626e2aeb1657f112feb6d03c34bb9e9f44764c75 (patch)
tree9e4a306df7b5826a796b99f0b6ffa3423ee9f5f9
parent766fcd5ee2ef632cd982a1ec118dbdfde17c03a8 (diff)
downloadzsh-626e2aeb1657f112feb6d03c34bb9e9f44764c75.tar.gz
zsh-626e2aeb1657f112feb6d03c34bb9e9f44764c75.tar.xz
zsh-626e2aeb1657f112feb6d03c34bb9e9f44764c75.zip
zsh-workers/10195
-rw-r--r--Completion/Base/_arguments22
-rw-r--r--Completion/Base/_brace_parameter2
-rw-r--r--Completion/Base/_condition4
-rw-r--r--Completion/Base/_default2
-rw-r--r--Completion/Base/_describe47
-rw-r--r--Completion/Base/_first2
-rw-r--r--Completion/Base/_jobs14
-rw-r--r--Completion/Base/_math2
-rw-r--r--Completion/Base/_parameter2
-rw-r--r--Completion/Base/_subscript26
-rw-r--r--Completion/Base/_tilde9
-rw-r--r--Completion/Base/_values11
-rw-r--r--Completion/Builtins/_arrays3
-rw-r--r--Completion/Builtins/_autoload3
-rw-r--r--Completion/Builtins/_bindkey6
-rw-r--r--Completion/Builtins/_builtin3
-rw-r--r--Completion/Builtins/_cd3
-rw-r--r--Completion/Builtins/_command3
-rw-r--r--Completion/Builtins/_compdef20
-rw-r--r--Completion/Builtins/_echotc5
-rw-r--r--Completion/Builtins/_functions3
-rw-r--r--Completion/Builtins/_hash9
-rw-r--r--Completion/Builtins/_limits3
-rw-r--r--Completion/Builtins/_pids7
-rw-r--r--Completion/Builtins/_popd5
-rw-r--r--Completion/Builtins/_sched6
-rw-r--r--Completion/Builtins/_signals7
-rw-r--r--Completion/Builtins/_stat8
-rw-r--r--Completion/Builtins/_vars6
-rw-r--r--Completion/Builtins/_zftp29
-rw-r--r--Completion/Builtins/_zle6
-rw-r--r--Completion/Builtins/_zmodload8
-rw-r--r--Completion/Builtins/_zpty6
-rw-r--r--Completion/Builtins/_zstyle61
-rw-r--r--Completion/Commands/_next_tags9
-rw-r--r--Completion/Core/_alternative10
-rw-r--r--Completion/Core/_files126
-rw-r--r--Completion/Core/_main_complete5
-rw-r--r--Completion/Core/_multi_parts2
-rw-r--r--Completion/Core/_options5
-rw-r--r--Completion/Core/_parameters8
-rw-r--r--Completion/Core/_path_files18
-rw-r--r--Completion/Core/_requested25
-rw-r--r--Completion/Core/_sep_parts2
-rw-r--r--Completion/Core/_set_options5
-rw-r--r--Completion/Core/_setup40
-rw-r--r--Completion/Core/_tags28
-rw-r--r--Completion/Core/_unset_options5
-rw-r--r--Completion/Core/_wanted25
-rw-r--r--Completion/Debian/_apt14
-rw-r--r--Completion/Debian/_deb_packages2
-rw-r--r--Completion/Linux/_rpm12
-rw-r--r--Completion/User/_archie2
-rw-r--r--Completion/User/_cvs27
-rw-r--r--Completion/User/_dd9
-rw-r--r--Completion/User/_domains4
-rw-r--r--Completion/User/_gcc4
-rw-r--r--Completion/User/_gdb22
-rw-r--r--Completion/User/_getconf37
-rw-r--r--Completion/User/_gprof2
-rw-r--r--Completion/User/_groups4
-rw-r--r--Completion/User/_gs13
-rw-r--r--Completion/User/_hosts4
-rw-r--r--Completion/User/_lp14
-rw-r--r--Completion/User/_mailboxes15
-rw-r--r--Completion/User/_make14
-rw-r--r--Completion/User/_man4
-rw-r--r--Completion/User/_mh31
-rw-r--r--Completion/User/_mount4
-rw-r--r--Completion/User/_mutt2
-rw-r--r--Completion/User/_mysql_utils20
-rw-r--r--Completion/User/_netscape33
-rw-r--r--Completion/User/_nslookup6
-rw-r--r--Completion/User/_pbm13
-rw-r--r--Completion/User/_perl_basepods3
-rw-r--r--Completion/User/_perl_builtin_funcs3
-rw-r--r--Completion/User/_perl_modules2
-rw-r--r--Completion/User/_ports2
-rw-r--r--Completion/User/_rcs2
-rw-r--r--Completion/User/_rlogin6
-rw-r--r--Completion/User/_socket9
-rw-r--r--Completion/User/_ssh28
-rw-r--r--Completion/User/_stty21
-rw-r--r--Completion/User/_tar3
-rw-r--r--Completion/User/_telnet12
-rw-r--r--Completion/User/_tiff9
-rw-r--r--Completion/User/_urls85
-rw-r--r--Completion/User/_user_at_host8
-rw-r--r--Completion/User/_users6
-rw-r--r--Completion/User/_users_on6
-rw-r--r--Completion/User/_whois8
-rw-r--r--Completion/User/_yp11
-rw-r--r--Completion/X/_x_color4
-rw-r--r--Completion/X/_x_cursor4
-rw-r--r--Completion/X/_x_display2
-rw-r--r--Completion/X/_x_extension8
-rw-r--r--Completion/X/_x_font4
-rw-r--r--Completion/X/_x_keysym5
-rw-r--r--Completion/X/_x_modifier4
-rw-r--r--Completion/X/_x_window9
-rw-r--r--Completion/X/_xmodmap9
-rw-r--r--Completion/X/_xutils19
-rw-r--r--Doc/Zsh/compsys.yo226
-rw-r--r--Doc/Zsh/mod_zutil.yo3
-rw-r--r--Etc/completion-style-guide134
-rw-r--r--Functions/Zftp/zfcd_match3
-rw-r--r--Functions/Zftp/zfget_match6
-rw-r--r--Src/Modules/zutil.c2
-rw-r--r--Src/Zle/computil.c66
109 files changed, 945 insertions, 765 deletions
diff --git a/Completion/Base/_arguments b/Completion/Base/_arguments
index 472f085d5..9a133617c 100644
--- a/Completion/Base/_arguments
+++ b/Completion/Base/_arguments
@@ -4,7 +4,7 @@
 # descriptions given as arguments to this function.
 
 local long cmd="$words[1]" descr mesg subopts opt usecc autod
-local oldcontext="$curcontext"
+local oldcontext="$curcontext" hasopts
 
 long=$argv[(I)--]
 if (( long )); then
@@ -230,35 +230,39 @@ if (( $# )) && comparguments -i "$autod" "$@"; then
 
             # Anything inside `(...)' is added directly.
 
-            compadd "$subopts[@]" "$expl[@]" - ${=action[2,-2]}
+            _loop arguments expl "$descr" \
+                compadd "$subopts[@]" - ${=action[2,-2]}
           elif [[ "$action" = \{*\} ]]; then
 
             # A string in braces is evaluated.
 
-            eval "$action[2,-2]"
+            _loop arguments expl "$descr" eval "$action[2,-2]"
 
           elif [[ "$action" = \ * ]]; then
 
             # If the action starts with a space, we just call it.
 
 	    eval "action=( $action )"
-            "$action[@]"
+            _loop arguments expl "$descr" "$action[@]"
           else
 
-            # Otherwise we call it with the description-arguments built above.
+            # Otherwise we call it with the description-arguments.
 
             eval "action=( $action )"
-            "$action[1]" "$subopts[@]" "$expl[@]" "${(@)action[2,-1]}"
+            _loop arguments expl "$descr" \
+                "$action[1]" "$subopts[@]" "${(@)action[2,-1]}"
           fi
         fi
       fi
 
-      if [[ -z "$matched" ]] && _requested options &&
+      if [[ -z "$matched$hasopts" ]] && _requested options &&
           { ! zstyle -T ":completion:${curcontext}:options" prefix-needed ||
-          [[ "$origpre" = [-+]* ||
-             ( -z "$aret$mesg" && nm -eq compstate[nmatches] ) ]] } ; then
+            [[ "$origpre" = [-+]* ||
+            ( -z "$aret$mesg" && nm -eq compstate[nmatches] ) ]] } ; then
 	local prevpre="$PREFIX" previpre="$IPREFIX"
 
+	hasopts=yes
+
 	PREFIX="$origpre"
 	IPREFIX="$origipre"
 
diff --git a/Completion/Base/_brace_parameter b/Completion/Base/_brace_parameter
index a6892d944..819ee24be 100644
--- a/Completion/Base/_brace_parameter
+++ b/Completion/Base/_brace_parameter
@@ -1,3 +1,3 @@
 #compdef -brace-parameter-
 
-_tags parameters && _parameters -e
+_wanted parameters && _parameters -e
diff --git a/Completion/Base/_condition b/Completion/Base/_condition
index b6a4eff7a..7ddfd9783 100644
--- a/Completion/Base/_condition
+++ b/Completion/Base/_condition
@@ -3,9 +3,9 @@
 local prev="$words[CURRENT-1]" ret=1
 
 if [[ "$prev" = -o ]]; then
-  _tags -C -o options && _options
+  _wanted -C -o options && _options
 elif [[ "$prev" = -([a-hkprsuwxLOGSN]|[no]t|ef) ]]; then
-  _tags -C "$prev" files && _files
+  _wanted -C "$prev" files && _files
 else
   if [[ "$PREFIX" = -* ]] ||
      ! zstyle -T ":completion:${curcontext}:options" prefix-needed; then
diff --git a/Completion/Base/_default b/Completion/Base/_default
index b84cbff6a..a237ae47d 100644
--- a/Completion/Base/_default
+++ b/Completion/Base/_default
@@ -12,7 +12,7 @@ if { zstyle -s ':completion:${curcontext}:' use-compctl ctl ||
   compcall "$opt[@]" || return 0
 fi
 
-_tags files || return 1
+_wanted files || return 1
 
 _files && return 0
 
diff --git a/Completion/Base/_describe b/Completion/Base/_describe
index 986d27c4e..95016fcd1 100644
--- a/Completion/Base/_describe
+++ b/Completion/Base/_describe
@@ -3,7 +3,7 @@
 # This can be used to add options or values with descriptions as matches.
 
 local _opt _expl _tmps _tmpd _tmpmd _tmpms _ret=1 _showd _nm _hide _args
-local _type=values
+local _type=values _descr
 
 # Get the option.
 
@@ -14,37 +14,40 @@ fi
 
 # Do the tests. `showd' is set if the descriptions should be shown.
 
-_tags "$_type" || return 1
+_wanted "$_type" || return 1
 
 zstyle -T ":completion:${curcontext}:$_type" verbose && _showd=yes
 
-_description "$_type" _expl "$1"
+_descr="$1"
 shift
 
-if [[ -n "$_showd" ]]; then
-  compdescribe -I ' -- ' "$@"
-else
-  compdescribe -i "$@"
-fi
-
 [[ "$_type" = options ]] &&
     zstyle -t ":completion:${curcontext}:options" prefix-hidden && _hide=yes
 
-while compdescribe -g _args _tmpd _tmpmd _tmps _tmpms; do
+while _try "$_type" _expl "$_descr"; do
+
+  if [[ -n "$_showd" ]]; then
+    compdescribe -I ' -- ' "$@"
+  else
+    compdescribe -i "$@"
+  fi
+
+  while compdescribe -g _args _tmpd _tmpmd _tmps _tmpms; do
 
-  # See if we should remove the option prefix characters.
+    # See if we should remove the option prefix characters.
 
-  if [[ -n "$_hide" ]]; then
-    if [[ "$PREFIX" = --* ]]; then
-      _tmpd=( "${(@)_tmpd#--}" )
-      _tmps=( "${(@)_tmps#--}" )
-    elif [[ "$PREFIX" = [-+]* ]]; then
-      _tmpd=( "${(@)_tmpd#[-+]}" )
-      _tmps=( "${(@)_tmps#[-+]}" )
+    if [[ -n "$_hide" ]]; then
+      if [[ "$PREFIX" = --* ]]; then
+        _tmpd=( "${(@)_tmpd#--}" )
+        _tmps=( "${(@)_tmps#--}" )
+      elif [[ "$PREFIX" = [-+]* ]]; then
+        _tmpd=( "${(@)_tmpd#[-+]}" )
+        _tmps=( "${(@)_tmps#[-+]}" )
+      fi
     fi
-  fi
-  compadd "$_args[@]" "$_expl[@]" -ld _tmpd - "$_tmpmd[@]" && _ret=0
-  compadd "$_args[@]" "$_expl[@]" -d _tmps  - "$_tmpms[@]" && _ret=0
-done
 
+    compadd "$_args[@]" "$_expl[@]" -ld _tmpd - "$_tmpmd[@]" && _ret=0
+    compadd "$_args[@]" "$_expl[@]" -d _tmps  - "$_tmpms[@]" && _ret=0
+  done
+done
 return _ret
diff --git a/Completion/Base/_first b/Completion/Base/_first
index 566cfc785..386f67fa0 100644
--- a/Completion/Base/_first
+++ b/Completion/Base/_first
@@ -34,7 +34,7 @@
 # completion of words from the history by adding two commas at the end 
 # and hitting TAB.
 #
-#     if [[ "$PREFIX" = *,, ]] && _tags history-words; then
+#     if [[ "$PREFIX" = *,, ]] && _wanted history-words; then
 #       local max i=1 expl
 #     
 #       PREFIX="$PREFIX[1,-2]"
diff --git a/Completion/Base/_jobs b/Completion/Base/_jobs
index 6c4154d6f..52674497e 100644
--- a/Completion/Base/_jobs
+++ b/Completion/Base/_jobs
@@ -1,8 +1,8 @@
 #autoload
 
-local expl disp jobs job jids pfx='%' desc how
+local expl disp jobs job jids pfx='%' desc how expls
 
-_tags jobs || return 1
+_wanted jobs || return 1
 
 if [[ "$1" = -t ]]; then
   zstyle -T ":completion:${curcontext}:jobs" prefix-needed &&
@@ -15,15 +15,15 @@ zstyle -T ":completion:${curcontext}:jobs" verbose       && desc=yes
 if [[ "$1" = -r ]]; then
   jids=( "${(@k)jobstates[(R)running*]}" )
   shift
-  _description jobs expl 'running job'
+  expls='running job'
 elif [[ "$1" = -s ]]; then
   jids=( "${(@k)jobstates[(R)running*]}" )
   shift
-  _description jobs expl 'suspended job'
+  expls='suspended job'
 else
   [[ "$1" = - ]] && shift
   jids=( "${(@k)jobtexts}" )
-  _description jobs expl job
+  expls=job
 fi
 
 if [[ -n "$desc" ]]; then
@@ -79,7 +79,7 @@ else
 fi
 
 if [[ -n "$desc" ]]; then
-  compadd "$@" "$expl[@]" -ld disp - "%$^jobs[@]"
+  _loop jobs expl "$expls" compadd "$@" -ld disp - "%$^jobs[@]"
 else
-  compadd "$@" "$expl[@]" - "%$^jobs[@]"
+  _loop jobs expl "$expls" compadd "$@" - "%$^jobs[@]"
 fi
diff --git a/Completion/Base/_math b/Completion/Base/_math
index 821121c33..b9743d6b4 100644
--- a/Completion/Base/_math
+++ b/Completion/Base/_math
@@ -9,4 +9,4 @@ if [[ "$SUFFIX" = *[^a-zA-Z0-9_]* ]]; then
   SUFFIX="${SUFFIX%%[^a-zA-Z0-9_]*}"
 fi
 
-_tags parameters && _parameters
+_parameters
diff --git a/Completion/Base/_parameter b/Completion/Base/_parameter
index 7a761dea9..7e7788535 100644
--- a/Completion/Base/_parameter
+++ b/Completion/Base/_parameter
@@ -1,3 +1,3 @@
 #compdef -parameter-
 
-_tags parameters && _parameters -e
+_parameters -e
diff --git a/Completion/Base/_subscript b/Completion/Base/_subscript
index c0c0b790d..aa31bd297 100644
--- a/Completion/Base/_subscript
+++ b/Completion/Base/_subscript
@@ -3,23 +3,23 @@
 local expl
 
 if [[ "$PREFIX" = :* ]]; then
-  _wanted characters expl 'character class' &&
-      compadd "$expl[@]" -p: -S ':]' alnum alpha blank cntrl digit graph \
-                                     lower print punct space upper xdigit
+  _wanted characters expl 'character class' \
+      compadd -p: -S ':]' alnum alpha blank cntrl digit graph \
+                          lower print punct space upper xdigit
 elif [[ ${(Pt)${compstate[parameter]}} = assoc* ]]; then
-  _wanted association-keys expl 'association key' &&
-      if [[ "$RBUFFER" = \]* ]]; then
-        compadd "$expl[@]" -S '' - "${(@kP)${compstate[parameter]}}"
-      else
-        compadd "$expl[@]" -S ']' - "${(@kP)${compstate[parameter]}}"
-      fi
+  local suf
+
+  [[ "$RBUFFER" != \]* ]] && suf=']'
+
+  _wanted association-keys expl 'association key' \
+      compadd -S "$suf" - "${(@kP)${compstate[parameter]}}"
 elif [[ ${(Pt)${compstate[parameter]}} = array* ]]; then
   local list i j ret=1 disp
 
   _tags indexes parameters
 
   while _tags; do
-    if _requested -V indexes expl 'array index'; then
+    if _requested indexes; then
       ind=( {1..${#${(P)${compstate[parameter]}}}} )
       if zstyle -T ":completion:${curcontext}:indexes" verbose; then
         list=()
@@ -38,9 +38,11 @@ elif [[ ${(Pt)${compstate[parameter]}} = array* ]]; then
       fi
 
       if [[ "$RBUFFER" = \]* ]]; then
-        compadd "$expl[@]" -S '' "$disp[@]" - "$ind[@]" && ret=0
+        _loop -V indexes expl 'array index' \
+            compadd -S '' "$disp[@]" - "$ind[@]" && ret=0
       else
-        compadd "$expl[@]" -S ']' "$disp[@]" - "$ind[@]" && ret=0
+        _loop -V indexes expl 'array index' \
+            compadd -S ']' "$disp[@]" - "$ind[@]" && ret=0
       fi
     fi
     _requested parameters && _parameters && ret=0
diff --git a/Completion/Base/_tilde b/Completion/Base/_tilde
index 98e9d2c00..2edc2ca24 100644
--- a/Completion/Base/_tilde
+++ b/Completion/Base/_tilde
@@ -18,10 +18,10 @@ _tags users named-directories directory-stack
 
 while _tags; do
   _requested users && _users "$suf[@]" "$@" && ret=0
-  _requested named-directories expl 'named directory' &&
-      compadd "$suf[@]" "$expl[@]" "$@" - "${(@k)nameddirs}"
+  _requested named-directories expl 'named directory' \
+      compadd "$suf[@]" "$@" - "${(@k)nameddirs}"
 
-  if _requested -V directory-stack expl 'directory stack' &&
+  if _requested directory-stack &&
      { ! zstyle -T ":completion:${curcontext}:directory-stack" prefix-needed ||
        [[ "$PREFIX" = [-+]* || nm -eq compstate[nmatches] ]] }; then
     if zstyle -T ":completion:${curcontext}:directory-stack" verbose; then
@@ -46,7 +46,8 @@ while _tags; do
       list=( ${PREFIX[1]}{0..${#dirstack}} )
       disp=()
     fi
-    compadd "$expl[@]" "$suf[@]" "$disp[@]" -Q - "$list[@]" && ret=0
+    _loop -V directory-stack expl 'directory stack' \
+        compadd "$suf[@]" "$disp[@]" -Q - "$list[@]" && ret=0
   fi
   (( ret )) || return 0
 done
diff --git a/Completion/Base/_values b/Completion/Base/_values
index e8004ba6f..754147e05 100644
--- a/Completion/Base/_values
+++ b/Completion/Base/_values
@@ -18,7 +18,7 @@ if compvalues -i "$@"; then
 
   if ! compvalues -D descr action; then
 
-    _tags values || return 1
+    _wanted values || return 1
 
     curcontext="${oldcontext%:*}:values"
 
@@ -119,25 +119,26 @@ if compvalues -i "$@"; then
 
       # Anything inside `(...)' is added directly.
 
-      compadd "$subopts[@]" "$expl[@]" - ${=action[2,-2]}
+      _loop arguments expl "$descr" compadd "$subopts[@]" - ${=action[2,-2]}
     elif [[ "$action" = \{*\} ]]; then
 
       # A string in braces is evaluated.
 
-      eval "$action[2,-2]"
+      _loop arguments expl "$descr" eval "$action[2,-2]"
 
     elif [[ "$action" = \ * ]]; then
 
       # If the action starts with a space, we just call it.
 
       eval "action=( $action )"
-      "$action[@]"
+      _loop arguments expl "$descr" "$action[@]"
     else
 
       # Otherwise we call it with the description-arguments built above.
 
       eval "action=( $action )"
-      "$action[1]" "$subopts[@]" "$expl[@]" "${(@)action[2,-1]}"
+      _loop arguments expl "$descr" \
+          "$action[1]" "$subopts[@]" "${(@)action[2,-1]}"
     fi
   fi
 
diff --git a/Completion/Builtins/_arrays b/Completion/Builtins/_arrays
index 4f67ff08d..138b14091 100644
--- a/Completion/Builtins/_arrays
+++ b/Completion/Builtins/_arrays
@@ -2,5 +2,4 @@
 
 local expl
 
-_wanted arrays expl array &&
-    compadd "$expl[@]" - "${(@k)parameters[(R)*array*]}"
+_wanted arrays expl array compadd - "${(@k)parameters[(R)*array*]}"
diff --git a/Completion/Builtins/_autoload b/Completion/Builtins/_autoload
index de5a6045d..f1d49c3e3 100644
--- a/Completion/Builtins/_autoload
+++ b/Completion/Builtins/_autoload
@@ -2,5 +2,4 @@
 
 local expl
 
-_wanted functions expl 'shell function' &&
-    compadd "$expl[@]" - ${^fpath}/*(N:t)
+_wanted functions expl 'shell function' compadd - ${^fpath}/*(N:t)
diff --git a/Completion/Builtins/_bindkey b/Completion/Builtins/_bindkey
index 98459916b..d96c2289b 100644
--- a/Completion/Builtins/_bindkey
+++ b/Completion/Builtins/_bindkey
@@ -10,9 +10,7 @@
 local expl
 
 if [[ "$words[2]" = -*[DAN]* || "$words[CURRENT-1]" = -*M ]]; then
-  _wanted -C -M keymaps expl keymap &&
-      compadd "$expl[@]" - "$keymaps[@]"
+  _wanted -C -M keymaps expl keymap compadd - "$keymaps[@]"
 else
-  _wanted widgets expl widget &&
-      compadd "$expl[@]" -M 'r:|-=* r:|=*' - "${(@k)widgets}"
+  _wanted widgets expl widget compadd -M 'r:|-=* r:|=*' - "${(@k)widgets}"
 fi
diff --git a/Completion/Builtins/_builtin b/Completion/Builtins/_builtin
index 8d682420a..1ca5e346c 100644
--- a/Completion/Builtins/_builtin
+++ b/Completion/Builtins/_builtin
@@ -7,6 +7,5 @@ if (( $CURRENT > 2 )); then
 else
   local expl
 
-  _wanted commands expl 'builtin command' &&
-      compadd "$expl[@]" "$@" - "${(k@)builtins}"
+  _wanted commands expl 'builtin command' compadd "$@" - "${(k@)builtins}"
 fi
diff --git a/Completion/Builtins/_cd b/Completion/Builtins/_cd
index 4cb070811..bea6ffbc6 100644
--- a/Completion/Builtins/_cd
+++ b/Completion/Builtins/_cd
@@ -22,8 +22,7 @@ if [[ CURRENT -eq 3 ]]; then
   rep=(${~PWD/$words[2]/*}~$PWD(-/N))
   # Now remove all the common parts of $PWD and the completions from this
   rep=(${${rep#${PWD%%$words[2]*}}%${PWD#*$words[2]}})
-  (( $#rep )) && _wanted -C replacement strings expl replacement &&
-      compadd "$expl[@]" $rep
+  (( $#rep )) && _wanted -C replacement strings expl replacement compadd $rep
 elif _popd || [[ $PREFIX != (\~|/|./|../)* && $#cdpath -ne 0 ]]; then
   local tdir tdir2
 
diff --git a/Completion/Builtins/_command b/Completion/Builtins/_command
index 1cfa6add9..6631b9b6b 100644
--- a/Completion/Builtins/_command
+++ b/Completion/Builtins/_command
@@ -6,6 +6,5 @@ if [[ CURRENT -ge 3 ]]; then
 else
   local expl
 
-  _wanted commands expl 'external command' &&
-      compadd "$expl[@]" "$@" - "${(k@)commands}"
+  _wanted commands expl 'external command' compadd "$@" - "${(k@)commands}"
 fi
diff --git a/Completion/Builtins/_compdef b/Completion/Builtins/_compdef
index 772c6b90d..13711e865 100644
--- a/Completion/Builtins/_compdef
+++ b/Completion/Builtins/_compdef
@@ -16,24 +16,24 @@ _arguments -C -s \
 
 case $state in
   ccom)
-    _wanted commands expl 'completed command' &&
-        compadd "$expl[@]" - ${(k)_comps}
+    _wanted commands expl 'completed command' compadd - ${(k)_comps}
   ;;
   cfun)
-    if _wanted functions expl 'completion function'; then
+    if _wanted functions; then
       list=( ${^fpath:/.}/_(|*[^~])(N:t) )
-      if zstyle -T ":completion:${curcontext}" prefix-hidden; then
+      if zstyle -T ":completion:${curcontext}:functions" prefix-hidden; then
         disp=( ${list[@]#_} )
-        compadd "$expl[@]" -d disp - "$list[@]"
+        _loop functions expl 'completion function' compadd -d disp - "$list[@]"
       else
-        compadd "$expl[@]" - "$list[@]"
+        _loop functions expl 'completion function' compadd - "$list[@]"
       fi
     fi
   ;;
   style)
-    _wanted widgetstyle expl 'widget style' &&
-        compadd complete-word delete-char-or-list expand-or-complete \
-        expand-or-complete-prefix list-choices menu-complete \
-        menu-expand-or-complete reverse-menu-complete
+    _wanted widgetstyle expl 'widget style' \
+        compadd -M 'r:|-=* r:|=*' \
+            complete-word delete-char-or-list expand-or-complete \
+            expand-or-complete-prefix list-choices menu-complete \
+            menu-expand-or-complete reverse-menu-complete
   ;;
 esac
diff --git a/Completion/Builtins/_echotc b/Completion/Builtins/_echotc
index 4051c1945..cc07b9cd0 100644
--- a/Completion/Builtins/_echotc
+++ b/Completion/Builtins/_echotc
@@ -2,7 +2,6 @@
 
 local expl
 
-_wanted arguments expl 'terminal capability' &&
-    compadd "$expl[@]" \
-            al dc dl do le up al bl cd ce cl cr \
+_wanted arguments expl 'terminal capability' \
+    compadd al dc dl do le up al bl cd ce cl cr \
             dc dl do ho is le ma nd nl se so up
diff --git a/Completion/Builtins/_functions b/Completion/Builtins/_functions
index 98b21da68..de49d96ed 100644
--- a/Completion/Builtins/_functions
+++ b/Completion/Builtins/_functions
@@ -2,5 +2,4 @@
 
 local expl
 
-_wanted functions expl 'shell function' &&
-    compadd "$expl[@]" "$@" - "${(k@)functions}"
+_wanted functions expl 'shell function' compadd "$@" - "${(k@)functions}"
diff --git a/Completion/Builtins/_hash b/Completion/Builtins/_hash
index c8a51a38a..b7e777a05 100644
--- a/Completion/Builtins/_hash
+++ b/Completion/Builtins/_hash
@@ -4,15 +4,14 @@ local expl
 
 if [[ "$words[2]" = -*d* ]]; then
   if compset -P 1 '*='; then
-    _wanted -C -d-value files && _path_files -g '*(-/)'
+    _wanted -C -d-value files expl directories _path_files -/
   else
-    _wanted -C -d named-directories expl 'named directory' &&
-        compadd "$expl[@]" -q -S '=' - "${(@k)nameddirs}"
+    _wanted -C -d named-directories expl 'named directory' \
+        compadd -q -S '=' - "${(@k)nameddirs}"
   fi
 elif compset -P 1 '*='; then
   _wanted -C value values expl 'executable file' &&
       _files "$expl[@]" -g '*(-*)'
 else
-  _wanted -C name commands expl command &&
-      compadd "$expl[@]" -q -S '=' - "${(@k)commands}"
+  _wanted -C name commands expl command compadd -q -S '=' - "${(@k)commands}"
 fi
diff --git a/Completion/Builtins/_limits b/Completion/Builtins/_limits
index dae573e03..5dd2bffe5 100644
--- a/Completion/Builtins/_limits
+++ b/Completion/Builtins/_limits
@@ -2,5 +2,4 @@
 
 local expl
 
-_wanted limits expl 'process limits' &&
-    compadd "$expl[@]" ${${(f)"$(limit)"}%% *}
+_wanted limits expl 'process limits' compadd ${${(f)"$(limit)"}%% *}
diff --git a/Completion/Builtins/_pids b/Completion/Builtins/_pids
index 92fc9bac7..ff65cef31 100644
--- a/Completion/Builtins/_pids
+++ b/Completion/Builtins/_pids
@@ -5,7 +5,7 @@
 
 local out list expl match desc listargs args
 
-_wanted processes expl 'process ID' || return 1
+_wanted processes || return 1
 
 if [[ "$1" = -m ]]; then
   match="${2}*"
@@ -29,5 +29,6 @@ else
   desc=()
 fi
 
-compadd "$expl[@]" "$@" "$desc[@]" - \
-    ${${${(M)${(f)"${out}"}[2,-1]:#[ 	]#${PREFIX}[0-9]#${SUFFIX}[ 	]#*${~match}}## #}%% *}
+_loop processes expl 'process ID' \
+    compadd "$@" "$desc[@]" - \
+        ${${${(M)${(f)"${out}"}[2,-1]:#[ 	]#${PREFIX}[0-9]#${SUFFIX}[ 	]#*${~match}}## #}%% *}
diff --git a/Completion/Builtins/_popd b/Completion/Builtins/_popd
index b79121139..ba12bb3f3 100644
--- a/Completion/Builtins/_popd
+++ b/Completion/Builtins/_popd
@@ -12,7 +12,7 @@ local expl list lines revlines disp
 ! zstyle -T ":completion:${curcontext}:directory-stack" prefix-needed ||
     [[ $PREFIX = [-+]* ]] || return 1
 
-_wanted -V directory-stack expl 'directory stack' || return 1
+_wanted directory-stack || return 1
 
 if zstyle -T ":completion:${curcontext}:directory-stack" verbose; then
   # get the list of directories with their canonical number
@@ -39,4 +39,5 @@ else
   disp=()
 fi
 
-compadd "$expl[@]" "$@" "$disp[@]" -Q - "$list[@]"
+_loop -V directory-stack expl 'directory stack' \
+    compadd "$@" "$disp[@]" -Q - "$list[@]"
diff --git a/Completion/Builtins/_sched b/Completion/Builtins/_sched
index 783113c45..97d8830b8 100644
--- a/Completion/Builtins/_sched
+++ b/Completion/Builtins/_sched
@@ -4,7 +4,7 @@ local expl lines disp
 
 if [[ CURRENT -eq 2 ]]; then
   if compset -P -; then
-    _wanted -C - jobs expl 'scheduled jobs' || return 1
+    _wanted -C - jobs || return 1
 
     lines=(${(f)"$(sched)"})
     if zstyle -T ":completion:${curcontext}:jobs" verbose; then
@@ -12,7 +12,9 @@ if [[ CURRENT -eq 2 ]]; then
     else
       disp=()
     fi
-    [[ -z $lines ]] || compadd "$expl[@]" "$disp[@]" - {1..$#lines}
+    [[ -z $lines ]] || _loop jobs expl 'scheduled jobs' \
+                           compadd "$disp[@]" - {1..$#lines}
+    return
   else
     _message 'time specification'
     return 1
diff --git a/Completion/Builtins/_signals b/Completion/Builtins/_signals
index 910502165..041b6eb6b 100644
--- a/Completion/Builtins/_signals
+++ b/Completion/Builtins/_signals
@@ -20,7 +20,7 @@ done
 
 [[ "$1" = -(|-) ]] && shift
 
-if _wanted signals expl signal &&
+if _wanted signals &&
        { [[ -z "$minus" ]] ||
          ! zstyle -T ":completion:${curcontext}:signals" prefix-needed ||
          [[ "$PREFIX" = -* ]] } ; then
@@ -32,6 +32,7 @@ if _wanted signals expl signal &&
   else
     disp=()
   fi
-  compadd "$@" "$expl[@]" "$disp[@]" -M 'm:{a-z}=${A-Z}' - \
-          "${minus}${(@)^signals[1,last]}"
+  _loop signals expl signal \
+      compadd "$@" "$disp[@]" -M 'm:{a-z}={A-Z}' - \
+              "${minus}${(@)^signals[1,last]}"
 fi
diff --git a/Completion/Builtins/_stat b/Completion/Builtins/_stat
index c03b1590c..5f291d49b 100644
--- a/Completion/Builtins/_stat
+++ b/Completion/Builtins/_stat
@@ -9,10 +9,12 @@ else
 
   while _tags; do
     _requested files && _files && ret=0
-    _requested options expl 'inode element' &&
+    _requested options &&
         { ! zstyle -T ":completion:${curcontext}:options" prefix-needed ||
           [[ "$PREFIX[1]" = + || ret -eq 1 ]] } &&
-        compadd "$expl[@]" - +device +inode +mode +nlink +uid +gid +rdev \
-                             +size +atime +mtime +ctime +blksize +block +link
+        _loop options expl 'inode element' \
+            compadd - +device +inode +mode +nlink +uid +gid +rdev \
+                      +size +atime +mtime +ctime +blksize +block +link
+    (( ret )) || return 0
   done
 fi
diff --git a/Completion/Builtins/_vars b/Completion/Builtins/_vars
index 2758f3de2..7d8c20f52 100644
--- a/Completion/Builtins/_vars
+++ b/Completion/Builtins/_vars
@@ -16,9 +16,9 @@ if [[ $PREFIX = *\[* ]]; then
   if [[ ${(tP)var} = assoc* ]]; then
     local expl
 
-    _wanted -C subscript association-keys expl 'association key' &&
-        compadd "$expl[@]" $addclose - ${(kP)var}
+    _wanted -C subscript association-keys expl 'association key' \
+        compadd $addclose - ${(kP)var}
   fi
 else
-  _tags parameters && _parameters
+  _wanted parameters && _parameters
 fi
diff --git a/Completion/Builtins/_zftp b/Completion/Builtins/_zftp
index 6246015ec..c0b19a796 100644
--- a/Completion/Builtins/_zftp
+++ b/Completion/Builtins/_zftp
@@ -13,8 +13,8 @@ local subcom expl curcontext="${curcontext}"
 
 if [[ $words[1] = zftp ]]; then
   if [[ $CURRENT -eq 2 ]]; then
-    _wanted commands expl sub-command &&
-        compadd "$expl[@]" open params user login type ascii binary mode put \
+    _wanted commands expl sub-command \
+        compadd open params user login type ascii binary mode put \
           putat get getat append appendat ls dir local remote mkdir rmdir \
           session rmsession
     return
@@ -28,49 +28,51 @@ fi
 case $subcom in
   *(cd|ls|dir))
     # complete remote directories
-    _tags directories && zfcd_match $PREFIX $SUFFIX
+    _wanted directories && zfcd_match $PREFIX $SUFFIX
     ;;
 
   *(get(|at)|gcp|delete|remote))
     # complete remote files
-    _tags files && zfget_match $PREFIX $SUFFIX
+    _wanted files && zfget_match $PREFIX $SUFFIX
     ;;
 
   *(put(|at)|pcp))
     # complete local files
-    _tags files && _files
+    _wanted files && _files
     ;;
 
   *(open|anon|params))
     # complete hosts:  should do cleverer stuff with user names
-    _tags hosts && _hosts
+    _wanted hosts && _hosts
     ;;
 
   *(goto|mark))
     # complete bookmarks.  First decide if ncftp mode is go.
-    _wanted bookmarks expl bookmark || return 1
+    _wanted bookmarks || return 1
     if [[ $words[2] = -*n* ]]; then
       if [[ -f ~/.ncftp/bookmarks ]]; then
-        compadd "$expl[@]" - $(awk -F, 'NR > 2 { print $1 }' ~/.ncftp/bookmarks)
+        _loop bookmarks expl bookmark \
+            compadd - $(awk -F, 'NR > 2 { print $1 }' ~/.ncftp/bookmarks)
       fi
     else
       if [[ -f ${ZFTP_BMFILE:=${ZDOTDIR:-$HOME}/.zfbkmarks} ]]; then
-        compadd "$expl[@]" - $(awk '{print $1}' $ZFTP_BMFILE)
+        _loop bookmarks expl bookmark \
+            compadd - $(awk '{print $1}' $ZFTP_BMFILE)
       fi
     fi
     ;;
 
   *session)
     # complete sessions, excluding the current one.
-    _wanted sessions expl 'another FTP session' &&
-        compadd "$expl[@]" - ${$(zftp session):#$ZFTP_SESSION}
+    _wanted sessions expl 'another FTP session' \
+        compadd - ${$(zftp session):#$ZFTP_SESSION}
     ;;
 
   *transfer)
     # complete arguments like sess1:file1 sess2:file2
     if [[ $PREFIX = *:* ]]; then
       # complete file in the given session
-      _tags files || return 1
+      _wanted files || return 1
       local sess=${PREFIX%%:*} oldsess=$ZFTP_SESSION
       compset -p $(( $#sess + 1 ))
       [[ -n $sess ]] && zftp session $sess
@@ -78,8 +80,7 @@ case $subcom in
       [[ -n $sess && -n $oldsess ]] && zftp session $oldsess
     else
       # note here we can complete the current session
-      _wanted sessions expl 'FTP session' &&
-          compadd "$expl[@]" -S : - $(zftp session)
+      _wanted sessions expl 'FTP session' compadd -S : - $(zftp session)
     fi
     ;;
 
diff --git a/Completion/Builtins/_zle b/Completion/Builtins/_zle
index 8e8017817..46765bc5e 100644
--- a/Completion/Builtins/_zle
+++ b/Completion/Builtins/_zle
@@ -3,8 +3,8 @@
 local expl
 
 if [[ "$words[2]" = -N && CURRENT -eq 3 ]]; then
-  _wanted -C -N functions expl 'widget shell function' &&
-      compadd "$expl[@]" "$@" - "${(k@)functions}" && ret=0
+  _wanted -C -N functions expl 'widget shell function' \
+      compadd "$@" - "${(k@)functions}"
 else
-  _wanted widgets expl widget && compadd "$expl[@]" - "${(@k)widgets}"
+  _wanted widgets expl widget compadd - "${(@k)widgets}"
 fi
diff --git a/Completion/Builtins/_zmodload b/Completion/Builtins/_zmodload
index c167df445..7e893c860 100644
--- a/Completion/Builtins/_zmodload
+++ b/Completion/Builtins/_zmodload
@@ -3,11 +3,9 @@
 local fl="$words[2]" expl
 
 if [[ "$fl" = -*(a*u|u*a)* || "$fl" = -*a* && CURRENT -ge 4 ]]; then
-  _wanted builtins expl 'builtin command' &&
-      compadd "$expl[@]" "$@" - "${(k@)builtins}"
+  _wanted builtins expl 'builtin command' compadd "$@" - "${(k@)builtins}"
 elif [[ "$fl" = -*u* ]]; then
-  _wanted modules expl module && compadd "$expl[@]" - "${(@k)modules}"
+  _wanted modules expl module compadd - "${(@k)modules}"
 else
-  _wanted files expl 'module file' &&
-      _files "$expl[@]" -W module_path -/g '*.s[ol](:r)'
+  _wanted files expl 'module file' _files -W module_path -/g '*.s[ol](:r)'
 fi
diff --git a/Completion/Builtins/_zpty b/Completion/Builtins/_zpty
index b197b4128..4090bde69 100644
--- a/Completion/Builtins/_zpty
+++ b/Completion/Builtins/_zpty
@@ -11,13 +11,13 @@ _arguments -C -s \
   '(-e -b -d -w -r)-L[list defined commands as calls]' \
   '*::args:_normal'
 
-if [[ $state = name ]] && _wanted zptynames expl 'zpty command names'; then
+if [[ $state = name ]] && _wanted names; then
   list=( ${${(f)"$(zpty)"}#*\) } )
   names=( ${list%%:*} )
   if zstyle -T ":completion:${curcontext}" verbose; then
     zformat -a list ' --' ${${(f)"$(zpty)"}#*\) }
-    compadd "$expl[@]" -d list - "$names[@]"
+    _loop names expl 'zpty command names' compadd -d list - "$names[@]"
   else
-    compadd "$expl[@]" - "$names[@]"
+    _loop names expl 'zpty command names' compadd - "$names[@]"
   fi
 fi
diff --git a/Completion/Builtins/_zstyle b/Completion/Builtins/_zstyle
index 328e2d7d2..6cb369cfd 100644
--- a/Completion/Builtins/_zstyle
+++ b/Completion/Builtins/_zstyle
@@ -41,7 +41,6 @@ styles=(
   list-packed		 c:bool
   list-rows-first	 c:bool
   local			 c:
-  matcher		 c:
   matcher-list		 c:
   max-errors		 c:
   menu			 c:boolauto
@@ -94,9 +93,9 @@ while [[ -n $state ]]; do
 
   case "$ostate" in
     contexts)
-      if _wanted contexts expl context; then
+      if _wanted contexts; then
         if [[ $PREFIX != :*: ]]; then
-	  compadd -P : -S : "$expl[@]" completion zftp
+	  _loop contexts expl context compadd -P : -S : completion zftp
         elif [[ $PREFIX = :completion:* ]]; then
           mesg=''
           case "$PREFIX" in
@@ -118,8 +117,8 @@ while [[ -n $state ]]; do
       else
         ctop=cz
       fi
-      _wanted styles expl style &&
-         compadd "$expl[@]" -M 'r:|-=* r:|=*' - ${(k)styles[(R)[^:]#[$ctop][^:]#:*]}
+      _wanted styles expl style \
+         compadd -M 'r:|-=* r:|=*' - ${(k)styles[(R)[^:]#[$ctop][^:]#:*]}
       ;;
       
     style-arg)
@@ -127,32 +126,28 @@ while [[ -n $state ]]; do
       ;;
 
     bool) 
-      _wanted values expl boolean &&
-	compadd "$expl[@]" true false
+      _wanted values expl boolean compadd true false
       ;;
 
     boolauto) 
-      _wanted values expl boolean &&
-	compadd "$expl[@]" true false auto select
+      _wanted values expl boolean compadd true false auto select
       ;;
 
     cursor)
       if [[ "$words[2]" = *:completion:inc* ]]; then
-        _wanted values expl 'cursor positioning' &&
-	  compadd "$expl[@]" complete key default
+        _wanted values expl 'cursor positioning' compadd complete key default
       elif [[ "$words[2]" = *:completion::* ]]; then
-        _wanted values expl 'cursor positioning' &&
-	  compadd "$expl[@]" true false
+        _wanted values expl 'cursor positioning' compadd true false
       else
-        _wanted values expl 'cursor positioning' &&
-	  compadd "$expl[@]" complete key default true false
+        _wanted values expl 'cursor positioning' \
+	  compadd complete key default true false
       fi
       ;;
 
     completer)
-      _wanted values expl completer &&
-	compadd "$expl[@]" _complete _approximate _correct _match \
-          _expand _list _menu _oldlist
+      _wanted values expl completer \
+	compadd _complete _approximate _correct _match \
+                _expand _list _menu _oldlist _next_tags
       ;;
 
     user-host-port)
@@ -177,32 +172,32 @@ while [[ -n $state ]]; do
       ;;
 
     listwhen)
-      _wanted values expl 'when to list completions' &&
-	compadd "$expl[@]" always never sometimes
+      _wanted values expl 'when to list completions' \
+	compadd always never sometimes
       ;;
 
     packageset)
-      _wanted values expl 'default package set' &&
-        compadd "$expl[@]" available installed uninstalled
+      _wanted values expl 'default package set' \
+        compadd available installed uninstalled
       ;;
 
     progress)
-      _wanted values expl 'progress meter style' &&
-        compadd "$expl[@]" none bar percent
+      _wanted values expl 'progress meter style' \
+        compadd none bar percent
       ;;
 
     sdirs)
-      _wanted values expl 'whether to complete . or ..' &&
-        compadd "$expl[@]" true false ..
+      _wanted values expl 'whether to complete . or ..' \
+        compadd true false ..
       ;;
 
     stop)
-      _wanted values expl 'when to insert matches' &&
-	compadd "$expl[@]" true false verbose
+      _wanted values expl 'when to insert matches' \
+	compadd true false verbose
       ;;
 
     tag)
-      _wanted tags expl tag && compadd "$expl[@]" - $taglist
+      _wanted tags expl tag compadd - $taglist
       ;;
 
     user-host)
@@ -215,13 +210,13 @@ while [[ -n $state ]]; do
       ;;
 
     ignorepar)
-      _wanted values expl 'which parents to ignore' &&
-        compadd "$expl[@]" parent pwd .. directory
+      _wanted values expl 'which parents to ignore' \
+        compadd parent pwd .. directory
       ;;
 
     single-ignored)
-      _wanted values expl 'how to handle single alternate match' &&
-          compadd "$expl[@]" - show menu
+      _wanted values expl 'how to handle single alternate match' \
+          compadd - show menu
       ;;
 
     _*)
diff --git a/Completion/Commands/_next_tags b/Completion/Commands/_next_tags
index 5cda547e8..818b73fe0 100644
--- a/Completion/Commands/_next_tags
+++ b/Completion/Commands/_next_tags
@@ -52,8 +52,13 @@ _next_tags() {
 _next_tags_sort() {
   local order tags tag nodef
 
-  zstyle -a ":completion:${curcontext}:" tag-order order ||
-    order=( 'arguments values' options globbed-files directories all-files )
+  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...
 
diff --git a/Completion/Core/_alternative b/Completion/Core/_alternative
index 73292cb52..482e9db51 100644
--- a/Completion/Core/_alternative
+++ b/Completion/Core/_alternative
@@ -44,24 +44,26 @@ while _tags; do
 
         # Anything inside `(...)' is added directly.
 
-        compadd "$subopts[@]" "$expl[@]" - ${=action[2,-2]}
+        _loop "${def%%:*}" expl "$descr" \
+            compadd "$subopts[@]" - ${=action[2,-2]}
       elif [[ "$action" = \{*\} ]]; then
 
         # A string in braces is evaluated.
 
-        eval "$action[2,-2]"
+        _loop "${def%%:*}" expl "$descr" eval "$action[2,-2]"
       elif [[ "$action" = \ * ]]; then
 
         # If the action starts with a space, we just call it.
 
         eval "action=( $action )"
-        "$action[@]"
+        _loop "${def%%:*}" expl "$descr" "$action[@]"
       else
 
         # Otherwise we call it with the description-arguments built above.
 
         eval "action=( $action )"
-        "$action[1]" "$subopts[@]" "$expl[@]" "${(@)action[2,-1]}"
+        _loop "${def%%:*}" expl "$descr" \
+            "$action[1]" "$subopts[@]" "${(@)action[2,-1]}"
       fi
     fi
   done
diff --git a/Completion/Core/_files b/Completion/Core/_files
index 75cabda81..d4eb2b7db 100644
--- a/Completion/Core/_files
+++ b/Completion/Core/_files
@@ -1,105 +1,61 @@
 #autoload
 
-local opts opt type=file glob group gopts dopts aopts tmp _file_pat_checked=yes
-local hasign ign
+local opts tmp glob pats tags expl tag ret=1 i pat descr minus
+local _comp_default_tags
 
 zparseopts -a opts \
-    '/=tmp' 'f=tmp' 'g+:-=tmp' q n 1 2 P: S: r: R: W: X: M+: F: \
-    'J:=group' 'V:=group'
+    '/=tmp' 'f=tmp' 'g+:-=tmp' q n 1 2 P: S: r: R: W: X+: M+: F: J+: V+:
 
 type="${(@j::M)${(@)tmp#-}#?}"
-[[ -n "$type" ]] || type=f
-if (( $tmp[(I)-g*] )); then
-  gopts=( -g ${(j: :)${(M)tmp:#-g*}#-g} )
-else
-  gopts=()
-fi
-(( $opts[(I)-F] )) && hasign=yes
-
-[[ "$group[2]" = files ]] && opts=("$opts[@]" "$group[@]") group=()
-
-ign=()
-
-zstyle -s ":completion:${curcontext}:all-files" file-patterns tmp &&
-    [[ -n "$tmp" ]] &&
-        aopts=(-g "$tmp")
+(( $tmp[(I)-g*] )) && glob="${(j: :)${(M)tmp:#-g*}#-g}"
 
-if zstyle -s ":completion:${curcontext}:directories" file-patterns tmp &&
-   [[ -n "$tmp" ]]; then
-  dopts=(-g "$tmp")
-  if [[ "$type" = (*/*g*|*g*/*) ]]; then
-    type=g
-  elif [[ "$type" != *[/g]* ]]; then
-    type="${type}/"
-  fi
+if zstyle -a ":completion:${curcontext}:" file-patterns pats; then
+  [[ "$type" = */* ]] && glob="$glob *(-/)"
+  pats=( \ ${(M)^${pats/#:/ ${glob:-\*}:}:#*[^\\]:*} )
 else
-  dopts=(-/)
-fi
-if zstyle -s ":completion:${curcontext}:globbed-files" file-patterns tmp &&
-   [[ -n "$tmp" ]]; then
-  gopts=(-g "$tmp")
-  if [[ "$type" != (*/*g*|*g*/*) ]]; then
-    if [[ "$type" = *[g/]* ]]; then
-      type=g
+  if [[ "$type" = *g* ]]; then
+    if [[ "$type" = */* ]]; then
+      pats=( " ${glob//:/\\:} *(-/):globbed-files" '*:all-files' )
     else
-      type=ga
+      pats=( " ${glob//:/\\:}:globbed-files"
+             '*(-/):directories' '*:all-files' )
     fi
+  elif [[ "$type" = */* ]]; then
+    pats=( '*(-/):directories' '*:all-files' )
+  else
+    pats=( '*:all-files' )
   fi
 fi
 
-case "$type" in
-*/*g*|*g*/*) _tags globbed-files all-files             ;;
-*a*g*|*g*a*) _tags globbed-files all-files             ;;
-*g*)         _tags globbed-files directories all-files ;;
-*/*)         _tags directories all-files               ;;
-*)           _tags all-files                           ;;
-esac
+tags=( "${(@)${(@)pats#*[^\\]:}%%:*}" )
+_comp_default_tags=( "$tags[@]" )
+
+_tags "$tags[@]"
 
 while _tags; do
-  if _requested all-files; then
-    if (( $#group )); then
-      group[2]=all-files
-      _setup all-files
-      [[ -z "$hasign" ]] &&
-        zstyle -a ":completion:${curcontext}:all-files" ignored-patterns _comp_ignore &&
-	  ign=(-F _comp_ignore)
-    fi
-    _path_files "$opts[@]" "$ign[@]" "$aopts[@]"
-    return
-  elif _requested directories; then
-    if _requested globbed-files; then
-      if (( $#group )); then
-        group[2]=globbed-files
-	_setup globbed-files
-        [[ -z "$hasign" ]] &&
-          zstyle -a ":completion:${curcontext}:all-files" ignored-patterns _comp_ignore &&
-	    ign=(-F _comp_ignore)
-      fi
-      _path_files "$opts[@]" "$ign[@]" "$dopts[@]" "$gopts[@]" && return 0
-    else
-      if (( $#group )); then
-        group[2]=directories
-	_setup directories
-        [[ -z "$hasign" ]] &&
-          zstyle -a ":completion:${curcontext}:all-files" ignored-patterns _comp_ignore &&
-	    ign=(-F _comp_ignore)
+
+  for tag in "$tags[@]"; do
+
+    if _requested "$tag"; then
+
+      i="$pats[(I)*[^\\\\]:${tag}(|:*)]"
+      pat="${${pats[i]%%:${tag}*}//\\\\:/:}"
+
+      if [[ i -gt 0 && "$pat" != \ # ]]; then
+        if [[ "$pats[i]" = *:${tag}:* ]]; then
+          descr="${pats[i]#*:${tag}:}"
+          minus=()
+        else
+          descr=file
+	  minus=(-)
+        fi
+        _loop "$tag" expl "$descr" \
+            _path_files -g "$pat" "$opts[@]" "$minus[@]" && ret=0
       fi
-      _path_files "$opts[@]" "$ign[@]" "$dopts[@]" && return 0
     fi
-  elif _requested globbed-files; then
-    if (( $#group )); then
-      group[2]=globbed-files
-      _setup globbed-files
-      [[ -z "$hasign" ]] &&
-        zstyle -a ":completion:${curcontext}:all-files" ignored-patterns _comp_ignore &&
-	  ign=(-F _comp_ignore)
-    fi
-    if [[ "$type" = (*/*g*|*g*/*) ]]; then
-      _path_files "$opts[@]" "$ign[@]" "$dopts[@]" "$gopts[@]" && return 0
-    else
-      _path_files "$opts[@]" "$ign[@]" "$gopts[@]" && return 0
-    fi
-  fi
+  done
+
+  (( ret )) || return 0
 done
 
 return 1
diff --git a/Completion/Core/_main_complete b/Completion/Core/_main_complete
index 63d785686..fedea9b51 100644
--- a/Completion/Core/_main_complete
+++ b/Completion/Core/_main_complete
@@ -20,7 +20,7 @@ setopt localoptions nullglob rcexpandparam extendedglob
 unsetopt markdirs globsubst shwordsplit nounset ksharrays
 
 local ctxt post ret=1 tmp _compskip format _comp_ignore \
-      _completers _completer _completer_num \
+      _completers _completer _completer_num curtag \
       _matchers _matcher _matcher_num _comp_tags \
       context state line opt_args val_args curcontext="$curcontext" \
       _last_nmatches=-1 _last_menu_style _def_menu_style _menu_style sel \
@@ -31,6 +31,9 @@ local ctxt post ret=1 tmp _compskip format _comp_ignore \
 
 typeset -U _lastdescr
 
+_comp_opts=()
+_comp_tries=()
+
 [[ -z "$curcontext" ]] && curcontext=:::
 
 # Special completion contexts after `~' and `='.
diff --git a/Completion/Core/_multi_parts b/Completion/Core/_multi_parts
index 9e5906ac2..1c02e7e39 100644
--- a/Completion/Core/_multi_parts
+++ b/Completion/Core/_multi_parts
@@ -14,7 +14,7 @@ typeset -U tmp2
 # Get the options.
 
 zparseopts -D -a sopts \
-    'J:=group' 'V:=group' 'X:=expl' 'P:=opts' 'F:=opts' \
+    'J+:=group' 'V+:=group' 'X+:=expl' 'P:=opts' 'F:=opts' \
     S: r: R: q 1 2 n f 'M+:=match' 'i=imm'
 
 sopts=( "$sopts[@]" "$opts[@]" )
diff --git a/Completion/Core/_options b/Completion/Core/_options
index 8664e239e..70e106247 100644
--- a/Completion/Core/_options
+++ b/Completion/Core/_options
@@ -4,6 +4,5 @@
 
 local expl
 
-_wanted zsh-options expl 'zsh option' &&
-    compadd "$expl[@]" "$@" -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' - \
-        "${(@k)options}"
+_wanted zsh-options expl 'zsh option' \
+    compadd "$@" -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' - "${(@k)options}"
diff --git a/Completion/Core/_parameters b/Completion/Core/_parameters
index c7875abcf..1e430dfc1 100644
--- a/Completion/Core/_parameters
+++ b/Completion/Core/_parameters
@@ -3,10 +3,6 @@
 # This should be used to complete parameter names if you need some of the
 # extra options of compadd. It completes only non-local parameters.
 
-local pars expl
+local expl
 
-_wanted parameters expl parameter || return 1
-
-pars=( ${(k)parameters[(R)^*local*]} )
-
-compadd "$expl[@]" "$@" - $pars
+_wanted parameters expl parameter compadd "$@" - ${(k)parameters[(R)^*local*]}
diff --git a/Completion/Core/_path_files b/Completion/Core/_path_files
index ad956bb72..21ca05529 100644
--- a/Completion/Core/_path_files
+++ b/Completion/Core/_path_files
@@ -20,7 +20,7 @@ exppaths=()
 zparseopts -a mopts \
     'P:=pfxsfx' 'S:=pfxsfx' 'q=pfxsfx' 'r:=pfxsfx' 'R:=pfxsfx' \
     'W:=prepaths' 'F:=ignore' 'M+:=matcher' \
-    J: V: X: 1: 2: n: 'f=tmp1' '/=tmp1' 'g+:-=tmp1'
+    J+: V+: X+: 1: 2: n: 'f=tmp1' '/=tmp1' 'g+:-=tmp1'
 
 sopt="-${(@j::M)${(@)tmp1#-}#?}"
 (( $tmp1[(I)-[/g]*] )) && haspats=yes
@@ -54,20 +54,6 @@ if (( $#ignore )); then
   fi
 fi  
 
-if [[ -z "$_file_pat_checked" ]] &&
-   zstyle -s ":completion:${curcontext}:files" file-patterns tmp1 &&
-   [[ -n "$tmp1" ]]; then
-  if [[ "$tmp1" = '*(-/)' ]]; then
-    gopt=''
-    sopt=-/
-  else
-    gopt=yes
-    sopt=-
-  fi
-  pats=( $=tmp1 )
-  haspats=yes
-fi
-
 # If we were given no file selection option, we behave as if we were given
 # a `-f'.
 
@@ -155,7 +141,7 @@ eorig="$orig"
 
 # If given no `-F' option, we may want to use $fignore, turned into patterns.
 
-[[ $#ignore -eq 0 && -z $gopt && -n $FIGNORE ]] && 
+[[ $#ignore -eq 0 && ( -z $gopt || "$pats" = \ #\*\ # ) && -n $FIGNORE ]] && 
    ignore=( "?*${^fignore[@]}" )
 
 if (( $#ignore )); then
diff --git a/Completion/Core/_requested b/Completion/Core/_requested
index b5efb5a9e..41122819a 100644
--- a/Completion/Core/_requested
+++ b/Completion/Core/_requested
@@ -1,15 +1,20 @@
 #autoload
 
-local tag
+local gopt=-J
 
-if [[ "$1" = -[VJ]* ]]; then
-  tag="$2"
-else
-  tag="$1"
+if [[ "$1" = -([12]|)[VJ] ]]; then
+  gopt="$1"
+  shift
 fi
 
-comptags -R "$tag" && _comp_tags="$_comp_tags $tag" &&
-    if [[ $# -gt 1 ]]; then
-      _description "$@"
-      return 0
-    fi
+if comptags -R "$1"; then
+  _comp_tags="$_comp_tags $1"
+  if [[ $# -gt 3 ]]; then
+    _loop "$gopt" "$@"
+  elif [[ $# -gt 1 ]]; then
+    _description "$gopt" "$@"
+  fi
+  return 0
+else
+  return 1
+fi
diff --git a/Completion/Core/_sep_parts b/Completion/Core/_sep_parts
index 11fb20ab6..2ea0e6c68 100644
--- a/Completion/Core/_sep_parts
+++ b/Completion/Core/_sep_parts
@@ -23,7 +23,7 @@ local matchflags opt group expl nm=$compstate[nmatches] opre osuf opts match
 # Get the options.
 
 zparseopts -D -a opts \
-    'J:=group' 'V:=group' P: F: S: r: R: q 1 2 n 'X:=expl' 'M+:=match'
+    'J+:=group' 'V+:=group' P: F: S: r: R: q 1 2 n 'X+:=expl' 'M+:=match'
 
 if (( $#match )); then
   match="${match[2]}"
diff --git a/Completion/Core/_set_options b/Completion/Core/_set_options
index ae4d3784e..ea851d64a 100644
--- a/Completion/Core/_set_options
+++ b/Completion/Core/_set_options
@@ -6,6 +6,5 @@
 
 local expl
 
-_wanted zsh-options expl 'set zsh option' &&
-    compadd "$expl[@]" "$@" -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' - \
-            $=_set_options
+_wanted zsh-options expl 'set zsh option' \
+    compadd "$@" -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' - $=_set_options
diff --git a/Completion/Core/_setup b/Completion/Core/_setup
index 5d63b97ce..0b9e5d0a9 100644
--- a/Completion/Core/_setup
+++ b/Completion/Core/_setup
@@ -18,42 +18,34 @@ if zstyle -a ":completion:${curcontext}:$1" list-colors val; then
 
 fi
 
-if zstyle -s ":completion:${curcontext}:$1" list-packed val; then
-  if [[ "$val" = (yes|true|1|on) ]]; then
-    compstate[list]="${compstate[list]} packed"
-  else
-    compstate[list]="${compstate[list]:gs/packed//}"
-  fi
+if zstyle -t ":completion:${curcontext}:$1" list-packed; then
+  compstate[list]="${compstate[list]} packed"
+elif [[ $? -eq 1 ]]; then
+  compstate[list]="${compstate[list]:gs/packed//}"
 else
   compstate[list]="$_saved_list"
 fi
 
-if zstyle -s ":completion:${curcontext}:$1" list-rows-first val; then
-  if [[ "$val" = (yes|true|1|on) ]]; then
-    compstate[list]="${compstate[list]} rows"
-  else
-    compstate[list]="${compstate[list]:gs/rows//}"
-  fi
+if zstyle -t ":completion:${curcontext}:$1" list-rows-first; then
+  compstate[list]="${compstate[list]} rows"
+elif [[ $? -eq 1 ]]; then
+  compstate[list]="${compstate[list]:gs/rows//}"
 else
   compstate[list]="$_saved_list"
 fi
 
-if zstyle -s ":completion:${curcontext}:$1" last-prompt val; then
-  if [[ "$val" = (yes|true|1|on) ]]; then
-    compstate[last_prompt]=yes
-  else
-    compstate[last_prompt]=''
-  fi
+if zstyle -t ":completion:${curcontext}:$1" last-prompt; then
+  compstate[last_prompt]=yes
+elif [[ $? -eq 1 ]]; then
+  compstate[last_prompt]=''
 else
   compstate[last_prompt]="$_saved_lastprompt"
 fi
 
-if zstyle -s ":completion:${curcontext}:$1" accept-exact val; then
-  if [[ "$val" = (yes|true|1|on) ]]; then
-    compstate[exact]=accept
-  else
-    compstate[exact]=''
-  fi
+if zstyle -t ":completion:${curcontext}:$1" accept-exact; then
+  compstate[exact]=accept
+elif [[ $? -eq 1 ]]; then
+  compstate[exact]=''
 else
   compstate[exact]="$_saved_exact"
 fi
diff --git a/Completion/Core/_tags b/Completion/Core/_tags
index 6e3966074..b74e70264 100644
--- a/Completion/Core/_tags
+++ b/Completion/Core/_tags
@@ -50,21 +50,31 @@ if (( $# )); then
              fi
              ;;
       \!*)   comptry "${(@)argv:#(${(j:|:)~${=tag[2,-1]}})}";;
-      ?*)    comptry ${=tag};;
+      ?*)    comptry ${${(ps: :)${tag//\\\\ /$'\0'}}//$'\0'/ };;
       esac
     done
 
-    [[ -z "$nodef" ]] && comptry "$@"
+    if [[ -z "$nodef" ]]; then
+      if (( $+_comp_default_tags )); then
+        for tag in "$_comp_default_tags[@]"; do
+          comptry "$tag"
+        done
+      else
+        comptry "$@"
+      fi
+    fi
   else
 
-    # The first ones give the default behaviour.
-
-    comptry arguments values
-    comptry options
-    comptry globbed-files
-    comptry directories
-    comptry all-files
+    # Use default tags...
 
+    if (( $+_comp_default_tags )); then
+      for tag in "$_comp_default_tags[@]"; do
+        comptry "$tag"
+      done
+    else
+      comptry arguments values
+      comptry options
+    fi
     comptry "$@"
   fi
 
diff --git a/Completion/Core/_unset_options b/Completion/Core/_unset_options
index 8c8ed780d..d06866517 100644
--- a/Completion/Core/_unset_options
+++ b/Completion/Core/_unset_options
@@ -6,6 +6,5 @@
 
 local expl
 
-_wanted zsh-options expl 'unset zsh option' &&
-    compadd "$expl[@]" "$@" -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' - \
-            $=_unset_options
+_wanted zsh-options expl 'unset zsh option' \
+    compadd "$@" -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' - $=_unset_options
diff --git a/Completion/Core/_wanted b/Completion/Core/_wanted
index 400daa701..1d6dcdb59 100644
--- a/Completion/Core/_wanted
+++ b/Completion/Core/_wanted
@@ -1,6 +1,6 @@
 #autoload
 
-local targs tag
+local targs gopt=-J
 
 if [[ "$1" = -C?* ]]; then
   targs=( -C "${1[3,-1]}" )
@@ -12,15 +12,22 @@ else
   targs=()
 fi
 
-if [[ "$1" = -[VJ]* ]]; then
-  tag="$2"
-else
-  tag="$1"
+if [[ "$1" = -([12]|)[VJ] ]]; then
+  gopt="$1"
+  shift
 fi
 
-if [[ $# -gt 1 ]]; then
-  _tags "$targs[@]" "$tag" && _comp_tags="$_comp_tags $tag" &&
-    _description "$@"
+if [[ $# -gt 3 ]]; then
+  if _tags "$targs[@]" "$1"; then
+    _comp_tags="$_comp_tags $1"
+
+    _loop -t "$gopt" "$@"
+  else
+    return 1
+  fi
+elif [[ $# -gt 1 ]]; then
+  _tags "$targs[@]" "$1" && _comp_tags="$_comp_tags $1" &&
+    _description "$gopt" "$@"
 else
-  _tags "$targs[@]" "$tag" && _comp_tags="$_comp_tags $tag"
+  _tags "$targs[@]" "$1" && _comp_tags="$_comp_tags $1"
 fi
diff --git a/Completion/Debian/_apt b/Completion/Debian/_apt
index be7973c34..7ed7b8974 100644
--- a/Completion/Debian/_apt
+++ b/Completion/Debian/_apt
@@ -75,7 +75,7 @@ _apt_arguments () {
   nul=$'\0'
   qnul="\$'\\0'"
 
-  comp_bool='_tags values && compadd "$expl_bool[@]" '"$bool"
+  comp_bool='_wanted values && compadd "$expl_bool[@]" '"$bool"
   comp_intlevel= #"_message 'intlevel'"
   comp_configfile='_files "$expl_configfile[@]"'
   comp_arbitem= #"_message 'Foo::Bar=bar'"
@@ -384,7 +384,7 @@ _apt-get () {
     /$'check\0'/ \| \
     /$'source\0'/ /$'[^\0]#\0'/ :'_deb_packages "$expl_packages[@]" avail' \# \| \
     /$'help\0/' \| \
-    /"[]"/	:'_tags actions && compadd "$expl_action[@]" update upgrade install remove dist-upgrade dselect-upgrade clean autoclean check source help'
+    /"[]"/	:'_wanted actions expl_action action compadd update upgrade install remove dist-upgrade dselect-upgrade clean autoclean check source help'
 
   _apt-get () {
     local expl_action expl_packages
@@ -422,7 +422,7 @@ _apt-cache () {
     /$'search\0'/ /$'[^\0]#\0'/ :'_message "pattern"' \| \
     /$'show\0'/ /$'[^\0]#\0'/ :'_deb_packages "$expl_packages[@]" avail' \# \| \
     /$'depends\0'/ \| \
-    /"[]"/ :'_tags actions && compadd "$expl_action[@]" help add gencaches showpkg stats dump dumpavail unmet check search show depends'
+    /"[]"/ :'_wanted actions expl_action action compadd help add gencaches showpkg stats dump dumpavail unmet check search show depends'
 
   _apt-cache () {
     local expl_action expl_packages expl_pkg_cache expl_src_cache
@@ -451,7 +451,7 @@ _apt-cdrom () {
     -o,--option:arbitem \
     -- \
     /$'add\0'/ \| \
-    /"[]"/	:'_tags actions && compadd "$expl_action[@]" add'
+    /"[]"/	:'_wanted actions expl_action action compadd add'
 
   _apt-cdrom () {
     local expl_action expl_mount_point
@@ -473,11 +473,11 @@ _apt-config () {
     -- \
     /$'shell\0'/ \
       \( \
-	/$'[^\0]#\0'/ :'_tags parameters && compadd "$expl_shell_var[@]" - "${(@k)parameters}"' \
-	/$'[^\0]#\0'/ :'_tags configuration-keys && compadd "$expl_config_key[@]" - ${${(f)"$(apt-config dump 2>&1)"}% *}' \
+	/$'[^\0]#\0'/ :'_wanted parameters expl_shell_var "shell variable to assign" compadd - "${(@k)parameters}"' \
+	/$'[^\0]#\0'/ :'_wanted configuration-keys expl_config_key "configuration key" compadd - ${${(f)"$(apt-config dump 2>&1)"}% *}' \
       \) \# \| \
     /$'dump\0'/ \| \
-    /"[]"/	:'_tags actions && compadd "$expl_action[@]" shell dump'
+    /"[]"/	:'_wanted actions expl_action action compadd shell dump'
 
   _apt-config () {
     local expl_action expl_shell_var expl_config_key
diff --git a/Completion/Debian/_deb_packages b/Completion/Debian/_deb_packages
index 7973d9868..3d742aa2c 100644
--- a/Completion/Debian/_deb_packages
+++ b/Completion/Debian/_deb_packages
@@ -51,7 +51,7 @@ _deb_packages () {
 
   _deb_packages_update_$pkgset
 
-  _tags packages && compadd "$expl[@]" - "${(@P)cachevar}"
+  _wanted packages && compadd "$expl[@]" - "${(@P)cachevar}"
 }
 
 _deb_packages "$@"
diff --git a/Completion/Linux/_rpm b/Completion/Linux/_rpm
index d5978eb0b..e23768185 100644
--- a/Completion/Linux/_rpm
+++ b/Completion/Linux/_rpm
@@ -189,12 +189,12 @@ while [[ -n "$state" ]]; do
     state=package_file
     ;&
   package)
-    _wanted packages expl 'RPM package' &&
-        compadd "$expl[@]" -M 'r:|-=* r:|=*' - $(_call packages rpm -qa) && ret=0
+    _wanted packages expl 'RPM package' \
+        compadd -M 'r:|-=* r:|=*' - $(_call packages rpm -qa) && ret=0
     ;;
   package_file)
     if compset -P ftp://; then
-      _tags hosts && _hosts -S/ && ret=0
+      _hosts -S/ && ret=0
     else
       _alternative \
           'files:RPM package file:_files -g \*.\(\#i\)rpm' \
@@ -203,8 +203,8 @@ while [[ -n "$state" ]]; do
     ;;
   tags)
     if compset -P '*\{'; then
-      _wanted tags expl 'RPM tag' &&
-          compadd "$expl[@]" -M 'm:{a-z}={A-Z}' -S '\}' - \
+      _wanted tags expl 'RPM tag' \
+          compadd -M 'm:{a-z}={A-Z}' -S '\}' - \
                   "${(@)${(@f)$(_call tags rpm --querytags)}#RPMTAG_}" && ret=0
     else
       _message 'RPM format'
@@ -220,8 +220,6 @@ while [[ -n "$state" ]]; do
       _description directories expl 'old path'
     fi
 
-    _tags directories || return 1
-
     _files "$expl[@]" -/ && ret=0
     ;;
   esac
diff --git a/Completion/User/_archie b/Completion/User/_archie
index 57a5db494..cddd7680d 100644
--- a/Completion/User/_archie
+++ b/Completion/User/_archie
@@ -26,6 +26,6 @@ case "$state" in
 serverhost)
   : ${(A)archie_servers:=${(M)$(_call hosts archie -L):#archie.*}}
 
-  _wanted hosts expl 'archie servers' && compadd "$expl[@]" -  $archie_servers
+  _wanted hosts expl 'archie servers' compadd -  $archie_servers
   ;;
 esac
diff --git a/Completion/User/_cvs b/Completion/User/_cvs
index 7d55a7635..41a1b8a97 100644
--- a/Completion/User/_cvs
+++ b/Completion/User/_cvs
@@ -34,7 +34,7 @@ _cvs_command () {
 	watchers "")
 
   if (( CURRENT == 1 )); then
-    _tags commands && { compadd "$@" ${(k)cmds} || compadd "$@" ${(kv)=cmds} }
+    _wanted commands && { compadd "$@" ${(k)cmds} || compadd "$@" ${(kv)=cmds} }
   else
     local curcontext="$curcontext"
 
@@ -371,7 +371,7 @@ _cvs_watch () {
   local expl
 
   if (( CURRENT == 2 )); then
-    _wanted values expl 'watch comamnd' && compadd on off add remove
+    _wanted values expl 'watch command' compadd on off add remove
   else
     case "$words[2]" in
       on|off) # "+lR"
@@ -427,14 +427,14 @@ _cvs_root () {
     fi
   fi
 
-  _tags files && {
+  _wanted files && {
     compadd -M 'r:|[:@./]=* r:|=*' "$@" $_cvs_roots || _files "$@" -/
   }
 }
 
 (( $+functions[_cvs_tempdir] )) ||
 _cvs_tempdir () {
-  _tags directories && compadd "$@" $TMPPREFIX:h $TMPDIR /tmp
+  _wanted directories && compadd "$@" $TMPPREFIX:h $TMPDIR /tmp
 }
 
 (( $+functions[_cvs_user_variable] )) ||
@@ -450,29 +450,29 @@ _cvs_user_variable () {
 
 (( $+functions[_cvs_bindir] )) ||
 _cvs_bindir () {
-  _tags directories && { compadd "$@" /usr/local/bin || _files "$@" -/ }
+  _wanted directories && { compadd "$@" /usr/local/bin || _files "$@" -/ }
 }
 
 (( $+functions[_cvs_editor] )) ||
 _cvs_editor () {
-  _tags commands && compadd "$@" vi
+  _wanted commands && compadd "$@" vi
 }
 
 (( $+functions[_cvs_gzip_level] )) ||
 _cvs_gzip_level () {
-  _tags values && compadd "$@" 9
+  _wanted values && compadd "$@" 9
 }
 
 # define completion functions for cvs common options and arguments.
 
 (( $+functions[_cvs_D] )) ||
 _cvs_D () {
-  _tags values && compadd "$@" today yesterday week\ ago month\ ago
+  _wanted values && compadd "$@" today yesterday week\ ago month\ ago
 }
 
 (( $+functions[_cvs_k] )) ||
 _cvs_k () {
-  _tags values && compadd "$@" kv kvl k o b v
+  _wanted values && compadd "$@" kv kvl k o b v
 }
 
 (( $+functions[_cvs_m] )) ||
@@ -489,9 +489,8 @@ _cvs_modules () {
   if [[ $root = :* || ! -d $root ]]; then
     _message "module name"
   else
-    _wanted modules expl module &&
-        compadd "$expl[@]" - \
-            $root/^CVSROOT(:t) \
+    _wanted modules expl module \
+        compadd - $root/^CVSROOT(:t) \
             ${${(M)${(f)"$(<$root/CVSROOT/modules)"}:#[^#]*}%%[ 	]*}
   fi
 }
@@ -500,7 +499,7 @@ _cvs_modules () {
 _cvs_revisions () {
   local expl
 
-  _wanted values expl revision &&
+  _wanted values expl revision \
       compadd - ${${${(M)${(f)"$(cvs -q status -vl .)"}:#	*}##[ 	]##(No Tags Exist)#}%%[ 	]*}
 }
 
@@ -618,7 +617,7 @@ _cvs_files_removed () {
     local omit
     omit=(${pref}*(D:t))
     eval 'entries=(${entries:#('${(j:|:)${(@)omit:q}}')})'
-    _tags directories && compadd "$@" -P "$qpref" - ${entries:q} ||
+    _wanted directories && compadd "$@" -P "$qpref" - ${entries:q} ||
         _cvs_directories "$@"
   else
     _files "$@"
diff --git a/Completion/User/_dd b/Completion/User/_dd
index fa322d791..419fc1a7a 100644
--- a/Completion/User/_dd
+++ b/Completion/User/_dd
@@ -6,9 +6,8 @@ if compset -P 1 'conv='; then
   # If there's a comma present, ignore up to the last one.  The
   # test alone will have that effect.
   compset -p '*,'
-  _wanted values expl conversion &&
-      compadd "$expl[@]" -qS, -q \
-              ascii ebcdic ibm block unblock lcase ucase swab noerror sync
+  _wanted values expl conversion \
+      compadd -qS, ascii ebcdic ibm block unblock lcase ucase swab noerror sync
 elif compset -P 1 'if='; then
   _description files expl 'input file'
   _tilde_files "$expl[@]"
@@ -16,6 +15,6 @@ elif compset -P 1 'of='; then
   _description files expl 'output file'
   _tilde_files "$expl[@]"
 else
-  _wanted values expl option &&
-      compadd "$expl[@]" -S '=' if of ibs obs bs cbs skip files seek count conv
+  _wanted values expl option \
+      compadd -S '=' if of ibs obs bs cbs skip files seek count conv
 fi
diff --git a/Completion/User/_domains b/Completion/User/_domains
index cf7e9befe..3cc64db07 100644
--- a/Completion/User/_domains
+++ b/Completion/User/_domains
@@ -16,5 +16,5 @@ if ! zstyle -a ":completion:${curcontext}:domains" domains domains; then
   domains=( "$_cache_domains[@]" )
 fi
 
-_wanted domains expl domain &&
-    compadd -M 'm:{a-zA-Z}={A-Za-z} r:|.=* r:|=*' "$@" "$expl[@]" - "$domains[@]"
+_wanted domains expl domain \
+    compadd -M 'm:{a-zA-Z}={A-Za-z} r:|.=* r:|=*' "$@" - "$domains[@]"
diff --git a/Completion/User/_gcc b/Completion/User/_gcc
index 7292a933c..f826f9793 100644
--- a/Completion/User/_gcc
+++ b/Completion/User/_gcc
@@ -273,8 +273,8 @@ dump)
     'p[annotate assembler output]' && ret=0
   ;;
 library)
-  _wanted libraries expl library &&
-      compadd "$expl[@]" - ${^=LD_LIBRARY_PATH:-/usr/lib /usr/local/lib}/lib*.(a|so*)(:t:fr:s/lib//) && ret=0
+  _wanted libraries expl library \
+      compadd - ${^=LD_LIBRARY_PATH:-/usr/lib /usr/local/lib}/lib*.(a|so*)(:t:fr:s/lib//) && ret=0
   ;;
 esac
 
diff --git a/Completion/User/_gdb b/Completion/User/_gdb
index 283aff631..2fd09cbc5 100644
--- a/Completion/User/_gdb
+++ b/Completion/User/_gdb
@@ -10,18 +10,21 @@ local cur="$words[CURRENT]" prev w list ret=1 expl
 if compset -P '-(cd|directory)='; then
   _files -/
 elif compset -P '-tty='; then
-  _wanted devices expl 'terminal device' && compadd "$expl[@]" - /dev/tty*
+  _wanted devices expl 'terminal device' compadd - /dev/tty*
 elif compset -P '-(exec|se)='; then
   _description files expl executable
   _files "$expl[@]" -g '*(-*)'
 elif compset -P '-(symbols|core|command)='; then
   _files
 elif [[ "$PREFIX" = -* ]]; then
-  if _wanted options expl option; then
-    compadd "$expl[@]" -QS '' - -symbols\= -exec\= -se\= -core\= -command\= \
-                                -directory\= -cd\= -tty\=
-    compadd "$expl[@]"        - -help -h -s -e -c -x -d -nx -n -quiet -q \
-	  		        -batch -fullname -f -b
+  if _wanted options; then
+    while _try options expl option; do
+      compadd "$expl[@]" -QS '' - -symbols\= -exec\= -se\= -core\= -command\= \
+                                  -directory\= -cd\= -tty\= && ret=0
+      compadd "$expl[@]"        - -help -h -s -e -c -x -d -nx -n -quiet -q \
+	    		          -batch -fullname -f -b && ret=0
+      (( ret )) || return 0
+    done
   fi
 else
   prev="$words[CURRENT-1]"
@@ -31,10 +34,9 @@ else
   (-[csx]) _files && return 0 ;;
   (-e)     _description files expl executable
            _files "$expl[@]" -g '*(-*)' && return 0 ;;
-  (-b)     _wanted -V values expl 'baud rate' &&
-               compadd "$expl[@]" 0 50 75 110 134 150 200 300 600 1200 1800 \
-			          2400 4800 9600 19200 38400 57600 115200 \
-			          230400 && return 0 ;;
+  (-b)     _wanted -V values expl 'baud rate' \
+               compadd 0 50 75 110 134 150 200 300 600 1200 1800 2400 4800 \
+		       9600 19200 38400 57600 115200 230400 && return 0 ;;
   esac
 
   w=( "${(@)words[2,-1]}" )
diff --git a/Completion/User/_getconf b/Completion/User/_getconf
index 7ce709588..3a635368f 100644
--- a/Completion/User/_getconf
+++ b/Completion/User/_getconf
@@ -1,20 +1,19 @@
 #compdef getconf
 
-local expl
+local expl ret=1
 
 if [[ CURRENT -eq 2 ]]; then
   _tags syswideconfig pathconfig standardsconfig
 
   while _tags; do
-    if _requested -V syswideconfig expl 'systemwide configuration variables'
-    then
-      compadd "$expl[@]" -S '' ARG_MAX BC_BASE_MAX BC_DIM_MAX BC_SCALE_MAX \
+    _requested -V syswideconfig expl 'systemwide configuration variables' \
+      compadd -S '' ARG_MAX BC_BASE_MAX BC_DIM_MAX BC_SCALE_MAX \
           BC_STRING_MAX CHILD_MAX COLL_WEIGHTS_MAX EXPR_NEST_MAX LINE_MAX \
-	  NGROUPS_MAX OPEN_MAX RE_DUP_MAX STREAM_MAX TZNAME_MAX
-    fi
-    if _requested -V standardsconfig \
-        expl 'system-standards configuration variables'; then
-      compadd "$expl[@]" -S '' _POSIX_CHILD_MAX _POSIX_LINK_MAX \
+	  NGROUPS_MAX OPEN_MAX RE_DUP_MAX STREAM_MAX TZNAME_MAX && ret=0
+
+    _requested -V standardsconfig \
+        expl 'system-standards configuration variables' \
+      compadd -S '' _POSIX_CHILD_MAX _POSIX_LINK_MAX \
           _POSIX_MAX_CANON _POSIX_MAX_INPUT _POSIX_NAME_MAX _POSIX_NGROUPS_MAX \
 	  _POSIX_OPEN_MAX _POSIX_PATH_MAX _POSIX_PIPE_BUF _POSIX_SSIZE_MAX \
 	  _POSIX_STREAM_MAX _POSIX_TZNAME_MAX _POSIX_VERSION \
@@ -22,15 +21,17 @@ if [[ CURRENT -eq 2 ]]; then
 	  POSIX2_BC_STRING_MAX POSIX2_COLL_WEIGHTS_MAX POSIX2_EXPR_NEST_MAX \
 	  POSIX2_LINE_MAX POSIX2_RE_DUP_MAX POSIX2_VERSION POSIX2_C_BIND \
 	  POSIX2_C_DEV POSIX2_FORT_DEV POSIX2_FORT_RUN POSIX2_LOCALEDEF \
-	  POSIX2_SW_DEV _XOPEN_VERSION
-    fi
-    if _requested -V pathconfig expl 'system path configuration variables'
-    then
-      compadd "$expl[@]" -S '' PIPE_BUF _POSIX_CHOWN_RESTRICTED \
-          _POSIX_NO_TRUNC _POSIX_VDISABLE
-      compadd "$expl[@]" -S ' ' LINK_MAX MAX_CANON MAX_INPUT NAME_MAX PATH_MAX \
-          PIPE_BUF
-    fi
+	  POSIX2_SW_DEV _XOPEN_VERSION && ret=0
+
+    _requested pathconfig &&
+        while _try -V pathconfig expl 'system path configuration variables'; do
+          compadd "$expl[@]" -S '' PIPE_BUF _POSIX_CHOWN_RESTRICTED \
+                                   _POSIX_NO_TRUNC _POSIX_VDISABLE && ret=0
+          compadd "$expl[@]" -S ' ' LINK_MAX MAX_CANON MAX_INPUT NAME_MAX \
+                                    PATH_MAX PIPE_BUF && ret=0
+          (( ret )) || break
+        done
+    (( ret )) || return 0
   done
 else
   _files -/
diff --git a/Completion/User/_gprof b/Completion/User/_gprof
index 80de70bb4..67fbb99eb 100644
--- a/Completion/User/_gprof
+++ b/Completion/User/_gprof
@@ -17,7 +17,7 @@ _arguments -C -s -{a,b,c,D,h,i,l,L,s,T,v,w,x,y,z} \
 if [[ -n "$state" ]]; then
   local cmd pair expl
 
-  _tags functions || return 1
+  _wanted functions || return 1
 
   [[ "$state" = pair ]] && pair=yes
 
diff --git a/Completion/User/_groups b/Completion/User/_groups
index 185b06549..748536f3b 100644
--- a/Completion/User/_groups
+++ b/Completion/User/_groups
@@ -2,7 +2,7 @@
 
 local expl groups tmp
 
-_wanted groups expl group || return 1
+_wanted groups || return 1
 
 if ! zstyle -a ":completion:${curcontext}:" groups groups; then
   (( $+_cache_groups )) ||
@@ -16,4 +16,4 @@ if ! zstyle -a ":completion:${curcontext}:" groups groups; then
   groups=( "$_cache_groups[@]" )
 fi
 
-compadd "$@" "$expl[@]" - "$groups[@]"
+_loop groups expl group compadd "$@" - "$groups[@]"
diff --git a/Completion/User/_gs b/Completion/User/_gs
index 8ae5a65f9..52345cdbb 100644
--- a/Completion/User/_gs
+++ b/Completion/User/_gs
@@ -25,8 +25,8 @@ else
     if [[ "$PREFIX" = *\=* ]]; then
       _message 'systemdict definition value'
     else
-      _wanted names expl 'systemdict definition name' &&
-          compadd "$expl[@]" -M 'm:{a-z}={A-Z}' - \
+      _wanted names expl 'systemdict definition name' \
+          compadd -M 'm:{a-z}={A-Z}' - \
                   DISKFONTS NOCACHE NOBIND NODISPLAY NOPAUSE PLATFONTS SAFER \
                   WRITESYSTEMDICT && ret=0
     fi
@@ -35,8 +35,8 @@ else
     if compset -P '*='; then
       case "$IPREFIX" in
       *DEVICE\=)
-        _wanted devices expl 'ghostscript device' &&
-            compadd "$expl[@]" - "${(@)${=${$(_call devices gs -h)##* devices:}%%Search path:*}:#}" && ret=0
+        _wanted devices expl 'ghostscript device' \
+            compadd - "${(@)${=${$(_call devices gs -h)##* devices:}%%Search path:*}:#}" && ret=0
         ;;
       *OutputFile\=)
         _description files expl 'output file'
@@ -47,9 +47,8 @@ else
         return 1
       esac
     else
-      _wanted names expl 'systemdict name' &&
-          compadd "$expl[@]" -S\= -M 'm:{a-z}={A-Z}' - DEVICE OutputFile &&
-              ret=0
+      _wanted names expl 'systemdict name' \
+          compadd -S\= -M 'm:{a-z}={A-Z}' - DEVICE OutputFile && ret=0
     fi
     ;;
   esac
diff --git a/Completion/User/_hosts b/Completion/User/_hosts
index cab65329c..c90493d21 100644
--- a/Completion/User/_hosts
+++ b/Completion/User/_hosts
@@ -9,5 +9,5 @@ if ! zstyle -a ":completion:${curcontext}:hosts" hosts hosts; then
   hosts=( "$_cache_hosts[@]" )
 fi
 
-_wanted hosts expl host &&
-    compadd -M 'm:{a-zA-Z}={A-Za-z} r:|.=* r:|=*' "$@" "$expl[@]" - "$hosts[@]"
+_wanted hosts expl host \
+    compadd -M 'm:{a-zA-Z}={A-Za-z} r:|.=* r:|=*' "$@" - "$hosts[@]"
diff --git a/Completion/User/_lp b/Completion/User/_lp
index 51fbb1616..3ff814cbb 100644
--- a/Completion/User/_lp
+++ b/Completion/User/_lp
@@ -36,14 +36,15 @@ if (( ! $+_lp_cache )); then
 fi
 
 if compset -P -P || [[ "$words[CURRENT-1]" = -P ]]; then
-  if _wanted printers expl printer; then
+  if _wanted printers; then
     if zstyle -T ":completion:${curcontext}:printers" verbose; then
       zformat -a list ' -- ' "$_lp_cache[@]"
       disp=(-ld list)
     else
       disp=()
     fi
-    compadd "$expl[@]" "$disp[@]" - "${(@)_lp_cache%%:*}" && return 0
+    _loop printers expl printer \
+        compadd "$disp[@]" - "${(@)_lp_cache%%:*}" && return 0
 
     (( $+_lp_alias_cache )) || return 1
 
@@ -70,7 +71,7 @@ else
       _tags users jobs
 
       while _tags; do
-        if _requested users expl user; then
+        if _requested users; then
           strs=( "${(@)${(@)list##[^ 	]##[ 	]##[^ 	]##[ 	]##}%%[ 	]*}" )
           if [[ -z "$shown" ]] &&
              zstyle -T ":completion:${curcontext}:users" verbose; then
@@ -79,9 +80,10 @@ else
           else
   	  disp=()
           fi
-          compadd "$expl[@]" "$disp[@]" - "$strs[@]" || _users && ret=0
+	  _loop users expl user compadd "$disp[@]" - "$strs[@]" ||
+              _users && ret=0
         fi
-        if _requested jobs expl job; then
+        if _requested jobs; then
           strs=( "${(@)${(@)list##[^ 	]##[ 	]##[^ 	]##[ 	]##[^ 	]##[ 	]##}%%[ 	]*}" )
           if [[ -z "$shown" ]] &&
              zstyle -T ":completion:${curcontext}:jobs" verbose; then
@@ -90,7 +92,7 @@ else
           else
   	  disp=()
           fi
-          compadd "$expl[@]" "$disp[@]" - "$strs[@]" && ret=0
+          _loop jobs expl job compadd "$disp[@]" - "$strs[@]" && ret=0
         fi
         (( ret )) || return 0
       done
diff --git a/Completion/User/_mailboxes b/Completion/User/_mailboxes
index 3f798c2d7..784bc4e6e 100644
--- a/Completion/User/_mailboxes
+++ b/Completion/User/_mailboxes
@@ -2,7 +2,7 @@
 
 _mailboxes() {
   #emulate -L zsh
-  local expl nm="$compstate[nmatches]"
+  local expl ret=1
   local pinedirectory="${pinedirectory:-~/mail}"
   local maildirectory="${maildirectory:-~/Mail}"
 
@@ -40,15 +40,14 @@ _mailboxes() {
   esac
 
   while _tags; do
-    if _requested mailboxes expl 'mailbox specification'; then
-      _mua_mailboxes "$expl[@]"
-    fi
+    _requested mailboxes expl 'mailbox specification' _mua_mailboxes && ret=0
+
     if _requested files expl 'mailbox file'; then
       [[ "${curcontext}" != *:(mail|mush|zmail|zmlite):* ]] &&
 	compset -P -f
-      _path_files "$expl[@]"
+      _files "$expl[@]" && ret=0
     fi
-    [[ nm -ne $compstate[nmatches] ]] && return 0
+    (( ret )) || return 0
   done
 
   return 1
@@ -96,6 +95,7 @@ _mua_mailboxes() {
 
   local -a mbox_short
   local -aU mbox_names
+  local ret=1
 
   case "${curcontext}" in
     (*:elm:*) # I've probably got this wrong, or at least incomplete
@@ -111,7 +111,7 @@ _mua_mailboxes() {
       fi
       ;;
     (*:mh:*) # I've probably got this wrong, or at least incomplete
-      (( $#_mh_cache )) && _multi_parts "${expl[@]}" / _mh_cache
+      (( $#_mh_cache )) && _multi_parts "${expl[@]}" / _mh_cache && ret=0
       ;;
     (*:mush:*)
       if compset -P %; then
@@ -155,7 +155,6 @@ _mua_mailboxes() {
        ;;
   esac
 
-  local ret=1
   (( $#mbox_names )) && _multi_parts "$@" / mbox_names && ret=0
   (( $#mbox_short )) && compadd "$@" - "$mbox_short[@]" && ret=0
   return ret
diff --git a/Completion/User/_make b/Completion/User/_make
index aaae444a8..dc08d4e26 100644
--- a/Completion/User/_make
+++ b/Completion/User/_make
@@ -1,6 +1,6 @@
 #compdef make gmake pmake
 
-local prev="$words[CURRENT-1]" file ret=1 expl
+local prev="$words[CURRENT-1]" file expl tmp
 
 if [[ "$prev" = -[CI] ]]; then
   _files -/
@@ -18,11 +18,15 @@ else
     file=''
   fi
 
-  [[ -n "$file" ]] && _wanted targets expl 'make target' &&
-      compadd "$expl[@]" - \
+  if [[ -n "$file" ]] && _wanted targets; then
+    tmp=(
           $(awk '/^[a-zA-Z0-9][^\/ \t]+:/ {print $1}
  	      /^\.include  *<bsd\.port\.(subdir\.|pre\.)?mk>/ || /^\.include  *".*mk\/bsd\.pkg\.(subdir\.)?mk"/ {
  	        print "fetch fetch-list extract patch configure build install reinstall deinstall package describe checkpatch checksum makesum" }' \
- 	     FS=: $file) && ret=0
-  (( ret )) && { compset -P 1 '*='; _files }
+ 	     FS=: $file)
+         )
+    _loop targets expl 'make target' compadd "$tmp[@]" && return 0
+  fi
+  compset -P 1 '*='
+  _files
 fi
diff --git a/Completion/User/_man b/Completion/User/_man
index 6f62501ee..8ae97962c 100644
--- a/Completion/User/_man
+++ b/Completion/User/_man
@@ -33,5 +33,5 @@ else
   rep=( $manpath/(sman|man|cat)*/${~approx}$PREFIX${~star}$SUFFIX.<->*(N:t) )
 fi
 
-(( $#rep )) && _wanted manuals expl 'manual page' &&
-    compadd "$expl[@]" - ${rep%%.[^.]##(.gz|.bz2|)}
+(( $#rep )) && _wanted manuals expl 'manual page' \
+    compadd - ${rep%%.[^.]##(.gz|.bz2|)}
diff --git a/Completion/User/_mh b/Completion/User/_mh
index f02aee9b5..aacde38a1 100644
--- a/Completion/User/_mh
+++ b/Completion/User/_mh
@@ -17,13 +17,16 @@ if compset -P 1 -; then
   # get list of options, which MH commands can generate themselves
   # awk is just too icky to use for this, sorry.  send me one if
   # you come up with it.
-  _wanted options expl option &&
-      compadd "$expl[@]" - $($words[1] -help | perl -ne 'if (/^\s*-\(?(\S+)/) {
+  if _wanted options; then
+    _loop options expl option \
+        compadd - $($words[1] -help | perl -ne 'if (/^\s*-\(?(\S+)/) {
             $n = $1;
             $n =~ s/\)//g;
             print $n =~ s/^\[([a-z]+)\]// ? "$n\n$1$n\n" : "$n\n";
           }')
-  return
+    return
+  fi
+  return 1
 elif compset -P 1 '[+@]' || [[ "$prev" = -draftfolder ]]; then
   # Complete folder names.
   local mhpath
@@ -35,7 +38,7 @@ elif compset -P 1 '[+@]' || [[ "$prev" = -draftfolder ]]; then
     mhpath=$(mhpath)
   fi
 
-  _wanted files expl 'MH folder' && _path_files "$expl[@]" -W mhpath -/
+  _wanted files expl 'MH folder' _path_files -W mhpath -/
 elif [[ "$prev" = -(editor|(whatnow|rmm|show|more)proc) ]]; then
   _command_names -e
 elif [[ "$prev" = -file ]]; then
@@ -48,14 +51,11 @@ elif [[ "$prev" = -(form|audit|filter) ]]; then
   [[ -d $mhlib ]] || { mhlib=$(mhparam mhlproc); mhlib=$mhlib:h; }
   mhfpath=($mymhdir $mhlib)
 
-  _wanted files expl 'MH template file' &&
-    _files "$expl[@]" -W mhfpath -g '*(.)'
+  _wanted files expl 'MH template file' _files -W mhfpath -g '*(.)'
 elif [[ "$prev" = -(no|)cc ]]; then
-  _wanted -C "$prev" values expl 'CC address' &&
-      compadd "$expl[@]" all to cc me
+  _wanted -C "$prev" values expl 'CC address' compadd all to cc me
 elif [[ "$prev" = -[rw]cache ]]; then
-  _wanted -C "$prev" values expl cache &&
-      compadd "$expl[@]" public private never ask
+  _wanted -C "$prev" values expl cache compadd public private never ask
 else
   # Generate sequences.
   local foldnam folddir f ret
@@ -72,11 +72,14 @@ else
     # leaving foldnam empty works here
   fi
 
-  if _wanted sequences expl sequence; then
-    compadd "$expl[@]" $(mark $foldnam 2>/dev/null | awk -F: '{ print $1 }') &&
+  if _wanted sequences; then
+    while _try sequences expl sequence; do
+      compadd "$expl[@]" $(mark $foldnam 2>/dev/null | awk -F: '{ print $1 }') &&
         ret=0
-    compadd "$expl[@]" reply next cur prev first last all unseen && ret=0
-    _files "$expl[@]" -W folddir -g '<->' && ret=0
+      compadd "$expl[@]" reply next cur prev first last all unseen && ret=0
+      _files "$expl[@]" -W folddir -g '<->' && ret=0
+      (( ret )) || return 0
+    done
   fi
   return ret
 fi
diff --git a/Completion/User/_mount b/Completion/User/_mount
index 23b2a6378..00fb00fb5 100644
--- a/Completion/User/_mount
+++ b/Completion/User/_mount
@@ -539,11 +539,11 @@ case "$state" in
 fstype)
   compset -P '*,'
 
-  _wanted types expl 'file system type' &&
+  _wanted types expl 'file system type' \
       compadd "$expl[@]" -qS, -M 'L:|no=' - "$fss[@]" && ret=0
   ;;
 fsopt)
-  _tags options || return 1
+  _wanted options || return 1
 
   eval 'tmp=(' '"$_fs_'${(s:,:)^${opt_args[$typeops]:-${deffs}}}'[@]"' ')'
   tmp=( "$_fs_any[@]" "${(@)tmp:#}" )
diff --git a/Completion/User/_mutt b/Completion/User/_mutt
index 90e7dec08..8df7799ee 100644
--- a/Completion/User/_mutt
+++ b/Completion/User/_mutt
@@ -25,8 +25,6 @@ local curcontext="$curcontext" state line ret=1
  '-Z+:open first mailbox with new mail:' && ret=0
 
 if [[ "$state" = userhost ]]; then
-  _tags hosts || return 1
-
   if compset -P '*@'; then
     _description hosts expl 'remote host name'
     _hosts "$expl[@]" -q -S, && return 0
diff --git a/Completion/User/_mysql_utils b/Completion/User/_mysql_utils
index 6d777112d..77ed7a36e 100644
--- a/Completion/User/_mysql_utils
+++ b/Completion/User/_mysql_utils
@@ -24,33 +24,33 @@ _mysql_hosts () {
   local _mysql_user _mysql_port _mysql_host _mysql_params
   _mysql_get_identity
 
-  _wanted hosts expl 'server host' &&
+  _wanted hosts expl 'server host' \
     _combination -s '[:@]' '' hosts-ports-users \
       ${_mysql_user:+users=${_mysql_user:q}} \
       ${_mysql_port:+ports=${_mysql_port:q}} \
-      hosts "$expl[@]"
+      hosts -
 }
 
 _mysql_ports () {
   local _mysql_user _mysql_port _mysql_host _mysql_params
   _mysql_get_identity
 
-  _wanted ports expl 'server port' &&
+  _wanted ports expl 'server port' \
     _combination -s '[:@]' '' hosts-ports-users \
       ${_mysql_user:+users=${_mysql_user:q}} \
       ${_mysql_host:+hosts=${_mysql_host:q}} \
-      ports "$expl[@]"
+      ports -
 }
 
 _mysql_users () {
   local _mysql_user _mysql_port _mysql_host _mysql_params
   _mysql_get_identity
 
-  _wanted users expl 'server username' &&
+  _wanted users expl 'server username' \
     _combination -s '[:@]' '' hosts-ports-users \
       ${_mysql_host:+hosts=${_mysql_host:q}} \
       ${_mysql_port:+ports=${_mysql_port:q}} \
-      users "$expl[@]"
+      users -
 }
 
 _mysql_databases () {
@@ -205,15 +205,13 @@ _mysqladmin_commands () {
        )
 
   if (( CURRENT == 1 )); then
-    _tags commands && compadd "$@" $cmds
+    _wanted commands expl command compadd "$@" - $cmds
   else
     local curcontext="$curcontext"
 
     case "$words[1]" in
-      (create)
-      ;&
-      (drop)
-        _wanted mysqldbs expl "MySQL databases" && _mysql_databases
+      (create|drop)
+        _wanted mysqldbs expl "MySQL databases" _mysql_databases
       ;;
       (kill)
         _message 'thread ids'
diff --git a/Completion/User/_netscape b/Completion/User/_netscape
index 23601de12..715ca408a 100644
--- a/Completion/User/_netscape
+++ b/Completion/User/_netscape
@@ -40,30 +40,31 @@ if [[ "$state" = "remote" ]]; then
     openFile*) _files -W ~;;
     saveAs*) 
       if compset -P "*,"; then
-        _wanted types expl 'data type' &&
+        _wanted types expl 'data type' \
             compadd -s")" -M 'm:{a-zA-Z}={A-Za-z}' HTML Text PostScript &&
                 ret=0
       else
-        _tags files && _path_files -W ~ && ret=0
+        _files -W ~ && ret=0
       fi
     ;;
     mailto*)
       compset -P "*,"
       if compset -P '*@'; then
-        _wanted hosts expl 'remote host name' &&
-            _hosts "$expl[@]" -q -S, && ret=0
+        _wanted hosts expl 'remote host name' _hosts -q -S, && ret=0
       else
-        _wanted users expl 'login name' && _users "$expl[@]" -q -S@ && ret=0
+        _wanted users expl 'login name' _users -q -S@ && ret=0
       fi
     ;;
     *)
-      if _wanted commands expl 'remote commands'; then
+      if _wanted commands; then
         if [[ -z "$QIPREFIX" ]]; then
-	  compadd "$expl[@]" -s'(' -S '' -M 'm:{a-zA-Z}={A-Za-z}' - \
-                  $remote_commands && ret=0
+	  _loop commands expl 'remote commands' \
+  	      compadd  -s'(' -S '' -M 'm:{a-zA-Z}={A-Za-z}' - \
+                      $remote_commands && ret=0
         else
-          compadd "$expl[@]" -qS '(' -M 'm:{a-zA-Z}={A-Za-z}' - \
-                  $remote_commands && ret=0
+	  _loop commands expl 'remote commands' \
+              compadd -qS '(' -M 'm:{a-zA-Z}={A-Za-z}' - \
+                      $remote_commands && ret=0
 	fi
       fi
     ;;
@@ -73,14 +74,16 @@ fi
 if [[ "$state" = "urls" ]]; then
   # Complete netscape urls
   if compset -P about: ; then
-    _wanted values expl 'about what' &&
+    _wanted values expl 'about what' \
         compadd authors blank cache document fonts global hype image-cache \
             license logo memory-cache mozilla plugins && ret=0
   else
-    if _tags prefixes; then
-      _description prefixes expl 'URL prefix'
-      compadd "$expl[@]" -S '' about: mocha: javascript:
-      _urls "$@" && ret=0
+    if _wanted prefixes; then
+      while _try prefixes expl 'URL prefix'; do
+        compadd "$expl[@]" -S '' about: mocha: javascript: && ret=0
+        _urls "$@" && ret=0
+	(( ret )) || return 0
+      done
     fi
   fi
 fi
diff --git a/Completion/User/_nslookup b/Completion/User/_nslookup
index 7c67cb256..fc14df18c 100644
--- a/Completion/User/_nslookup
+++ b/Completion/User/_nslookup
@@ -60,7 +60,7 @@ if [[ -n "$compcontext" ]]; then
 
     _funcall ret _nslookup_redirect && return ret
 
-    _tags -C redirection files || return 1
+    _wanted -C redirection files || return 1
 
     if [[ "$words[1]" != (finger|ls) ]]; then
       _message "redirection not allowed for command \`$words[1]'"
@@ -86,7 +86,7 @@ if [[ -n "$compcontext" ]]; then
 
   case "$words[1]" in
   (|l)server)
-    _wanted hosts expl 'new default server' && _hosts "$expl[@]"
+    _wanted hosts expl 'new default server' _hosts
     return
     ;;
   root|exit|help|\?)
@@ -119,7 +119,7 @@ if [[ -n "$compcontext" ]]; then
     [[ -z "$state" ]] && return ret
     ;;
   *)
-    _wanted hosts expl 'server' && _hosts "$expl[@]"
+    _wanted hosts expl 'server' _hosts
     return
   esac
 fi
diff --git a/Completion/User/_pbm b/Completion/User/_pbm
index 2c12505ee..1f740ad31 100644
--- a/Completion/User/_pbm
+++ b/Completion/User/_pbm
@@ -254,7 +254,7 @@ pgmtoppm)
     fi
     _x_color && ret=0
   
-    _wanted options expl option && compadd "$expl[@]" - -map && ret=0
+    _wanted options expl option compadd - -map && ret=0
   
     return ret
   elif [[ CURRENT -eq 3 && "$words[2]" = -map ]]; then
@@ -590,12 +590,11 @@ ppmquant)
   fi
   
   if [[ CURRENT -eq 2 ]]; then
-    _wanted options expl option &&
-        if [[ -n "$opt" ]]; then
-          compadd "$expl[@]" - -map -fs -floyd && ret=0
-        else
-          compadd "$expl[@]" - -map && ret=0
-        fi
+    if [[ -n "$opt" ]]; then
+      _wanted options expl option compadd - -map -fs -floyd && ret=0
+    else
+      _wanted options expl option compadd - -map && ret=0
+    fi
     _message 'number of colors'
   
     return ret
diff --git a/Completion/User/_perl_basepods b/Completion/User/_perl_basepods
index 7f257aed3..f5b2216c1 100644
--- a/Completion/User/_perl_basepods
+++ b/Completion/User/_perl_basepods
@@ -29,5 +29,4 @@ fi
 
 local expl
 
-_wanted pods expl 'Perl base pods' &&
-    compadd "$expl[@]" - $_perl_basepods
+_wanted pods expl 'Perl base pods' compadd - $_perl_basepods
diff --git a/Completion/User/_perl_builtin_funcs b/Completion/User/_perl_builtin_funcs
index 7ac69828d..8c221f5a6 100644
--- a/Completion/User/_perl_builtin_funcs
+++ b/Completion/User/_perl_builtin_funcs
@@ -28,5 +28,4 @@ fi
 
 local expl
 
-_wanted functions expl 'Perl built-in functions' &&
-    compadd "$expl[@]" - $_perl_builtin_funcs
+_wanted functions expl 'Perl built-in functions' compadd - $_perl_builtin_funcs
diff --git a/Completion/User/_perl_modules b/Completion/User/_perl_modules
index 8f6a5b882..d1701f57a 100644
--- a/Completion/User/_perl_modules
+++ b/Completion/User/_perl_modules
@@ -49,4 +49,4 @@ fi
 
 local expl
 
-_wanted modules expl 'Perl modules' && compadd "$expl[@]" "$opts[@]" - $_perl_modules
+_wanted modules expl 'Perl modules' compadd "$opts[@]" - $_perl_modules
diff --git a/Completion/User/_ports b/Completion/User/_ports
index 6780067b3..e2db41960 100644
--- a/Completion/User/_ports
+++ b/Completion/User/_ports
@@ -9,4 +9,4 @@ if ! zstyle -a ":completion:${curcontext}:" ports ports; then
   ports=( "$_cache_ports[@]" )
 fi
 
-_wanted ports expl port && compadd "$@" "$expl[@]" - "$ports[@]"
+_wanted ports expl port compadd "$@" - "$ports[@]"
diff --git a/Completion/User/_rcs b/Completion/User/_rcs
index 0831b1d0b..6c4a1d9d6 100644
--- a/Completion/User/_rcs
+++ b/Completion/User/_rcs
@@ -8,5 +8,5 @@ if [[ $compstate[nmatches] -eq nm && -d RCS && $words[1] != ci ]]; then
   local rep expl
 
   rep=(RCS/$PREFIX*$SUFFIX,v(:t:s/\,v//))
-  (( $#rep )) && _wanted files expl 'RCS file' && compadd "$expl[@]" - $rep
+  (( $#rep )) && _wanted files expl 'RCS file' compadd - $rep
 fi
diff --git a/Completion/User/_rlogin b/Completion/User/_rlogin
index df78bd447..2c5e9bfc0 100644
--- a/Completion/User/_rlogin
+++ b/Completion/User/_rlogin
@@ -40,7 +40,7 @@ _rlogin () {
       if compset -P '*:'; then
 	_files && ret=0
       elif compset -P '*@'; then
-        _tags hosts && _rlogin_hosts -S: -q && ret=0
+        _wanted hosts && _rlogin_hosts -S: -q && ret=0
       else
         _alternative \
 	    'files:: _files' \
@@ -54,11 +54,11 @@ _rlogin () {
 }
 
 _rlogin_users () {
-  _tags users && _combination -s '[:@]' my-accounts users-hosts users "$@"
+  _wanted users && _combination -s '[:@]' my-accounts users-hosts users "$@"
 }
 
 _rlogin_hosts () {
-  _tags hosts &&
+  _wanted hosts &&
       if [[ "$IPREFIX" == *@ ]]; then
         _combination -s '[:@]' my-accounts users-hosts "users=${IPREFIX/@}" hosts "$@"
       else
diff --git a/Completion/User/_socket b/Completion/User/_socket
index dfe8f4844..fecd3e6c0 100644
--- a/Completion/User/_socket
+++ b/Completion/User/_socket
@@ -39,17 +39,16 @@ command)
 
 arg1)
   if (( $+opt_args[-s] )); then
-    _wanted ports expl 'port to listen' && _ports "$expl[@]"
+    _wanted ports expl 'port to listen' _ports
   else
-    _wanted hosts expl 'host' &&
-        _combination '' hosts-ports hosts "$expl[@]"
+    _wanted hosts expl 'host' _combination '' hosts-ports hosts -
   fi
   ;;
 
 arg2)
   if (( ! $+opt_args[-s] )); then
-    _wanted ports expl 'port to connect' &&
-        _combination '' hosts-ports hosts="${line[1]:q}" ports "$expl[@]"
+    _wanted ports expl 'port to connect' \
+        _combination '' hosts-ports hosts="${line[1]:q}" ports -
   fi
   ;;
 esac
diff --git a/Completion/User/_ssh b/Completion/User/_ssh
index ddfe6de63..6748a270e 100644
--- a/Completion/User/_ssh
+++ b/Completion/User/_ssh
@@ -54,21 +54,18 @@ _ssh () {
         if compset -P '*[= ]'; then
           case "$IPREFIX" in
           *(#i)(batchmode|compression|fallbacktorsh|forward(agent|x11)|keepalive|passwordauthentication|rhosts(|rsa)authentication|rsaauthentication|usersh|kerberos(authetication|tgtparsing)|usepriviledgedport)*)
-	    _wanted values expl 'truth value' && compadd "$expl[@]" yes no &&
-                ret=0
+	    _wanted values expl 'truth value' compadd yes no && ret=0
             ;;
           *(#i)cipher*)
-	    _wanted values expl 'encryption cipher' &&
-                compadd "$expl[@]" idea des 3des blowfish arcfour tss none && \
-                    ret=0
+	    _wanted values expl 'encryption cipher' \
+                compadd idea des 3des blowfish arcfour tss none && ret=0
             ;;
           *(#i)globalknownhostsfile*)
             _description files expl 'global file with known hosts'
             _files "$expl[@]" && ret=0
             ;;
           *(#i)hostname*)
-	    _wanted hosts expl 'real host name to log into' &&
-                _ssh_hosts "$expl[@]" && ret=0
+	    _wanted hosts expl 'real host name to log into' _ssh_hosts && ret=0
             ;;
           *(#i)identityfile*)
             _description files expl 'SSH identity file'
@@ -84,16 +81,14 @@ _ssh () {
             _normal && ret=0
             ;;
           *(#i)stricthostkeychecking*)
-            _wanted values expl 'checking type' &&
-	        compadd "$expl[@]" yes no ask
+            _wanted values expl 'checking type' compadd yes no ask && ret=0
             ;;
           *(#i)userknownhostsfile*)
             _description files expl 'user file with known hosts'
             _files "$expl[@]" && ret=0
             ;;
           *(#i)user*)
-	    _wanted users expl 'user to log in as' &&
-                _ssh_users "$expl[@]" && ret=0
+	    _wanted users expl 'user to log in as' _ssh_users && ret=0
             ;;
           *(#i)xauthlocation*)
             _description files expl 'xauth program'
@@ -101,8 +96,8 @@ _ssh () {
             ;;
           esac
         else
-          _wanted values expl 'configure file option' &&
-              compadd "$expl[@]" -M 'm:{a-z}={A-Z}' -S '=' - \
+          _wanted values expl 'configure file option' \
+              compadd -M 'm:{a-z}={A-Z}' -S '=' - \
                   BatchMode ClearAllForwardings Cipher Compression \
                   CompressionLevel Host ConnectionAttempts EscapeChar \
                   FallBackToRsh ForwardAgent ForwardX11 \
@@ -121,7 +116,7 @@ _ssh () {
           if compset -P '*:'; then
             _message 'port number'
           else
-	    _wanted hosts expl host && _ssh_hosts -qS: "$expl[@]"
+	    _wanted hosts expl host _ssh_hosts -qS:
           fi
         else
           _message 'listen-port number'
@@ -136,8 +131,7 @@ _ssh () {
         ;;
       userhost)
         if compset -P '*@'; then
-	  _wanted hosts expl 'remote host name' &&
-              _ssh_hosts "$expl[@]" && ret=0
+	  _wanted hosts expl 'remote host name' _ssh_hosts && ret=0
         else
           if (( $+opt_args[-l] )); then
 	    tmp=()
@@ -180,7 +174,7 @@ _ssh () {
       if compset -P '*:'; then
         _remote_files && ret=0
       elif compset -P '*@'; then
-        _wanted hosts expl host && _ssh_hosts -S: "$expl[@]" && ret=0
+        _wanted hosts expl host _ssh_hosts -S: && ret=0
       else
         _alternative \
 	    'files:: _files' \
diff --git a/Completion/User/_stty b/Completion/User/_stty
index 06d0bf851..f40cd856e 100644
--- a/Completion/User/_stty
+++ b/Completion/User/_stty
@@ -4,18 +4,15 @@ local expl
 
 if [[ "$words[CURRENT-1]" = \
   (*erase|discard|status|dsusp|intr|kill|lnext|quit|reprint|start|s*p) ]]; then
-  _wanted characters expl 'control character' &&
-      compadd "$expl[@]" '^-' '^h' '^?' '^c' '^u'
+  _wanted characters expl 'control character' compadd '^-' '^h' '^?' '^c' '^u'
 else
   compset -P '[-+]'
-  _wanted values expl setting &&
-      compadd "$expl[@]" rows columns intr quit erase kill eof eol \
-                         eol2 start stop susp dsusp reprint discard \
-			 werase lnext parenb parodd cs8 cstopb hupcl \
-			 cread clocal parext ignbrk brkint ignpar \
-			 parmrk inpck istrip inlcr igncr icrnl iuclc \
-			 ixon ixany ixoff imaxbel isig icanon xcase \
-			 echo echoe echok echonl noflsh tostop echoctl \
-			 echoprt echoke flusho pending iexten opost \
-			 olcuc onlcr ocrnl onocr onlret ofill ofdel 
+  _wanted values expl setting \
+      compadd rows columns intr quit erase kill eof eol eol2 start stop \
+              susp dsusp reprint discard werase lnext parenb parodd cs8 \
+              cstopb hupcl cread clocal parext ignbrk brkint ignpar \
+	      parmrk inpck istrip inlcr igncr icrnl iuclc ixon ixany ixoff \
+              imaxbel isig icanon xcase echo echoe echok echonl noflsh \
+              tostop echoctl echoprt echoke flusho pending iexten opost \
+	      olcuc onlcr ocrnl onocr onlret ofill ofdel 
 fi
diff --git a/Completion/User/_tar b/Completion/User/_tar
index ac23e94f3..6ca1c27bf 100644
--- a/Completion/User/_tar
+++ b/Completion/User/_tar
@@ -142,8 +142,7 @@ elif [[ ( "$_tar_cmd" = *[xt]* || -n $del ) && -n "$tf" ]]; then
     _tar_cache_name=$tf
   fi
 
-  _wanted files expl 'file from archive' &&
-      _multi_parts "$expl[@]" / _tar_cache_list
+  _wanted files expl 'file from archive' _multi_parts / _tar_cache_list
 else
     _files
 fi
diff --git a/Completion/User/_telnet b/Completion/User/_telnet
index 2542ff34d..02a30f138 100644
--- a/Completion/User/_telnet
+++ b/Completion/User/_telnet
@@ -46,25 +46,25 @@ _arguments -C -s \
 
 case "$state" in
 hosts)
-  _wanted hosts expl host &&
+  _wanted hosts expl host \
       _combination -s '[@:]' '' users-hosts-ports \
           ${opt_args[-l]:+users=${opt_args[-l]:q}} \
-          hosts "$expl[@]"
+          hosts -
   ;;
 
 ports)
-  _wanted ports expl port &&
+  _wanted ports expl port \
       _combination -s '[@:]' '' users-hosts-ports \
           ${opt_args[-l]:+users=${opt_args[-l]:q}} \
           hosts="${line[1]:q}" \
-          ports "$expl[@]"
+          ports -
   ;;
 
 users)
-  _wanted users expl user &&
+  _wanted users expl user \
       _combination -s '[@:]' '' users-hosts-ports \
       ${line[2]:+hosts="${line[2]:q}"} \
       ${line[3]:+ports="${line[3]:q}"} \
-      users "$expl[@]"
+      users -
   ;;
 esac
diff --git a/Completion/User/_tiff b/Completion/User/_tiff
index a0fb0d4b4..5f7cc7edb 100644
--- a/Completion/User/_tiff
+++ b/Completion/User/_tiff
@@ -194,9 +194,12 @@ if [[ -n "$state" ]]; then
       ;;
     esac
   else
-    if _wanted values expl 'compression scheme'; then
-      compadd "$expl[@]" - none g4 packbits && ret=0
-      compadd "$expl[@]" -qS: - lzw zip jpeg g3 && ret=0
+    if _wanted values; then
+      while _try values expl 'compression scheme'; do
+        compadd "$expl[@]" - none g4 packbits && ret=0
+        compadd "$expl[@]" -qS: - lzw zip jpeg g3 && ret=0
+	(( ret )) || return 0
+      done
     fi
   fi
 fi
diff --git a/Completion/User/_urls b/Completion/User/_urls
index 3f2cab789..369017677 100644
--- a/Completion/User/_urls
+++ b/Completion/User/_urls
@@ -49,16 +49,18 @@ local localhttp_userdir="$localhttp[3]"
 
 if [[ "$1" = -f ]]; then
   shift
-  _tags -C -f files && _files "$@" && return
+  _wanted -C -f files && _files "$@" && return
 fi
 
 ipre="$IPREFIX"
 
-if ! compset -P '(#b)([-+.a-z0-9]#):' &&
-   _wanted -C argument prefixes expl 'URL prefix'; then
-  [[ -d $urls_path/bookmark ]] &&
-    compadd "$@" "$expl[@]" -S '' bookmark: && ret=0
-  compadd "$@" "$expl[@]" -S '' file: ftp:// gopher:// http:// && ret=0
+if ! compset -P '(#b)([-+.a-z0-9]#):' && _wanted -C argument prefixes; then
+  while _try prefixes expl 'URL prefix' "$@"; do
+    [[ -d $urls_path/bookmark ]] &&
+      compadd "$expl[@]" -S '' bookmark: && ret=0
+    compadd "$expl[@]" -S '' file: ftp:// gopher:// http:// && ret=0
+    (( ret )) || return 0
+  done
   return ret
 fi
 scheme="$match[1]"
@@ -66,35 +68,40 @@ scheme="$match[1]"
 case "$scheme" in
   http|ftp|gopher)
     if ! compset -P //; then
-      _wanted -C "$scheme" prefixes expl 'end of prefix' &&
-          compadd "$expl[@]" "$@" -S '' //
+      _wanted -C "$scheme" prefixes expl 'end of prefix' compadd "$@" -S '' //
       return
     fi
   ;;
   file)
     if ! compset -P //; then
-      _wanted -C file files expl 'local file' || return 1
+      _wanted -C file files || return 1
 
-      if [[ -prefix / ]]; then
-	_path_files "$expl[@]" "$@" -S '' -g '*(^/)' && ret=0
-	_path_files "$expl[@]" "$@" -S/ -r '/' -/ && ret=0
-      elif [[ -z "$PREFIX" ]]; then
-	compadd "$expl[@]" -S '/' -r '/' - "${PWD%/}" && ret=0
-      fi
+      while _try files expl 'local file' "$@"; do
+        if [[ -prefix / ]]; then
+	  _path_files "$expl[@]" -S '' -g '*(^/)' && ret=0
+	  _path_files "$expl[@]" -S/ -r '/' -/ && ret=0
+        elif [[ -z "$PREFIX" ]]; then
+	  compadd "$expl[@]" -S '/' -r '/' - "${PWD%/}" && ret=0
+        fi
+	(( ret )) || return 0
+      done
       return ret
     fi
   ;;
   bookmark)
     if [[ -f "$urls_path/$scheme/${(Q)PREFIX}${(Q)SUFFIX}" &&
 	  -s "$urls_path/$scheme/${(Q)PREFIX}${(Q)SUFFIX}" ]]; then
-      _wanted -C bookmark bookmarks expl bookmarks &&
-          compadd "$expl[@]" "$@" -U - \
+      _wanted -C bookmark bookmarks expl bookmarks \
+          compadd "$@" -U - \
               "$ipre$(<"$urls_path/$scheme/${(Q)PREFIX}${(Q)SUFFIX}")" && ret=0
     else
-      if _wanted -C bookmark files expl 'bookmark'; then
-        _path_files -W "$urls_path/$scheme" "$expl[@]" -S '' -g '*(^/)' && 
-            ret=0
-        _path_files -W "$urls_path/$scheme" -S/ -r '/' -/ && ret=0
+      if _wanted -C bookmark files; then
+        while _try files expl 'bookmark'; do
+          _path_files -W "$urls_path/$scheme" "$expl[@]" -S '' -g '*(^/)' && 
+              ret=0
+          _path_files -W "$urls_path/$scheme" -S/ -r '/' -/ && ret=0
+          (( ret )) || return 0
+        done
       fi
     fi
     return ret
@@ -102,19 +109,22 @@ case "$scheme" in
 esac
 
 # Complete hosts
-if ! compset -P '(#b)([^/]#)/' &&
-   _wanted hosts expl host; then
+if ! compset -P '(#b)([^/]#)/' && _wanted hosts; then
   uhosts=($urls_path/$scheme/$PREFIX*$SUFFIX(/:t))
-  (( $#uhosts )) || _hosts -S/ && ret=0
-  [[ "$scheme" = http ]] && uhosts=($uhosts $localhttp_servername)
-  compadd "$expl[@]" "$@" -S/ - $uhosts && ret=0
+
+  while _try hosts expl host "$@"; do
+    (( $#uhosts )) || _hosts -S/ && ret=0
+    [[ "$scheme" = http ]] && uhosts=($uhosts $localhttp_servername)
+    compadd "$expl[@]" -S/ - $uhosts && ret=0
+    (( ret )) || return 0
+  done
   return ret
 fi
 host="$match[1]"
 
 # Complete part after hostname
 
-_wanted -C local files expl 'local file' || return 1
+_wanted -C local files || return 1
 
 if [[ "$localhttp_servername" = "$host" ]]; then
   if compset -P \~; then
@@ -123,14 +133,23 @@ if [[ "$localhttp_servername" = "$host" ]]; then
       return
     fi
     user="$match[1]"
-    _path_files "$expl[@]" -W ~$user/$localhttp_userdir -g '*(^/)' && ret=0
-    _path_files "$expl[@]" -W ~$user/$localhttp_userdir -S/ -r '/' -/ && ret=0
+    while _try files expl 'local file'; do
+      _path_files "$expl[@]" -W ~$user/$localhttp_userdir -g '*(^/)' && ret=0
+      _path_files "$expl[@]" -W ~$user/$localhttp_userdir -S/ -r '/' -/ && ret=0
+      (( ret )) || return 0
+    done
   else
-    _path_files "$expl[@]" -W $localhttp_documentroot -g '*(^/)' && ret=0
-    _path_files "$expl[@]" -W $localhttp_documentroot -S/ -r '/' -/ && ret=0
+    while _try files expl 'local file'; do
+      _path_files "$expl[@]" -W $localhttp_documentroot -g '*(^/)' && ret=0
+      _path_files "$expl[@]" -W $localhttp_documentroot -S/ -r '/' -/ && ret=0
+      (( ret )) || return 0
+    done
   fi
 else
-  _path_files "$expl[@]" -W $urls_path/$scheme/$host -g '*(^/)' && ret=0
-  _path_files "$expl[@]" -W $urls_path/$scheme/$host -S/ -r '/' -/ && ret=0
+  while _try files expl 'local file'; do
+    _path_files "$expl[@]" -W $urls_path/$scheme/$host -g '*(^/)' && ret=0
+    _path_files "$expl[@]" -W $urls_path/$scheme/$host -S/ -r '/' -/ && ret=0
+    (( ret )) || return 0
+  done
 fi
 return $ret
diff --git a/Completion/User/_user_at_host b/Completion/User/_user_at_host
index c7b86d385..785d79932 100644
--- a/Completion/User/_user_at_host
+++ b/Completion/User/_user_at_host
@@ -22,9 +22,9 @@ if [[ -prefix 1 *@ ]]; then
 
   compset -P 1 '*@'
 
-  _wanted -C user-at hosts expl "host for $user" &&
-      _combination -s '[:@]' "${tag}" users-hosts users="$user" hosts "$expl[@]" "$@"
+  _wanted -C user-at hosts expl "host for $user" \
+      _combination -s '[:@]' "${tag}" users-hosts users="$user" hosts "$@" -
 else
-  _wanted users expl "user" &&
-      _combination -s '[:@]' "${tag}" users-hosts users -S@ -q "$expl[@]" "$@"
+  _wanted users expl "user" \
+      _combination -s '[:@]' "${tag}" users-hosts users -S@ -q "$@" -
 fi
diff --git a/Completion/User/_users b/Completion/User/_users
index da5539556..0457ecabf 100644
--- a/Completion/User/_users
+++ b/Completion/User/_users
@@ -2,9 +2,9 @@
 
 local expl users
 
-_wanted users expl user || return 1
+_wanted users || return 1
 
 zstyle -a ":completion:${curcontext}:" users users &&
-    compadd "$expl[@]" "$@" - "$users[@]" && return 0
+    _loop users expl user compadd "$@" - "$users[@]" && return 0
 
-compadd "$@" "$expl[@]" - "${(@k)userdirs}"
+_loop users expl user compadd "$@" - "${(@k)userdirs}"
diff --git a/Completion/User/_users_on b/Completion/User/_users_on
index f620f83c7..04a834d53 100644
--- a/Completion/User/_users_on
+++ b/Completion/User/_users_on
@@ -2,11 +2,11 @@
 
 local expl
 
-_tags users || return 1
+_wanted users || return 1
 
 if which users >/dev/null; then
-  _description users expl 'users logged on'
-  compadd "$@" "$expl[@]" - $(_call users users) && return 0
+  _loop users expl 'users logged on' \
+      compadd "$@" - $(_call users users) && return 0
 else
   # Other methods of finding out users logged on should be added here
   return 1
diff --git a/Completion/User/_whois b/Completion/User/_whois
index 0d2675d47..ffdbc13f9 100644
--- a/Completion/User/_whois
+++ b/Completion/User/_whois
@@ -189,14 +189,14 @@ _whois_fwhois () {
 }
 
 _whois_hosts () {
-  _tags hosts &&
+  _wanted hosts &&
     compadd "$@" \
       -M 'm:{a-zA-Z}={A-Za-z} r:|.=* r:|=*' \
       - ${_whois_servers%:?} || _hosts "$@"
 }
 
 _whois_ports () {
-  _tags ports && compadd "$@" - whois || _ports "$@"
+  _wanted ports && compadd "$@" - whois || _ports "$@"
 }
 
 (( $+functions[_whois:whois.internic.net] )) ||
@@ -204,7 +204,7 @@ _whois:whois.internic.net () {
   if (( CURRENT == 1 )); then
     local expl
 
-    _wanted strings expl string && compadd "$expl[@]" HELP DOMAIN HOST
+    _wanted strings expl string compadd HELP DOMAIN HOST
   else
     _message 'string'
   fi
@@ -215,7 +215,7 @@ _whois:whois.nic.ad.jp () {
   if (( CURRENT == 1 )); then
     local expl
 
-    _wanted strings expl string && compadd HELP DOM NET HOST PERSON CONN COM
+    _wanted strings expl string compadd HELP DOM NET HOST PERSON CONN COM
   else
     _message 'string'
   fi
diff --git a/Completion/User/_yp b/Completion/User/_yp
index fe3c0a482..4b1b031b3 100644
--- a/Completion/User/_yp
+++ b/Completion/User/_yp
@@ -95,15 +95,16 @@ if [[ "$state" = map* ]]; then
 
   while _tags; do
     # The `-M ...' allows `pa.n<TAB>' to complete to `passwd.byname'.
-    _requested maps expl 'map name' &&
-        compadd "$expl[@]" -M 'l:.|by=by l:.|=by r:|.=* r:|=*' - \
+    _requested maps expl 'map name' \
+        compadd -M 'l:.|by=by l:.|=by r:|.=* r:|=*' - \
                 "$_yp_cache_maps[@]" && ret=0
-    _requested nicknames expl nicknames &&
-        compadd "$expl[@]" - "$_yp_cache_nicks[@]" && ret=0
+    _requested nicknames expl nicknames \
+        compadd - "$_yp_cache_nicks[@]" && ret=0
+    (( ret )) || return 0
   done
 elif [[ "$state" = servers ]]; then
   if compset -P '*,'; then
-    _wanted hosts expl server && _hosts -qS, && ret=0
+    _wanted hosts expl server _hosts -qS, && ret=0
   else
     _message 'domain name'
   fi
diff --git a/Completion/X/_x_color b/Completion/X/_x_color
index 43f8ad5cd..d58afcb74 100644
--- a/Completion/X/_x_color
+++ b/Completion/X/_x_color
@@ -30,6 +30,6 @@ if (( ! $+_color_cache )); then
   (( $#_color_cache )) || _color_cache=(white black gray red blue green)
 fi
 
-_wanted colors expl 'color specification' &&
-    compadd "$@" "$expl[@]" -M 'm:{a-z}={A-Z} m:-=\  r:|[ A-Z0-9]=* r:|=*' - \
+_wanted colors expl 'color specification' \
+    compadd "$@" -M 'm:{a-z}={A-Z} m:-=\  r:|[ A-Z0-9]=* r:|=*' - \
             "$_color_cache[@]"
diff --git a/Completion/X/_x_cursor b/Completion/X/_x_cursor
index 8b057a537..416ff49a5 100644
--- a/Completion/X/_x_cursor
+++ b/Completion/X/_x_cursor
@@ -14,5 +14,5 @@ if (( ! $+_cursor_cache )); then
   fi
 fi
 
-_wanted cursors expl 'cursor name' &&
-    compadd "$@" "$expl[@]" -M 'm:-=_ r:|_=*' - "$_cursor_cache[@]"
+_wanted cursors expl 'cursor name' \
+    compadd "$@" -M 'm:-=_ r:|_=*' - "$_cursor_cache[@]"
diff --git a/Completion/X/_x_display b/Completion/X/_x_display
index f547a64fa..0f0ebf9ae 100644
--- a/Completion/X/_x_display
+++ b/Completion/X/_x_display
@@ -1,3 +1,3 @@
 #autoload
 
-_tags displays && _hosts -S ':0 ' -r :
+_wnated displays && _hosts -S ':0 ' -r :
diff --git a/Completion/X/_x_extension b/Completion/X/_x_extension
index 9321f4951..61b8ea2d8 100644
--- a/Completion/X/_x_extension
+++ b/Completion/X/_x_extension
@@ -2,16 +2,18 @@
 
 local expl
 
-_wanted extensions expl 'X extensions' || return 1
+_wanted extensions || return 1
 
 (( $+_xe_cache )) || _xe_cache=( "${(@)${(@f)$(xdpyinfo)}[(r)number of extensions:*,-1][2,(r)default screen number:*][1,-2]//[      ]}" )
 
 if [[ "$1" = -a ]]; then
   shift
 
-  compadd "$@" "$expl[@]" -M 'm:{a-z}={A-Z} r:|-=* r:|=*' - all "$_xe_cache[@]"
+  _loop extensions expl 'X extensions' \
+      compadd "$@" -M 'm:{a-z}={A-Z} r:|-=* r:|=*' - all "$_xe_cache[@]"
 else
   [[ "$1" = - ]] && shift
 
-  compadd "$@" "$expl[@]" -M 'm:{a-z}={A-Z} r:|-=* r:|=*' - "$_xe_cache[@]"
+  _loop extensions expl 'X extensions' \
+      compadd "$@" -M 'm:{a-z}={A-Z} r:|-=* r:|=*' - "$_xe_cache[@]"
 fi
diff --git a/Completion/X/_x_font b/Completion/X/_x_font
index 1be2d3312..43c7846c5 100644
--- a/Completion/X/_x_font
+++ b/Completion/X/_x_font
@@ -2,7 +2,7 @@
 
 local expl
 
-_wanted fonts expl font || return 1
+_wanted fonts || return 1
 
 # This *has* to be improved some day...
 
@@ -12,4 +12,4 @@ if (( ! $+_font_cache )); then
  _font_cache=( "${(@)^${(@f)$(_call fonts xlsfonts)}%%--*}--" )
 fi
 
-compadd -M 'r:|-=* r:|=*' "$expl[@]" "$@" -S '' - "$_font_cache[@]"
+_loop fonts expl font compadd -M 'r:|-=* r:|=*' "$@" -S '' - "$_font_cache[@]"
diff --git a/Completion/X/_x_keysym b/Completion/X/_x_keysym
index 2e8f037b1..790571350 100644
--- a/Completion/X/_x_keysym
+++ b/Completion/X/_x_keysym
@@ -2,7 +2,7 @@
 
 local expl
 
-_wanted keysyms expl 'key symbol' || return 1
+_wanted keysyms || return 1
 
 if (( ! $+_keysym_cache )); then
   local file
@@ -18,4 +18,5 @@ if (( ! $+_keysym_cache )); then
   fi
 fi
 
-compadd "$@" "$expl[@]" -M 'm:{a-z}={A-Z} r:|-=* r:|=*' - $_keysym_cache
+_loop keysyms expl 'key symbol' \
+    compadd "$@" -M 'm:{a-z}={A-Z} r:|-=* r:|=*' - $_keysym_cache
diff --git a/Completion/X/_x_modifier b/Completion/X/_x_modifier
index 01052da65..490d12ef3 100644
--- a/Completion/X/_x_modifier
+++ b/Completion/X/_x_modifier
@@ -2,6 +2,6 @@
 
 local expl
 
-_wanted modifiers expl modifier &&
-    compadd "$@" "$expl[@]" -M 'm:{a-z}={A-Z}' - \
+_wanted modifiers expl modifier \
+    compadd "$@" -M 'm:{a-z}={A-Z}' - \
             Shift Lock Control Mod1 Mod2 Mod3 Mod4 Mod5
diff --git a/Completion/X/_x_window b/Completion/X/_x_window
index a79f7fd62..2ca31e1bd 100644
--- a/Completion/X/_x_window
+++ b/Completion/X/_x_window
@@ -2,18 +2,17 @@
 
 local list expl
 
-_tags windows || return 1
+_wanted windows || return 1
 
 list=( "${(@)${(M@)${(@f)$(_call windows xwininfo -root -tree)}:#[ 	]#0x[0-9a-f]# \"*}##[ 	]#}" )
 
 if [[ "$1" = -n ]]; then
   shift
 
-  _description windows expl 'window name'
-  compadd "$@" "$expl[@]" -d list - "${(@)${(@)list#*\"}%%\"*}"
+  _loop windows expl 'window name' \
+      compadd "$@" -d list - "${(@)${(@)list#*\"}%%\"*}"
 else
   [[ "$1" = - ]] && shift
 
-  _description windows expl 'window ID'
-  compadd "$@" "$expl[@]" -d list - "${(@)list%% *}"
+  _loop windows expl 'window ID' compadd "$@" -d list - "${(@)list%% *}"
 fi
diff --git a/Completion/X/_xmodmap b/Completion/X/_xmodmap
index da0029a16..01358b0d4 100644
--- a/Completion/X/_xmodmap
+++ b/Completion/X/_xmodmap
@@ -82,9 +82,12 @@ if [[ -n "$state" ]]; then
     [[ "$what" = *ksym* ]] && _x_keysym "$suf[@]" && ret=0
 
   else
-    if _wanted commands expl command; then
-      compadd "$expl[@]" -S ' ' keycode keysym clear add remove && ret=0
-      compadd "$expl[@]" -S ' = ' pointer && ret=0
+    if _wanted commands; then
+      while _try commands expl command; do
+        compadd "$expl[@]" -S ' ' keycode keysym clear add remove && ret=0
+        compadd "$expl[@]" -S ' = ' pointer && ret=0
+        (( ret )) || return 0
+      done
     fi
   fi
 fi
diff --git a/Completion/X/_xutils b/Completion/X/_xutils
index 1fe6ce468..fe01a5d30 100644
--- a/Completion/X/_xutils
+++ b/Completion/X/_xutils
@@ -55,20 +55,23 @@ xhost)
     if [[ "$tmp" = *:* ]]; then
       if compset -P '(#b)(*):'; then
 	type="$match[1]"
-	_wanted displays expl 'disallow access' &&
-	    {
-	      compadd "$expl[@]" -M 'm:{a-z}={A-Z} r:|[:.]=* r:|=*' - \
-		      ${${(M)tmp:#(#i)$type:*}#(#i)$type:} ||
-	      _hosts "$expl[@]"
-	    }
+	_wanted displays &&
+            while _try displays expl 'disallow access'; do
+	      { compadd "$expl[@]" -M 'm:{a-z}={A-Z} r:|[:.]=* r:|=*' - \
+		        ${${(M)tmp:#(#i)$type:*}#(#i)$type:} ||
+	            _hosts "$expl[@]" } && return 0
+	    done
       else
 	_alternative \
 	    'types:name family:compadd -S: ${(L)tmp%%:*}' \
 	    'hosts:host:compadd ${(@)tmp#*:}' && ret=0
       fi
     else
-      _wanted displays expl 'disallow access' &&
-	  { compadd "$expl[@]" -M 'm:{a-z}={A-Z} r:|[:.]=* r:|=*' - $tmp || _hosts "$expl[@]" }
+      _wanted displays &&
+          while _try displays expl 'disallow access'; do
+	    { compadd "$expl[@]" -M 'm:{a-z}={A-Z} r:|[:.]=* r:|=*' - $tmp ||
+              _hosts "$expl[@]" } && return 0
+          done
     fi
   else
     compset -P +
diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo
index e7d9fe9e4..1fc57de86 100644
--- a/Doc/Zsh/compsys.yo
+++ b/Doc/Zsh/compsys.yo
@@ -806,33 +806,38 @@ this will also cycle through the names of the files in pathname
 components after the first ambiguous one.
 )
 item(tt(file-patterns))(
-The completion system uses two functions to complete filenames,
-tt(_files) and tt(_path_files), with one of them calling the other,
-but this second one is sometimes also called directly. Depending on
-how it is called, the first one uses the tags tt(globbed-files),
-tt(directories) and tt(all-files). The second one, when called
-directly, uses the tag tt(files).
-
-Using this style one can specify which filenames should be completed
-in certain contexts. It is tested by tt(_files) and, if called
-directly, tt(_path_files) with the tags mentioned above. If it is set
-for these tags, the value is taken as a list of glob-patterns that
-should be used to select filenames when completing for the tag. Note
-that with tt(_files), calling completion functions may specify that
-all files are to be completed. Normally this would make tt(_files) use 
-only the tt(all-files) tag, but if this style is set for any of the
-other two tags (tt(globbed-files) and tt(directories)), these tags
-will be used, too, in the normal order given above (unless the user
-specified another order to be used with the tt(tag-order) style).
-
-For example, to make the completion system first try only filenames
-matching the pattern tt(*.o) for the tt(rm) command, one would use:
-
-example(zstyle ':completion:*:*:rm:*:globbed-files' file-patterns '*.o')
-
-With this, using only filenames ending in tt(.o) will be the first
-choice and other filenames will only be used if what is on the line
-matches none of the tt(.o) files (or if there are none).
+In most places where filenames are completed, the function tt(_files)
+is used which can be configured with this style. If the style is
+unset, tt(_files) offers up to three tags: tt(globbed-files),
+tt(directories) and tt(all-files), depending on the types of files
+expected by the caller of tt(_files). Using the tt(tag-order) style
+described below it is possible to specify when which type of files
+should be tried.
+
+If the tt(file-patterns) style is set, the default tags are not
+used. Instead, the value of the style says which tags and which
+patterns are to be offered. The strings in the value are of the form
+`var(patterns)tt(:)var(tag)'. The var(patterns) gives one or more glob 
+patterns separated by spaces that are to be used to generate
+filenames. If it is the empty string, i.e. the string starts with a
+colon, then the glob patterns supplied by the completion function will 
+be used. Colons in the pattern have to be preceded by a backslash to
+make them distinguishable from the colon before the var(tag). The
+var(tag)s of all strings in the value will be offered by tt(_files)
+and used when looking up other styles. The var(tag) may also be
+followed by an optional second colon and a description. If that is
+given, this description will be used for the `tt(%d)' in the value of
+the tt(format) style (if that is set) instead of the default
+description supplied by the completion function. If the description
+given here contains itself a `tt(%d)', that is replaced with the
+description supplied by the completion function.
+
+For example, to make the tt(rm) command first complete only names of
+object files and the names of all files if no object file matches
+the string on the line, one would do:
+
+example(zstyle ':completion:*:*:rm:*' file-patterns \
+  '*.o:object-files' ':all-files')
 
 Note also that during the execution of completion functions, the
 tt(EXTENDED_GLOB) option is in effect, so the characters `tt(#)',
@@ -1416,7 +1421,7 @@ The values for the style are sets of space-separated lists of tags.
 The tags in each value will be tried at the same time; if no match is
 found, the next value is used.
 
-For example,
+For example (with the tt(file-patterns) style not set for tt(gunzip)),
 
 example(zstyle ':completion:*:complete:gunzip:*' tag-order \ 
     'globbed-files directories' all-files)
@@ -1434,6 +1439,37 @@ the end if the selected tags did not generate any matches.  This means
 that a value of only one hyphen turns off completion in a particular
 context.
 
+In strings not starting with an exclamation mark, it is also possible
+to specify tag aliases instead of only tags. These are of the form
+`var(tag)tt(:)var(alias)', where var(tag) is one of the tags offered
+by the completion function for the current context and var(alias) is a 
+name. For this, the completion function will generate matches in the
+same way as for the var(tag) but it will use the var(alias) in place
+of the tag in the context names used to look up styles. This can be
+used to make the completion system try a certain tag more than once,
+supplying different style settings for each attempt. For example,
+
+example(zstyle ':completion:*:*:-command-:*' tag-order 'functions:-non-comp'
+zstyle '*:-non-comp' ignored-patterns '_*')
+
+Makes completion in command position first try only names of shell
+functions that don't match the pattern `tt(_*)'. If that generates no
+matches, the default of trying all the other things that can be
+completed in command position is used, including the names of all
+shell functions. Note that the var(alias) used in this example
+`tt(-non-comp)' with the hyphen at the bginning is not in any way
+special to the completion system. But since no other tag starts with a 
+hyphen, using such a name allows to use a context pattern as short as
+the one in the second line without making it ambiguous.
+
+The var(alias) may optionally be followed by a second colon and a
+description. This description will then be used for the `tt(%d)' in
+the value of the tt(format) style instead of the default description
+supplied by the completion function. Spaces in the description have to 
+be quoted by preceding them with a backslash and a `tt(%d)' appearing
+in the description is replaced with the description given by the
+completion function.
+
 Strings in the value may also be of the form `var(func)tt(())'. In
 this case the function var(func) will be called which can then define
 in which order tags are to be used based on additional context
@@ -1441,12 +1477,27 @@ information. See the tt(_sort_tags) function below for a description
 of how such functions can be implemented. The return value of the
 function is used to decide if the following values for the style
 should be used. If it is zero, they are used and if it is non-zero,
-they are not used.
+they are not used. For example:
+
+example(non-empty() { [[ -n $PREFIX ]] }
+zstyle ':completion:*:*:-command-:*' tag-order 'non-empty()')
+
+Makes completion in command position happen only if the string on the
+line is not empty (this is tested using the tt(PREFIX)
+parameter which is special in completion widgets, see
+ifzman(zshcompwid)\
+ifnzman(the section noderef(Completion System))\
+)\
+for a description of these special parameters).
 
 If no style has been defined for a context, the strings tt(arguments
-values), tt(options), tt(globbed-files), tt(directories) and
-tt(all-files) plus all tags offered by the completion function will be 
-used to provide a sensible default behavior.
+values) and tt(options) plus all tags offered by the completion
+function will be used to provide a sensible default behavior. The tags 
+given used by the tt(_files) function (either the default tags
+tt(globbed-files), tt(directories) and tt(all-files) or the tags
+specified by the tt(file-patterns) style) will be added one-by-one so
+that the different patterns represented by them will be tried one
+after another.
 )
 item(tt(use-compctl))(
 If this style is set to a string not equal to tt(false), tt(0),
@@ -2060,8 +2111,69 @@ tt(curcontext) parameter. This allows to make tt(_tags) use a more
 specific context name without having to change and reset the
 tt(curcontext) parameter (which would otherwise have the same effect).
 )
+findex(_try)
+item(tt(_try) [ tt(-12VJ) ] var(tag) var(name) var(descr) [ var(options) ... ])(
+This function should be called repeatedly to generate the tag
+aliases. On each call it will check if another tag alias is to be used 
+and, if there is at least one, zero is returned. If no more tag
+aliases are to be used, a non-zero status is returned.
+
+The tt(-12JV) options and the first three arguments are given to the
+tt(_desciption) function using the alias tag instead of the first
+argument is appropriate. The var(options) given after the var(descr)
+should be other options to be used for tt(compadd) or whatever
+function is to be called to add the matches. tt(_try) will store these 
+var(options) in the parameter whose var(name) is given as the second
+argument. This is done in such a way that the description given by the 
+user to the tt(tag-order) style is prefered over the one given to
+tt(_try).
+
+Note that this function must not be called without a previous call to
+tt(_tags), tt(_wanted) or tt(_requested) because it uses the alias
+tags for the current tag found by these functions.
+
+A normal use of this function for the alias tags for the tag tt(foo)
+looks like this:
+
+example(local expl ret=1
+...
+_wanted foo || return 1
+...
+while _try foo expl '...'; do
+  compadd "$expl[@]" ... && ret=0
+done
+...
+return ret
+)
+)
+findex(_loop)
+item(tt(_loop) [ tt(-12VJ) ] var(tag) var(name) var(descr) [ var(command) var(args) ... ])(
+This is a convenient interface to the tt(_try) function, implementing
+the loop shown in the example above. The var(command) is the one that
+should be called to generate the matches. The options stored in the
+parameter var(name) will automatically be inserted into the var(args)
+given to the var(command). Normally, they are put directly after the
+var(command), but if one of the var(args) is a single hyphen, they are 
+inserted directly before that. If the hyphen is the last argument,
+that will be removed from the argument list before the var(command) is 
+called. This allows to use tt(_loop) in almost all cases where the
+matches can be generated by a single call to the tt(compadd) builtin
+command or by a call to one of the utility functions.
+
+For example:
+
+example(local expl
+...
+_wanted foo || return 1
+...
+_loop foo expl '...' compadd ... - $matches)
+
+Will complete the strings from the tt(matches) parameter, using
+tt(compadd) with additional options which will take precedence over
+those generated by tt(_loop).
+)
 findex(_requested)
-item(tt(_requested) [ tt(-12VJ) ] var(tag) var(name) var(descr) [ var(specs) ... ])(
+item(tt(_requested) [ tt(-12VJ) ] var(tag) [ var(name) var(descr) [ var(command) var(args) ... ] ])(
 A function that uses tt(_tags) to register tags and then calls it to
 loop over the requested sets of tags should call this function to
 check if a certain tag is currently requested. This normally has to be 
@@ -2080,17 +2192,21 @@ So, the first argument for tt(_requested) is used as the name of a tag
 and if that tag is currently requested, the return value is zero (and
 non-zero otherwise).
 
-If more than one argument is given, tt(_requested) calls the
-tt(_description) function with all arguments, including the options.
-This is often useful to do both the testing of the tag and
-getting the description for the matches one is about to add at
+If the var(name) and the var(descr) are given, tt(_requested) calls the
+tt(_description) function with these arguments, including the options.
+
+If the var(command) is given, the tt(_loop) function will be called
+immediatly with the same arguments.
+
+This is often useful to do both the testing of the tag,
+getting the description for the matches and adding the matches at
 once. E.g.:
 
 example(local expl ret=1
 _tags foo bar baz
 while _tags; do
-  _requested foo expl 'description' &&
-      compadd "$expl[@]" foobar foobaz && ret=0
+  _requested foo expl 'description' \
+      compadd foobar foobaz && ret=0
   ...
   (( ret )) || break
 done)
@@ -2107,20 +2223,14 @@ With the var(tag) it calls tt(_tags) and if that returns zero
 if you want to offer only one tag and immediatly want to use the
 description built, you can just do:
 
-example(_wanted tag expl 'description' &&
-    compadd "$expl[@]" matches...)
-
-Note that you only need to use this function if you need a
-description. If, for example, you use one of the utility functions
-that adds a description itself, you only need to call tt(_tags) as in:
-
-example(_tags tag && _helper)
+example(_wanted tag expl 'description' \
+    compadd matches...)
 )
 findex(_alternative)
 item(tt(_alternative) [ tt(-C) var(name) ] var(specs) ...)(
 This function is useful if you offer multiple tags and building the
 matches for them is easy enough. It basically implements a loop like
-the one described above.
+the one described for the tt(_tags) function above above.
 
 The tags to use and what to do if the tags are requested are described 
 using the var(specs) which are of the form:
@@ -2140,6 +2250,11 @@ example(_alternative \
 to offer usernames and hostnames as possible matches (which are
 generated by the tt(_users) and tt(_hosts) functions respectively).
 
+Note that, like tt(_arguments) this will also use tt(_loop) to execute 
+the actions, so one doesn't need to call that explicitly unless
+another tag is to be used, for example in a function called from
+tt(_alternative).
+
 Like tt(_tags) this function supports the tt(-C) option to give a
 different name for the argument context field.
 )
@@ -2168,6 +2283,9 @@ use the tt(prefix-hidden), tt(prefix-needed) and tt(verbose) styles
 to find out if the strings should be added at all and if the
 descriptions should be shown. Without the `tt(-o)' option, only the
 tt(verbose) style is used.
+
+tt(_describe) uses the tt(_loop) function to generate the matches, so
+that one doesn't need to put it into a loop over the tag aliases.
 )
 findex(_multi_parts)
 item(tt(_multi_parts) var(sep) var(array))(
@@ -2231,9 +2349,10 @@ option from the tt(compadd) builtin is supported, giving direct control
 over which filenames should be ignored. If no such option is given,
 the tt(ignored-suffixes) style is used.
 
-The function tt(_files) calls tt(_path_files) with all the arguments
-it was passed and, if that generated no matches, calls tt(_path_files) again
-without any tt(-g) or tt(-/) option, thus generating all filenames.
+The function tt(_files) uses the tt(file-patterns) style and calls
+tt(_path_files) with all the arguments it was passed except for tt(-g) 
+and tt(-/). These two options are used depending on the setting of the 
+tt(file-patterns) style.
 
 These functions also accept the `tt(-J)', `tt(-V)', `tt(-1)',
 `tt(-2)', `tt(-n)', `tt(-X)', `tt(-M)', `tt(-P)', `tt(-S)', `tt(-q)',
@@ -2416,6 +2535,11 @@ are taken from the array parameter tt(expl) which will be set up
 before executing the var(action) and hence may be used in it (normally 
 in an expansion like `tt($expl[@])').
 
+Except for the `tt(->)var(string)' form, the var(action) will be
+executed by calling the tt(_loop) function to process all tag aliases,
+so one doesn't need to call that explicitly unless another tag is to
+be used, for example in a function called in the var(action).
+
 In places where no sensible matches can be generated, the action
 should consist of only a space. This will make the var(message) be
 displayed but no possible completions listed. Note that even in this
diff --git a/Doc/Zsh/mod_zutil.yo b/Doc/Zsh/mod_zutil.yo
index 565dafed9..9029985ff 100644
--- a/Doc/Zsh/mod_zutil.yo
+++ b/Doc/Zsh/mod_zutil.yo
@@ -70,7 +70,8 @@ zero if the style is defined for at least one matching pattern, has
 only one string in its value and that is equal to one of tt(true),
 tt(yes), tt(on) or tt(1). If any var(strings) are given the return
 zero if and only if at least one of the var(strings) is equal to at
-least one of the strings in the value.
+least one of the strings in the value. If the style is not defined,
+the return value is tt(2).
 
 The tt(-T) option is like tt(-t) but returns zero if the style is not
 set for any matching pattern.
diff --git a/Etc/completion-style-guide b/Etc/completion-style-guide
index 4075a79f4..df186e6c4 100644
--- a/Etc/completion-style-guide
+++ b/Etc/completion-style-guide
@@ -9,21 +9,21 @@ whenever you are about to add matches, you should use a tag for them
 and test if the user wants this type of matches to be generated.
 However, this only really needs to be done if no other function in the
 call chain has tested that already or if you can offer different types
-of matches.
+of matches or if you can handle tag aliases in some sophisticated way.
 
 Most of the utility functions do the testing themselves, so you don't
 have to worry about that at all. For example if you are adding matches 
 with `_files', `_hosts' or functions like these, you can just call
-them and they do the tests needed. The functions `_arguments' and
-`_values' do that too, but there is a small difference. These
-functions effectively change the context name and if you are using the
-`->state' form for actions, this changed name component has to be
-reported back to the function calling `_arguments' or `_values'. This
-is done with the parameter `context', so you have to make that local
-in the calling function in the same way as you have to make local
-`line', `state', and `{opt,val}_args'. This parameter `context' should
-then be used when you start adding matches by giving it to functions
-like `_tags' via the `-C' options, as in:
+them and they do the tests needed and the loops over the tag aliases.
+The functions `_arguments' and `_values' do that too, but there is a
+small difference. These functions effectively change the context
+name and if you are using the `->state' form for actions, this changed
+name component has to be reported back to the function calling
+`_arguments' or `_values'. This is done with the parameter `context',
+so you have to make that local in the calling function in the same way
+as you have to make local `line', `state', and `{opt,val}_args'. This
+parameter `context' should then be used when you start adding matches
+by giving it to functions like `_tags' via the `-C' options, as in:
 
   local context ...
   ...
@@ -62,31 +62,72 @@ example).
 
 Then, before adding the matches, see if matches of that type are
 requested by the user in the current context. If you will add only one 
-type of matches, this is very simple. You can use the function `_tags' 
-or the function `_wanted' for this. `_tags' is normally used to offer
-multiple types of matches by giving the tags for them as arguments. But 
-in any case its return value is zero only if at least one of these
-types is requested by the user, so you can just do:
+type of matches, this is very simple. You can use the function
+`_wanted' for this. Its return value is zero only if the type of
+matches is requested by the user, so you can just do:
 
-  _tags names || return 1
+  _wanted names || return 1
 
-  _description names expl 'name'
-  compadd "$expl[@]" - alice bob
+  _loop names expl 'name' compadd - alice bob
 
-Since this sequence of command is used so often, the `_wanted'
-function was added which just calls `_tags' with its first argument
-(i.e. the first argument is a tag) and then calls `_description' with
-all its arguments. The return value is as for `_tags' -- zero if the 
-matches should be added. So the example becomes:
+The `_loop' function implements the loop over the tag aliases and
+handles the user-defined description, using (in the example) the
+parameter `expl' to store options to give to the command. These option 
+are inserted into the command line either directly before a single
+hyphen if there is such an argument or after the first word if there
+is no single hyphen. Since using `_loop' is so much more conveient
+than writing the loop with the `_try' function (see below), but some
+function called to generate matches don't accept a single hyphen as
+argument anywhere but want the options built as their last arguments,
+`_loop' will *replace* the hyphen with the options if the hyphen is
+the last argument. A good example for such a function is
+`_combination' which can be called like:
 
-  _wanted names expl 'name' && compadd "$expl[@]" alice bob
+  _loop foo expl 'descr...' _combination ... -
+
+And the `-' will be replaced by the options that are to be given to
+`compadd'.
+
+Since the above sequence of command is used so often, the `_wanted'
+function can also accept the same arguments as `_loop'. In this case
+it will do the test for the requested tag and then just call `_loop',
+so:
+
+  _wanted names expl 'name' compadd - alice bob
 
 Note that you can also give the `-J' and `-V' options with the
 optional `1' or `2' preceding them supported by `_description':
 
-  _wanted -2V names expl 'name' && compadd ...
+  _wanted -2V names expl 'name' compadd ...
+
+In some cases one needs to call multiple functions or call `compadd'
+more than once to generate the matches. In such a case one needs to
+implement the loop over the tag aliases directly. This is done with the 
+`_try' function. Like this:
+
+  while _try names expl 'name'; do
+    compadd "$expl[@]" - alice bob && ret=0
+    _other_names "$expl[@]" && ret=0
+  done
+  return ret
+
+Simple enough, I hope. But `_try' can do some more: utility functions
+normally accept options which are then given to `compadd'. Since these 
+may contain options for the description and `_try' may generate such
+options, too, it isn't entirely trivial to decide which of these
+options should take precedence. But `_try' can do the work for you
+here. All you have to do is to give the options your utility function
+gets to `_try', as in:
+
+  while _try names expl 'name' "$@"; do
+    compadd "$expl[@]" - alice bob
+    ...
+  done
 
-The more complicated case is where you can offer multiple types of
+That's all. Note that the positional argument "$@" are *not* given to
+`compadd'. They will be stuffed into the `expl' array by `_try'.
+
+The most complicated case is where you can offer multiple types of
 matches. In this case the user should be able to say which types he
 wants to see at all and of those which he wants to see he should be
 able to say which types should be tried first. The generic solution
@@ -97,10 +138,7 @@ for this uses `_tags' and `_requested':
   _tags friends users hosts
 
   while _tags; do
-    if _requested friends; then
-      _description friends expl friend
-      compad "$expl[@]" alice bob && ret=0
-    fi
+    _requested friends expl friend compad alice bob && ret=0
     _requested users && _users && ret=0
     _requested hosts && _hosts && ret=0
 
@@ -116,38 +154,26 @@ tried and so on. `_tags' without arguments just makes the next set be
 tried (on the first call it makes the first set be used). The function
 `_requested' then tests if the tag given as its first argument is in
 the set currently used and returns zero if it is,  i.e. if matches of
-that type should be added now.
-
-But `_requested' can do more: since it is very common that you add
-different types of matches in different groups, with each group having 
-its own description the sequence of `_requested' followed by
-`_description' would be used very often. Hence, `_requested' can
-accept extra arguments which will be given to a call to `_description' 
-if the tag given as the first argument is to be used. I.e. we could
-change the example above to:
+that type should be added now. The arguments accepted by `_requested'
+are the same as for `_wanted'. I.e. you can call it with only the tag
+to test, with the `tag array description' or with that plus the
+command to execute.
 
-  local expl ret=1
-
-  _tags friends users hosts
-
-  while _tags; do
-    _requested friends expl friend && compadd "$expl[@]" alice bob && ret=0
-    _requested users && _users && ret=0
-    _requested hosts && _hosts && ret=0
-
-    (( ret )) || break   # leave the loop if matches were added
-  done
+In some cases (like the `users' and `hosts' tags in the example) you
+don't need do the loop over the tag aliases yourself, because the
+utility functions like `_users' and `_hosts' do it automatically.
 
-This looks better already. But in many cases such as this one you can
+This looks good already. But in many cases such as this one you can
 also use the function `_alternative' which simply implements a loop
-like this one. It gets arguments of the form `tag:descr:action'. E.g.:
+like the one above. It gets arguments of the form `tag:descr:action'.
+E.g.:
 
   _alternative \
       'friends:friend:(alice bob)' \
       'users:: _users' \
       'hosts:: _hosts'
 
-Which does the same as the previous examples. (Note the empty
+Which does the same as the previous example. (Note the empty
 descriptions in the last two arguments -- the actions start with a
 space so that they are executed without giving the description
 build by `_alternative', i.e. we just use the description added by
diff --git a/Functions/Zftp/zfcd_match b/Functions/Zftp/zfcd_match
index 9734ba8e2..5108d447e 100644
--- a/Functions/Zftp/zfcd_match
+++ b/Functions/Zftp/zfcd_match
@@ -30,8 +30,7 @@ if [[ $ZFTP_SYSTEM = UNIX* ]]; then
   rm -f $tmpf
   [[ -n $dir && $dir != */ ]] && dir="$dir/"
   if [[ -n $WIDGET ]]; then
-    _description directories expl 'remote directory'
-    compadd "$expl[@]" -S/ -q -P "$dir" - $reply
+    _loop directories expl 'remote directory' compadd -S/ -q -P "$dir" - $reply
   elif [[ -n $dir ]]; then
     reply=(${dir}$reply)
   fi
diff --git a/Functions/Zftp/zfget_match b/Functions/Zftp/zfget_match
index cd34c095c..7ff97f4c1 100644
--- a/Functions/Zftp/zfget_match
+++ b/Functions/Zftp/zfget_match
@@ -17,8 +17,7 @@ if [[ $ZFTP_SYSTEM == UNIX* && $1 == */* ]]; then
     local reply
     reply=(${${${(f)"$(<$tmpf)"}##$dir}%\*})
     rm -f $tmpf
-    _description files expl 'remote file'
-    compadd "$expl[@]" -P $dir - $reply
+    _loop files expl 'remote file' compadd -P $dir - $reply
   else
     # On the first argument to ls, we usually get away with a glob.
     zftp ls "$1*$2" >$tmpf
@@ -29,8 +28,7 @@ else
   local fcache_name
   zffcache
   if [[ -n $WIDGET ]]; then
-    _description files expl 'remote file'
-    compadd "$expl[@]" -F fignore - ${(P)fcache_name}
+    _loop files expl 'remote file' compadd -F fignore - ${(P)fcache_name}
   else
     reply=(${(P)fcache_name});
   fi
diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c
index 525d570a0..ef00ccdee 100644
--- a/Src/Modules/zutil.c
+++ b/Src/Modules/zutil.c
@@ -430,7 +430,7 @@ bin_zstyle(char *nam, char **args, char *ops, int func)
 			     !strcmp(s->vals[0], "on") ||
 			     !strcmp(s->vals[0], "1"));
 	    }
-	    return (args[0][1] == 't');
+	    return (args[0][1] == 't' ? (s ? 1 : 2) : 0);
 	}
 	break;
     case 'm':
diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c
index d407a97f3..b96bc20d8 100644
--- a/Src/Zle/computil.c
+++ b/Src/Zle/computil.c
@@ -2180,6 +2180,8 @@ struct ctags {
 struct ctset {
     Ctset next;
     char **tags;		/* the tags */
+    char *tag;			/* last tag checked for -A */
+    char **ptr;			/* ptr into tags for -A */
 };
 
 /* Array of tag-set infos. Index is the locallevel. */
@@ -2201,6 +2203,7 @@ freectset(Ctset s)
 
 	if (s->tags)
 	    freearray(s->tags);
+	zsfree(s->tag);
 	zfree(s, sizeof(*s));
 
 	s = n;
@@ -2240,12 +2243,20 @@ settags(char **tags)
 /* Check if an array contains a string. */
 
 static int
-arrcontains(char **a, char *s)
+arrcontains(char **a, char *s, int colon)
 {
-    while (*a)
-	if (!strcmp(s, *a++))
-	    return 1;
+    char *p, *q;
 
+    while (*a) {
+	if (colon) {
+	    for (p = s, q = *a++; *p && *q && *p != ':' && *q != ':'; p++, q++)
+		if (*p != *q)
+		    break;
+	    if ((!*p || *p == ':') && (!*q || *q == ':'))
+		return 1;
+	} else if (!strcmp(*a++, s))
+	    return 1;
+    }
     return 0;
 }
 
@@ -2266,7 +2277,8 @@ bin_comptags(char *nam, char **args, char *ops, int func)
 	zwarnnam(nam, "nesting level too deep", NULL, 0);
 	return 1;
     }
-    if (args[0][1] != 'i' && !comptags[locallevel]) {
+    if ((args[0][1] != 'i' && args[0][1] != 'A' && !comptags[locallevel]) ||
+	(args[0][1] == 'A' && !comptags[lasttaglevel])) {
 	zwarnnam(nam, "no tags registered", NULL, 0);
 	return 1;
     }
@@ -2277,6 +2289,7 @@ bin_comptags(char *nam, char **args, char *ops, int func)
     case 'N': min = 0; max =  0; break;
     case 'R': min = 1; max =  1; break;
     case 'S': min = 1; max =  1; break;
+    case 'A': min = 2; max =  2; break;
     default:
 	zwarnnam(nam, "invalid option: %s", args[0], 0);
 	return 1;
@@ -2317,7 +2330,42 @@ bin_comptags(char *nam, char **args, char *ops, int func)
 	    Ctset s;
 
 	    return !((s = comptags[locallevel]->sets) &&
-		     arrcontains(s->tags, args[1]));
+		     arrcontains(s->tags, args[1], 1));
+	}
+    case 'A':
+	{
+	    Ctset s;
+
+	    if (comptags[lasttaglevel] && (s = comptags[lasttaglevel]->sets)) {
+		char **q, *v = NULL;
+		int l = strlen(args[1]);
+
+		if (!s->tag || strcmp(s->tag, args[1])) {
+		    zsfree(s->tag);
+		    s->tag = ztrdup(args[1]);
+		    s->ptr = s->tags;
+		}
+		for (q = s->ptr; *q; q++) {
+		    if (strpfx(args[1], *q)) {
+			if (!(*q)[l]) {
+			    v = *q;
+			    break;
+			} else if ((*q)[l] == ':') {
+			    v = (*q) + l + 1;
+			    break;
+			}
+		    }
+		}
+		if (!v) {
+		    zsfree(s->tag);
+		    s->tag = NULL;
+		    return 1;
+		}
+		s->ptr = q + 1;
+		setsparam(args[2], ztrdup(v));
+		return 0;
+	    }
+	    return 1;
 	}
     case 'S':
 	if (comptags[locallevel]->sets) {
@@ -2350,11 +2398,11 @@ bin_comptry(char *nam, char **args, char *ops, int func)
 	args = arrdup(args);
 
 	for (p = q = args, all = comptags[lasttaglevel]->all; *p; p++)
-	    if (arrcontains(all, *p)) {
+	    if (arrcontains(all, *p, 1)) {
 		Ctset s;
 
 		for (s = comptags[lasttaglevel]->sets; s; s = s->next)
-		    if (arrcontains(s->tags, *p))
+		    if (arrcontains(s->tags, *p, 0))
 			break;
 
 		if (!s)
@@ -2367,6 +2415,8 @@ bin_comptry(char *nam, char **args, char *ops, int func)
 
 	    s->tags = zarrdup(args);
 	    s->next = NULL;
+	    s->ptr = NULL;
+	    s->tag = NULL;
 
 	    if ((l = comptags[lasttaglevel]->sets)) {
 		while (l->next)