Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: tag aliases



Ok, here is the patch. Looks rather big, compared to the few changes
in the configuration stuff...


The idea is to let users invent their own tags. This is done with the
tag-order style, the syntax is currently:

  zstyle ':completion:...' tag-order 'foo:bar'

Here, `foo' is the tag offered by the completion function and `bar' is 
the alias. Completion will then proceed as if only `foo' were given,
i.e. the matches for that tag are generated. BUT: instead of using
`foo' to look up style, the function will use `bar'.

The alias may also be followed by another colon and a
description. This description will then be used for the `%d' in the
format style instead of the one given by the completion function.

This only really gets interesting when using more than one alias for
the same tag:

  zstyle ':completion:...' tag-order 'foo:bar foo:baz'

This will make the matches for the `foo' tag be generated *twice*,
once using `bar' as the tag for lookup and once with `baz'. And with
that one can set all our tag-specific styles separately, e.g.:

  zstyle ':completion:*' tag-order 'arguments values' \
      'options:-long-options:long\ options 
       options:-short-options:short\ options 
       options:-single-letter-options:single\ letter\ options'

  zstyle '*:-long-options' ignored-patterns '[-+](|-|[^-]*)'
  zstyle '*:-short-options' ignored-patterns '--*' '-?'
  zstyle '*:-single-letter-options' ignored-patterns '???*'

Can be used to separate long options, normal options and single letter 
options. Another example would be to use something like:

  zstyle ':completion:...' tag-order 'foo:-no-match' 'foo:-case-match'
  zstyle '*:-case-match' matcher 'm:{a-z}={A-Z}'

To try multiple matchers for a single type of matches.

[ This also quite clearly shows that we should try to find ways to make
  configuration easier, I'll make some suggestions below. ]

So, from a user's point of view the change is rather small, but the
fact that multiple tag aliases have to be tried everywhere is
responsible for most of the patch. I did this by adding two new
functions `_try' and `_loop' (here, too, I'd like to hear suggestions
for better names). Then I changed `_wanted' and `_requested' to allow
to do the loop over the tag aliases directly, calling a command with
arguments given to them. See the updated completion-style-guide for a
description and examples (or the manual, or the completion functions).


The other change we were discussing is file-patterns. This has been
cleaned up (as I hope you'll agree if you look at _files). You can now 
do things like:

  zstyle ':completion:*:*:rm:*' file-patterns \
      '*.o:object-files' ':all-files'

I.e., the strings in the value are of the form `<patterns>:<tag>',
again with an optional `:<description>' after it. _files will then
offer all the tags from the value (they are real tags, not aliases)
one after another (but you can change that with tag-order, as
usual). A empty pattern (as in the `:all-files' from the example) is
replaced by the pattern used by the completion function (if any).

That's it. Nicely simple?


Sooo... please note that this patch is almost only intended to provide 
the basic machinery on which we can now try to make things easier, as
I already said: especially (and probably: only; meaning that the code
may become more complicated) from the configuration side.


I think we should do this by looking at the things users might want to 
configure (I too often look at the way we can implement it, trying to
make that fast/easy, I know...).

One thing that already came up is the matcher style. It would be nice
to be able to have an easy way to say `in context ... first try this
match spec, then this, then...'. This can be done with alias tags, but 
certainly not convenient enough. It gets especially uncomfortable when 
the match specs are to be used for more than one tag. One way I can
think of to make that more comfortable is to allow patterns for the
tags in the tag-order style and allow tag aliases to be meant to be
appended to the original tag. For example:

  zstyle ... tag-order '*' '*:-case-match'
  zstyle '...:*-case-match' matcher 'm:{a-z}={A-Z}'

The '*' would be replaced by all tags offered, so they would first be
tried with no match specs (only those from matcher-list, that is).
If that produces no matches, it would be tried again with (if the
offered tags are `foo' and `bar') the tag aliases `foo-case-match' and 
`bar-case-match', so that the matcher from the second line would be
used for them. I.e. if the alias starts with a hyphen this means that
it is to be appended to the tag instead of replacing it for the
lookup. There is almost certainly a better syntax...

Aside: I can almost hear some people saying that we should just make
the matcher style try its values one after another. This would be
possible, by looking it up in _try and _loop and making them loop over 
the match specs if there are any. I actually tried that (before
implementing the tag aliases) and I don't like it. The problem is that 
we already have several loops (completers, matcher-list, offered tags, 
tag aliases; in this order) and for adding more loops we would have to 
decide how to nest them. For the ones this we have now, this is fairly 
obvious (with the probably exception of matcher-list). But for the
matcher style: should it be in the loop for the tag aliases or around
it. And then someone could say that ignored-patterns should be changed 
to try the patterns one after another -- another loop and again: how
should it be nested? Because of that I would definitely prefer to
leave the control flow as it is now and just try to find the most
convenient way to configure things.

Ok. Another thing people might want to configure is to give different
(sets of) patterns to ignore and to try them one after another. There
are two forms of this: use it to split groups of matches as in the
options example above and use it to really try first one pattern, if
that generates no matches, try the next pattern and so on. Of course
we can express that with tag-order -- its the difference between
putting it in one string and in separate strings. But both forms are
relatively complicated to configure at the moment. For the first form
the example above already shows that we had to give the `arguments values'
in the first string of the value to get the normal tag-order. I.e.
there is no easy way to express `*if* the tag foo is used, then always 
use the aliases bar and baz for it'. Of course we could easily extend
_tags (where tag-order is tested) to look up a style, say
`tag-aliases' for every tag it uses and, if the style is set, replace
the tag in its list with the values from that style. But I still hope
there is a better way (or maybe everyone likes this? it is certainly
easy to implement).

The second form is more complicated. I haven't had too many ideas
about this yet, but maybe it could be done with the patterns-for-tags
I suggested above. E.g.:

  zstyle ':completion:*:*:-command-:*' tag-order 'functions:-non-comp *' '*'
  zstyle '*:-non-comp' ignored-patterns '_*'

Would say to first try only functions not beginning with an underscore 
and all the other tags offered. I.e. the `*' would here mean `all
other tags', not `all tags', but I think this is sensible anyway,
because giving the same tag more than once in the same string doesn't
make much sense anyway.

The last thing on my list is (for now) the alternate set stuff. Of
course, this is also connected to the ignored-patterns style. The
thing I wasn't sure about is how to easily get the behaviour this
shows now when removing the alternate set altogether for the new
completion system. But its quite simple: we could just add a
completer, say `_ignored' that does normal completion (or that calls
all preceding completer in the way _prefix does it), but makes sure
that the ignored-patterns style and $fignore are not used. Since it
will only be called when no preceding completer generated matches, it
can easily be used to give the default behaviour by putting it at the
end of the completer style. It would also make the prefer-ignored syle 
superfluous because one could simply put the completer at the place
where one wants the ignored matches to be tried. In fact, I'm so
content with this, that I'd like to start write it. The only thing
that holds me back is that I don't know how religiously attached
people are to the alternate set stuff. Would anyone be against this
change? It would make completion from the alternate set somewhat
slower, because the list of matches would have to be build anew. But
with the finer control over the ignored-patterns style we have now,
one could fine-tune this anyway for the places where one wants to try
otherwise-ignored matches earlier.

And finally: Bart and I had this bit of discussion about changing the
completer field to always contain the `-<num>' suffix. And we didn't
like it. With the prefer-ignored change I just suggested I'm not sure
how important this will be in the future anyway, but I found another
possibility. We could make the completer style allow an alias-syntax
like the one from tag-order, too. I would then first change the style
so that one doesn't need to give the leading underscores (given that
people who use the completion system don't have to worry much about
function names, this change is probably overdue anyway). And then one
could do:

  zstyle ':completion:*' completer complete ... complete:foo

The first invocation of _complete would use the usual
`...:complete:...' in the context name but the second one would use
`...:foo:...' in the completer field.


Anyway... I'd like to hear your comments, suggestions and so
on. Especially about the configuration stuff, but also about the
syntax of the tag-order and file-patterns styles, about the names of
the two new functions (yes, I didn't even try to make them sensible
because I wasn't sure what I was implementing when I started it), and
so on...


Bye
 Sven

P.S.: Next to all the tags stuff the patch contains a small change for 
      the return value of `zstyle -t  ...', as `suggested' by Oliver.
      See _setup or the manual for enlightenment.

diff -ru ../z.old/Completion/Base/_arguments Completion/Base/_arguments
--- ../z.old/Completion/Base/_arguments	Wed Mar 22 09:13:13 2000
+++ Completion/Base/_arguments	Wed Mar 22 10:31:44 2000
@@ -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,34 +230,38 @@
 
             # 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 -ru ../z.old/Completion/Base/_brace_parameter Completion/Base/_brace_parameter
--- ../z.old/Completion/Base/_brace_parameter	Wed Mar 22 09:13:13 2000
+++ Completion/Base/_brace_parameter	Wed Mar 22 09:14:05 2000
@@ -1,3 +1,3 @@
 #compdef -brace-parameter-
 
-_tags parameters && _parameters -e
+_wanted parameters && _parameters -e
diff -ru ../z.old/Completion/Base/_condition Completion/Base/_condition
--- ../z.old/Completion/Base/_condition	Wed Mar 22 09:13:13 2000
+++ Completion/Base/_condition	Wed Mar 22 09:14:05 2000
@@ -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 -ru ../z.old/Completion/Base/_default Completion/Base/_default
--- ../z.old/Completion/Base/_default	Wed Mar 22 09:13:13 2000
+++ Completion/Base/_default	Wed Mar 22 09:14:05 2000
@@ -12,7 +12,7 @@
   compcall "$opt[@]" || return 0
 fi
 
-_tags files || return 1
+_wanted files || return 1
 
 _files && return 0
 
diff -ru ../z.old/Completion/Base/_describe Completion/Base/_describe
--- ../z.old/Completion/Base/_describe	Wed Mar 22 09:13:13 2000
+++ Completion/Base/_describe	Wed Mar 22 10:32:09 2000
@@ -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 @@
 
 # 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 -ru ../z.old/Completion/Base/_first Completion/Base/_first
--- ../z.old/Completion/Base/_first	Wed Mar 22 09:13:13 2000
+++ Completion/Base/_first	Wed Mar 22 09:14:05 2000
@@ -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 -ru ../z.old/Completion/Base/_jobs Completion/Base/_jobs
--- ../z.old/Completion/Base/_jobs	Wed Mar 22 09:13:13 2000
+++ Completion/Base/_jobs	Wed Mar 22 09:14:05 2000
@@ -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 @@
 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 @@
 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 -ru ../z.old/Completion/Base/_math Completion/Base/_math
--- ../z.old/Completion/Base/_math	Wed Mar 22 09:13:13 2000
+++ Completion/Base/_math	Wed Mar 22 09:14:06 2000
@@ -9,4 +9,4 @@
   SUFFIX="${SUFFIX%%[^a-zA-Z0-9_]*}"
 fi
 
-_tags parameters && _parameters
+_parameters
diff -ru ../z.old/Completion/Base/_parameter Completion/Base/_parameter
--- ../z.old/Completion/Base/_parameter	Wed Mar 22 09:13:13 2000
+++ Completion/Base/_parameter	Wed Mar 22 09:14:06 2000
@@ -1,3 +1,3 @@
 #compdef -parameter-
 
-_tags parameters && _parameters -e
+_parameters -e
diff -ru ../z.old/Completion/Base/_subscript Completion/Base/_subscript
--- ../z.old/Completion/Base/_subscript	Wed Mar 22 09:13:14 2000
+++ Completion/Base/_subscript	Wed Mar 22 09:14:06 2000
@@ -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 @@
       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 -ru ../z.old/Completion/Base/_tilde Completion/Base/_tilde
--- ../z.old/Completion/Base/_tilde	Wed Mar 22 09:13:14 2000
+++ Completion/Base/_tilde	Wed Mar 22 09:14:06 2000
@@ -18,10 +18,10 @@
 
 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 @@
       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 -ru ../z.old/Completion/Base/_values Completion/Base/_values
--- ../z.old/Completion/Base/_values	Wed Mar 22 09:13:14 2000
+++ Completion/Base/_values	Wed Mar 22 09:14:06 2000
@@ -18,7 +18,7 @@
 
   if ! compvalues -D descr action; then
 
-    _tags values || return 1
+    _wanted values || return 1
 
     curcontext="${oldcontext%:*}:values"
 
@@ -119,25 +119,26 @@
 
       # 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 -ru ../z.old/Completion/Builtins/_arrays Completion/Builtins/_arrays
--- ../z.old/Completion/Builtins/_arrays	Wed Mar 22 09:13:15 2000
+++ Completion/Builtins/_arrays	Wed Mar 22 09:14:07 2000
@@ -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 -ru ../z.old/Completion/Builtins/_autoload Completion/Builtins/_autoload
--- ../z.old/Completion/Builtins/_autoload	Wed Mar 22 09:13:15 2000
+++ Completion/Builtins/_autoload	Wed Mar 22 09:14:07 2000
@@ -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 -ru ../z.old/Completion/Builtins/_bindkey Completion/Builtins/_bindkey
--- ../z.old/Completion/Builtins/_bindkey	Wed Mar 22 09:13:15 2000
+++ Completion/Builtins/_bindkey	Wed Mar 22 09:14:07 2000
@@ -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 -ru ../z.old/Completion/Builtins/_builtin Completion/Builtins/_builtin
--- ../z.old/Completion/Builtins/_builtin	Wed Mar 22 09:13:15 2000
+++ Completion/Builtins/_builtin	Wed Mar 22 09:14:07 2000
@@ -7,6 +7,5 @@
 else
   local expl
 
-  _wanted commands expl 'builtin command' &&
-      compadd "$expl[@]" "$@" - "${(k@)builtins}"
+  _wanted commands expl 'builtin command' compadd "$@" - "${(k@)builtins}"
 fi
diff -ru ../z.old/Completion/Builtins/_cd Completion/Builtins/_cd
--- ../z.old/Completion/Builtins/_cd	Wed Mar 22 09:13:15 2000
+++ Completion/Builtins/_cd	Wed Mar 22 09:14:07 2000
@@ -22,8 +22,7 @@
   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 -ru ../z.old/Completion/Builtins/_command Completion/Builtins/_command
--- ../z.old/Completion/Builtins/_command	Wed Mar 22 09:13:15 2000
+++ Completion/Builtins/_command	Wed Mar 22 09:14:07 2000
@@ -6,6 +6,5 @@
 else
   local expl
 
-  _wanted commands expl 'external command' &&
-      compadd "$expl[@]" "$@" - "${(k@)commands}"
+  _wanted commands expl 'external command' compadd "$@" - "${(k@)commands}"
 fi
diff -ru ../z.old/Completion/Builtins/_compdef Completion/Builtins/_compdef
--- ../z.old/Completion/Builtins/_compdef	Wed Mar 22 09:13:15 2000
+++ Completion/Builtins/_compdef	Wed Mar 22 09:14:08 2000
@@ -16,24 +16,24 @@
 
 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 -ru ../z.old/Completion/Builtins/_echotc Completion/Builtins/_echotc
--- ../z.old/Completion/Builtins/_echotc	Wed Mar 22 09:13:15 2000
+++ Completion/Builtins/_echotc	Wed Mar 22 09:14:08 2000
@@ -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 -ru ../z.old/Completion/Builtins/_functions Completion/Builtins/_functions
--- ../z.old/Completion/Builtins/_functions	Wed Mar 22 09:13:16 2000
+++ Completion/Builtins/_functions	Wed Mar 22 09:14:08 2000
@@ -2,5 +2,4 @@
 
 local expl
 
-_wanted functions expl 'shell function' &&
-    compadd "$expl[@]" "$@" - "${(k@)functions}"
+_wanted functions expl 'shell function' compadd "$@" - "${(k@)functions}"
diff -ru ../z.old/Completion/Builtins/_hash Completion/Builtins/_hash
--- ../z.old/Completion/Builtins/_hash	Wed Mar 22 09:13:16 2000
+++ Completion/Builtins/_hash	Wed Mar 22 09:14:08 2000
@@ -4,15 +4,14 @@
 
 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 -ru ../z.old/Completion/Builtins/_limits Completion/Builtins/_limits
--- ../z.old/Completion/Builtins/_limits	Wed Mar 22 09:13:16 2000
+++ Completion/Builtins/_limits	Wed Mar 22 09:14:08 2000
@@ -2,5 +2,4 @@
 
 local expl
 
-_wanted limits expl 'process limits' &&
-    compadd "$expl[@]" ${${(f)"$(limit)"}%% *}
+_wanted limits expl 'process limits' compadd ${${(f)"$(limit)"}%% *}
diff -ru ../z.old/Completion/Builtins/_pids Completion/Builtins/_pids
--- ../z.old/Completion/Builtins/_pids	Wed Mar 22 09:13:16 2000
+++ Completion/Builtins/_pids	Wed Mar 22 09:14:09 2000
@@ -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 @@
   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 -ru ../z.old/Completion/Builtins/_popd Completion/Builtins/_popd
--- ../z.old/Completion/Builtins/_popd	Wed Mar 22 09:13:16 2000
+++ Completion/Builtins/_popd	Wed Mar 22 09:14:09 2000
@@ -12,7 +12,7 @@
 ! 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 @@
   disp=()
 fi
 
-compadd "$expl[@]" "$@" "$disp[@]" -Q - "$list[@]"
+_loop -V directory-stack expl 'directory stack' \
+    compadd "$@" "$disp[@]" -Q - "$list[@]"
diff -ru ../z.old/Completion/Builtins/_sched Completion/Builtins/_sched
--- ../z.old/Completion/Builtins/_sched	Wed Mar 22 09:13:16 2000
+++ Completion/Builtins/_sched	Wed Mar 22 09:14:09 2000
@@ -4,7 +4,7 @@
 
 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 @@
     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 -ru ../z.old/Completion/Builtins/_signals Completion/Builtins/_signals
--- ../z.old/Completion/Builtins/_signals	Wed Mar 22 09:13:16 2000
+++ Completion/Builtins/_signals	Wed Mar 22 09:14:09 2000
@@ -20,7 +20,7 @@
 
 [[ "$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 @@
   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 -ru ../z.old/Completion/Builtins/_stat Completion/Builtins/_stat
--- ../z.old/Completion/Builtins/_stat	Wed Mar 22 09:13:16 2000
+++ Completion/Builtins/_stat	Wed Mar 22 09:14:09 2000
@@ -9,10 +9,12 @@
 
   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 -ru ../z.old/Completion/Builtins/_vars Completion/Builtins/_vars
--- ../z.old/Completion/Builtins/_vars	Wed Mar 22 09:13:17 2000
+++ Completion/Builtins/_vars	Wed Mar 22 09:14:10 2000
@@ -16,9 +16,9 @@
   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 -ru ../z.old/Completion/Builtins/_zftp Completion/Builtins/_zftp
--- ../z.old/Completion/Builtins/_zftp	Wed Mar 22 09:13:17 2000
+++ Completion/Builtins/_zftp	Wed Mar 22 09:14:10 2000
@@ -13,8 +13,8 @@
 
 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 @@
 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 @@
       [[ -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 -ru ../z.old/Completion/Builtins/_zle Completion/Builtins/_zle
--- ../z.old/Completion/Builtins/_zle	Wed Mar 22 09:13:17 2000
+++ Completion/Builtins/_zle	Wed Mar 22 09:14:10 2000
@@ -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 -ru ../z.old/Completion/Builtins/_zmodload Completion/Builtins/_zmodload
--- ../z.old/Completion/Builtins/_zmodload	Wed Mar 22 09:13:17 2000
+++ Completion/Builtins/_zmodload	Wed Mar 22 09:14:10 2000
@@ -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 -ru ../z.old/Completion/Builtins/_zpty Completion/Builtins/_zpty
--- ../z.old/Completion/Builtins/_zpty	Wed Mar 22 09:13:17 2000
+++ Completion/Builtins/_zpty	Wed Mar 22 09:14:10 2000
@@ -11,13 +11,13 @@
   '(-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 -ru ../z.old/Completion/Builtins/_zstyle Completion/Builtins/_zstyle
--- ../z.old/Completion/Builtins/_zstyle	Wed Mar 22 09:13:17 2000
+++ Completion/Builtins/_zstyle	Wed Mar 22 09:14:10 2000
@@ -41,7 +41,6 @@
   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 @@
 
   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 @@
       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 @@
       ;;
 
     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 @@
       ;;
 
     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 @@
       ;;
 
     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 -ru ../z.old/Completion/Commands/_next_tags Completion/Commands/_next_tags
--- ../z.old/Completion/Commands/_next_tags	Wed Mar 22 09:13:18 2000
+++ Completion/Commands/_next_tags	Wed Mar 22 13:23:01 2000
@@ -52,8 +52,13 @@
 _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 -ru ../z.old/Completion/Core/_alternative Completion/Core/_alternative
--- ../z.old/Completion/Core/_alternative	Wed Mar 22 09:13:19 2000
+++ Completion/Core/_alternative	Wed Mar 22 09:14:11 2000
@@ -44,24 +44,26 @@
 
         # 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 -ru ../z.old/Completion/Core/_files Completion/Core/_files
--- ../z.old/Completion/Core/_files	Wed Mar 22 09:13:20 2000
+++ Completion/Core/_files	Wed Mar 22 11:28:51 2000
@@ -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=()
+(( $tmp[(I)-g*] )) && glob="${(j: :)${(M)tmp:#-g*}#-g}"
 
-ign=()
-
-zstyle -s ":completion:${curcontext}:all-files" file-patterns tmp &&
-    [[ -n "$tmp" ]] &&
-        aopts=(-g "$tmp")
-
-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 -ru ../z.old/Completion/Core/_main_complete Completion/Core/_main_complete
--- ../z.old/Completion/Core/_main_complete	Wed Mar 22 09:13:20 2000
+++ Completion/Core/_main_complete	Wed Mar 22 09:14:11 2000
@@ -20,7 +20,7 @@
 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 \
@@ -30,6 +30,9 @@
       _saved_insert="${compstate[insert]}"
 
 typeset -U _lastdescr
+
+_comp_opts=()
+_comp_tries=()
 
 [[ -z "$curcontext" ]] && curcontext=:::
 
diff -ru ../z.old/Completion/Core/_multi_parts Completion/Core/_multi_parts
--- ../z.old/Completion/Core/_multi_parts	Wed Mar 22 09:13:20 2000
+++ Completion/Core/_multi_parts	Wed Mar 22 09:14:11 2000
@@ -14,7 +14,7 @@
 # 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 -ru ../z.old/Completion/Core/_options Completion/Core/_options
--- ../z.old/Completion/Core/_options	Wed Mar 22 09:13:21 2000
+++ Completion/Core/_options	Wed Mar 22 09:14:12 2000
@@ -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 -ru ../z.old/Completion/Core/_parameters Completion/Core/_parameters
--- ../z.old/Completion/Core/_parameters	Wed Mar 22 09:13:21 2000
+++ Completion/Core/_parameters	Wed Mar 22 09:14:12 2000
@@ -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 -ru ../z.old/Completion/Core/_path_files Completion/Core/_path_files
--- ../z.old/Completion/Core/_path_files	Wed Mar 22 09:13:21 2000
+++ Completion/Core/_path_files	Wed Mar 22 09:14:12 2000
@@ -20,7 +20,7 @@
 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 @@
   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 @@
 
 # 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 -ru ../z.old/Completion/Core/_requested Completion/Core/_requested
--- ../z.old/Completion/Core/_requested	Wed Mar 22 09:13:21 2000
+++ Completion/Core/_requested	Wed Mar 22 09:36:16 2000
@@ -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 -ru ../z.old/Completion/Core/_sep_parts Completion/Core/_sep_parts
--- ../z.old/Completion/Core/_sep_parts	Wed Mar 22 09:13:21 2000
+++ Completion/Core/_sep_parts	Wed Mar 22 09:14:12 2000
@@ -23,7 +23,7 @@
 # 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 -ru ../z.old/Completion/Core/_set_options Completion/Core/_set_options
--- ../z.old/Completion/Core/_set_options	Wed Mar 22 09:13:21 2000
+++ Completion/Core/_set_options	Wed Mar 22 09:14:13 2000
@@ -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 -ru ../z.old/Completion/Core/_setup Completion/Core/_setup
--- ../z.old/Completion/Core/_setup	Wed Mar 22 09:13:21 2000
+++ Completion/Core/_setup	Wed Mar 22 09:22:56 2000
@@ -18,42 +18,34 @@
 
 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 -ru ../z.old/Completion/Core/_tags Completion/Core/_tags
--- ../z.old/Completion/Core/_tags	Wed Mar 22 09:13:21 2000
+++ Completion/Core/_tags	Wed Mar 22 11:05:44 2000
@@ -50,21 +50,31 @@
              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 -ru ../z.old/Completion/Core/_unset_options Completion/Core/_unset_options
--- ../z.old/Completion/Core/_unset_options	Wed Mar 22 09:13:21 2000
+++ Completion/Core/_unset_options	Wed Mar 22 09:14:13 2000
@@ -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 -ru ../z.old/Completion/Core/_wanted Completion/Core/_wanted
--- ../z.old/Completion/Core/_wanted	Wed Mar 22 09:13:21 2000
+++ Completion/Core/_wanted	Wed Mar 22 09:14:13 2000
@@ -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 @@
   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 -ru ../z.old/Completion/Debian/_apt Completion/Debian/_apt
--- ../z.old/Completion/Debian/_apt	Wed Mar 22 09:13:23 2000
+++ Completion/Debian/_apt	Wed Mar 22 09:14:14 2000
@@ -75,7 +75,7 @@
   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 @@
     /$'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 @@
     /$'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 @@
     -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 @@
     -- \
     /$'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 -ru ../z.old/Completion/Debian/_deb_packages Completion/Debian/_deb_packages
--- ../z.old/Completion/Debian/_deb_packages	Wed Mar 22 09:13:23 2000
+++ Completion/Debian/_deb_packages	Wed Mar 22 09:14:14 2000
@@ -51,7 +51,7 @@
 
   _deb_packages_update_$pkgset
 
-  _tags packages && compadd "$expl[@]" - "${(@P)cachevar}"
+  _wanted packages && compadd "$expl[@]" - "${(@P)cachevar}"
 }
 
 _deb_packages "$@"
diff -ru ../z.old/Completion/Linux/_rpm Completion/Linux/_rpm
--- ../z.old/Completion/Linux/_rpm	Wed Mar 22 09:13:24 2000
+++ Completion/Linux/_rpm	Wed Mar 22 09:14:14 2000
@@ -189,12 +189,12 @@
     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 @@
     ;;
   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'
@@ -219,8 +219,6 @@
     else
       _description directories expl 'old path'
     fi
-
-    _tags directories || return 1
 
     _files "$expl[@]" -/ && ret=0
     ;;
diff -ru ../z.old/Completion/User/_archie Completion/User/_archie
--- ../z.old/Completion/User/_archie	Wed Mar 22 09:13:25 2000
+++ Completion/User/_archie	Wed Mar 22 09:14:14 2000
@@ -26,6 +26,6 @@
 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 -ru ../z.old/Completion/User/_cvs Completion/User/_cvs
--- ../z.old/Completion/User/_cvs	Wed Mar 22 09:13:26 2000
+++ Completion/User/_cvs	Wed Mar 22 09:14:15 2000
@@ -34,7 +34,7 @@
 	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 @@
   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 @@
     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 @@
 
 (( $+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 @@
   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_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 @@
     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 -ru ../z.old/Completion/User/_dd Completion/User/_dd
--- ../z.old/Completion/User/_dd	Wed Mar 22 09:13:26 2000
+++ Completion/User/_dd	Wed Mar 22 09:14:15 2000
@@ -6,9 +6,8 @@
   # 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 @@
   _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 -ru ../z.old/Completion/User/_domains Completion/User/_domains
--- ../z.old/Completion/User/_domains	Wed Mar 22 09:13:26 2000
+++ Completion/User/_domains	Wed Mar 22 09:14:15 2000
@@ -16,5 +16,5 @@
   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 -ru ../z.old/Completion/User/_gcc Completion/User/_gcc
--- ../z.old/Completion/User/_gcc	Wed Mar 22 09:13:27 2000
+++ Completion/User/_gcc	Wed Mar 22 09:14:15 2000
@@ -273,8 +273,8 @@
     '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 -ru ../z.old/Completion/User/_gdb Completion/User/_gdb
--- ../z.old/Completion/User/_gdb	Wed Mar 22 09:13:27 2000
+++ Completion/User/_gdb	Wed Mar 22 09:14:15 2000
@@ -10,18 +10,21 @@
 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 @@
   (-[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 -ru ../z.old/Completion/User/_getconf Completion/User/_getconf
--- ../z.old/Completion/User/_getconf	Wed Mar 22 09:13:24 2000
+++ Completion/User/_getconf	Wed Mar 22 09:14:15 2000
@@ -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 @@
 	  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 -ru ../z.old/Completion/User/_gprof Completion/User/_gprof
--- ../z.old/Completion/User/_gprof	Wed Mar 22 09:13:27 2000
+++ Completion/User/_gprof	Wed Mar 22 09:14:16 2000
@@ -17,7 +17,7 @@
 if [[ -n "$state" ]]; then
   local cmd pair expl
 
-  _tags functions || return 1
+  _wanted functions || return 1
 
   [[ "$state" = pair ]] && pair=yes
 
diff -ru ../z.old/Completion/User/_groups Completion/User/_groups
--- ../z.old/Completion/User/_groups	Wed Mar 22 09:13:27 2000
+++ Completion/User/_groups	Wed Mar 22 09:14:16 2000
@@ -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 @@
   groups=( "$_cache_groups[@]" )
 fi
 
-compadd "$@" "$expl[@]" - "$groups[@]"
+_loop groups expl group compadd "$@" - "$groups[@]"
diff -ru ../z.old/Completion/User/_gs Completion/User/_gs
--- ../z.old/Completion/User/_gs	Wed Mar 22 09:13:27 2000
+++ Completion/User/_gs	Wed Mar 22 09:14:16 2000
@@ -25,8 +25,8 @@
     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 @@
     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 @@
         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 -ru ../z.old/Completion/User/_hosts Completion/User/_hosts
--- ../z.old/Completion/User/_hosts	Wed Mar 22 09:13:28 2000
+++ Completion/User/_hosts	Wed Mar 22 09:14:16 2000
@@ -9,5 +9,5 @@
   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 -ru ../z.old/Completion/User/_lp Completion/User/_lp
--- ../z.old/Completion/User/_lp	Wed Mar 22 09:13:28 2000
+++ Completion/User/_lp	Wed Mar 22 09:14:16 2000
@@ -36,14 +36,15 @@
 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 @@
       _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
   	  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
   	  disp=()
           fi
-          compadd "$expl[@]" "$disp[@]" - "$strs[@]" && ret=0
+          _loop jobs expl job compadd "$disp[@]" - "$strs[@]" && ret=0
         fi
         (( ret )) || return 0
       done
diff -ru ../z.old/Completion/User/_mailboxes Completion/User/_mailboxes
--- ../z.old/Completion/User/_mailboxes	Wed Mar 22 09:13:28 2000
+++ Completion/User/_mailboxes	Wed Mar 22 09:14:16 2000
@@ -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 @@
   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 @@
 
   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 @@
       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 @@
        ;;
   esac
 
-  local ret=1
   (( $#mbox_names )) && _multi_parts "$@" / mbox_names && ret=0
   (( $#mbox_short )) && compadd "$@" - "$mbox_short[@]" && ret=0
   return ret
diff -ru ../z.old/Completion/User/_make Completion/User/_make
--- ../z.old/Completion/User/_make	Wed Mar 22 09:13:28 2000
+++ Completion/User/_make	Wed Mar 22 09:14:17 2000
@@ -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 @@
     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 -ru ../z.old/Completion/User/_man Completion/User/_man
--- ../z.old/Completion/User/_man	Wed Mar 22 09:13:28 2000
+++ Completion/User/_man	Wed Mar 22 09:14:17 2000
@@ -33,5 +33,5 @@
   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 -ru ../z.old/Completion/User/_mh Completion/User/_mh
--- ../z.old/Completion/User/_mh	Wed Mar 22 09:13:28 2000
+++ Completion/User/_mh	Wed Mar 22 09:14:17 2000
@@ -17,13 +17,16 @@
   # 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 @@
     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 @@
   [[ -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 @@
     # 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 -ru ../z.old/Completion/User/_mount Completion/User/_mount
--- ../z.old/Completion/User/_mount	Wed Mar 22 09:13:29 2000
+++ Completion/User/_mount	Wed Mar 22 09:14:17 2000
@@ -539,11 +539,11 @@
 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 -ru ../z.old/Completion/User/_mutt Completion/User/_mutt
--- ../z.old/Completion/User/_mutt	Wed Mar 22 09:13:29 2000
+++ Completion/User/_mutt	Wed Mar 22 09:14:17 2000
@@ -25,8 +25,6 @@
  '-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 -ru ../z.old/Completion/User/_mysql_utils Completion/User/_mysql_utils
--- ../z.old/Completion/User/_mysql_utils	Wed Mar 22 09:13:35 2000
+++ Completion/User/_mysql_utils	Wed Mar 22 09:14:18 2000
@@ -24,33 +24,33 @@
   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 @@
        )
 
   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 -ru ../z.old/Completion/User/_netscape Completion/User/_netscape
--- ../z.old/Completion/User/_netscape	Wed Mar 22 09:13:29 2000
+++ Completion/User/_netscape	Wed Mar 22 09:14:18 2000
@@ -40,30 +40,31 @@
     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 @@
 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 -ru ../z.old/Completion/User/_nslookup Completion/User/_nslookup
--- ../z.old/Completion/User/_nslookup	Wed Mar 22 09:13:29 2000
+++ Completion/User/_nslookup	Wed Mar 22 09:14:18 2000
@@ -60,7 +60,7 @@
 
     _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 @@
 
   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 @@
     [[ -z "$state" ]] && return ret
     ;;
   *)
-    _wanted hosts expl 'server' && _hosts "$expl[@]"
+    _wanted hosts expl 'server' _hosts
     return
   esac
 fi
diff -ru ../z.old/Completion/User/_pbm Completion/User/_pbm
--- ../z.old/Completion/User/_pbm	Wed Mar 22 09:13:29 2000
+++ Completion/User/_pbm	Wed Mar 22 09:14:18 2000
@@ -254,7 +254,7 @@
     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 @@
   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 -ru ../z.old/Completion/User/_perl_basepods Completion/User/_perl_basepods
--- ../z.old/Completion/User/_perl_basepods	Wed Mar 22 09:13:30 2000
+++ Completion/User/_perl_basepods	Wed Mar 22 09:14:18 2000
@@ -29,5 +29,4 @@
 
 local expl
 
-_wanted pods expl 'Perl base pods' &&
-    compadd "$expl[@]" - $_perl_basepods
+_wanted pods expl 'Perl base pods' compadd - $_perl_basepods
diff -ru ../z.old/Completion/User/_perl_builtin_funcs Completion/User/_perl_builtin_funcs
--- ../z.old/Completion/User/_perl_builtin_funcs	Wed Mar 22 09:13:30 2000
+++ Completion/User/_perl_builtin_funcs	Wed Mar 22 09:14:18 2000
@@ -28,5 +28,4 @@
 
 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 -ru ../z.old/Completion/User/_perl_modules Completion/User/_perl_modules
--- ../z.old/Completion/User/_perl_modules	Wed Mar 22 09:13:30 2000
+++ Completion/User/_perl_modules	Wed Mar 22 09:14:19 2000
@@ -49,4 +49,4 @@
 
 local expl
 
-_wanted modules expl 'Perl modules' && compadd "$expl[@]" "$opts[@]" - $_perl_modules
+_wanted modules expl 'Perl modules' compadd "$opts[@]" - $_perl_modules
diff -ru ../z.old/Completion/User/_ports Completion/User/_ports
--- ../z.old/Completion/User/_ports	Wed Mar 22 09:13:30 2000
+++ Completion/User/_ports	Wed Mar 22 09:14:19 2000
@@ -9,4 +9,4 @@
   ports=( "$_cache_ports[@]" )
 fi
 
-_wanted ports expl port && compadd "$@" "$expl[@]" - "$ports[@]"
+_wanted ports expl port compadd "$@" - "$ports[@]"
diff -ru ../z.old/Completion/User/_rcs Completion/User/_rcs
--- ../z.old/Completion/User/_rcs	Wed Mar 22 09:13:31 2000
+++ Completion/User/_rcs	Wed Mar 22 09:14:19 2000
@@ -8,5 +8,5 @@
   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 -ru ../z.old/Completion/User/_rlogin Completion/User/_rlogin
--- ../z.old/Completion/User/_rlogin	Wed Mar 22 09:13:31 2000
+++ Completion/User/_rlogin	Wed Mar 22 09:14:19 2000
@@ -40,7 +40,7 @@
       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_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 -ru ../z.old/Completion/User/_socket Completion/User/_socket
--- ../z.old/Completion/User/_socket	Wed Mar 22 09:13:31 2000
+++ Completion/User/_socket	Wed Mar 22 09:14:19 2000
@@ -39,17 +39,16 @@
 
 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 -ru ../z.old/Completion/User/_ssh Completion/User/_ssh
--- ../z.old/Completion/User/_ssh	Wed Mar 22 09:13:31 2000
+++ Completion/User/_ssh	Wed Mar 22 09:14:20 2000
@@ -54,21 +54,18 @@
         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 @@
             _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 @@
             ;;
           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 @@
           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 @@
         ;;
       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 @@
       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 -ru ../z.old/Completion/User/_stty Completion/User/_stty
--- ../z.old/Completion/User/_stty	Wed Mar 22 09:13:31 2000
+++ Completion/User/_stty	Wed Mar 22 09:14:20 2000
@@ -4,18 +4,15 @@
 
 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 -ru ../z.old/Completion/User/_tar Completion/User/_tar
--- ../z.old/Completion/User/_tar	Wed Mar 22 09:13:32 2000
+++ Completion/User/_tar	Wed Mar 22 09:14:20 2000
@@ -142,8 +142,7 @@
     _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 -ru ../z.old/Completion/User/_telnet Completion/User/_telnet
--- ../z.old/Completion/User/_telnet	Wed Mar 22 09:13:32 2000
+++ Completion/User/_telnet	Wed Mar 22 09:14:20 2000
@@ -46,25 +46,25 @@
 
 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 -ru ../z.old/Completion/User/_tiff Completion/User/_tiff
--- ../z.old/Completion/User/_tiff	Wed Mar 22 09:13:32 2000
+++ Completion/User/_tiff	Wed Mar 22 09:14:20 2000
@@ -194,9 +194,12 @@
       ;;
     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 -ru ../z.old/Completion/User/_urls Completion/User/_urls
--- ../z.old/Completion/User/_urls	Wed Mar 22 09:13:33 2000
+++ Completion/User/_urls	Wed Mar 22 09:14:21 2000
@@ -49,16 +49,18 @@
 
 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 @@
 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 @@
 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 @@
       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 -ru ../z.old/Completion/User/_user_at_host Completion/User/_user_at_host
--- ../z.old/Completion/User/_user_at_host	Wed Mar 22 09:13:33 2000
+++ Completion/User/_user_at_host	Wed Mar 22 09:14:21 2000
@@ -22,9 +22,9 @@
 
   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 -ru ../z.old/Completion/User/_users Completion/User/_users
--- ../z.old/Completion/User/_users	Wed Mar 22 09:13:33 2000
+++ Completion/User/_users	Wed Mar 22 09:14:21 2000
@@ -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 -ru ../z.old/Completion/User/_users_on Completion/User/_users_on
--- ../z.old/Completion/User/_users_on	Wed Mar 22 09:13:33 2000
+++ Completion/User/_users_on	Wed Mar 22 09:14:21 2000
@@ -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 -ru ../z.old/Completion/User/_whois Completion/User/_whois
--- ../z.old/Completion/User/_whois	Wed Mar 22 09:13:34 2000
+++ Completion/User/_whois	Wed Mar 22 09:14:21 2000
@@ -189,14 +189,14 @@
 }
 
 _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 @@
   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 @@
   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 -ru ../z.old/Completion/User/_yp Completion/User/_yp
--- ../z.old/Completion/User/_yp	Wed Mar 22 09:13:34 2000
+++ Completion/User/_yp	Wed Mar 22 09:14:22 2000
@@ -95,15 +95,16 @@
 
   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 -ru ../z.old/Completion/X/_x_color Completion/X/_x_color
--- ../z.old/Completion/X/_x_color	Wed Mar 22 09:13:36 2000
+++ Completion/X/_x_color	Wed Mar 22 09:14:22 2000
@@ -30,6 +30,6 @@
   (( $#_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 -ru ../z.old/Completion/X/_x_cursor Completion/X/_x_cursor
--- ../z.old/Completion/X/_x_cursor	Wed Mar 22 09:13:36 2000
+++ Completion/X/_x_cursor	Wed Mar 22 09:14:22 2000
@@ -14,5 +14,5 @@
   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 -ru ../z.old/Completion/X/_x_display Completion/X/_x_display
--- ../z.old/Completion/X/_x_display	Wed Mar 22 09:13:36 2000
+++ Completion/X/_x_display	Wed Mar 22 09:14:22 2000
@@ -1,3 +1,3 @@
 #autoload
 
-_tags displays && _hosts -S ':0 ' -r :
+_wnated displays && _hosts -S ':0 ' -r :
diff -ru ../z.old/Completion/X/_x_extension Completion/X/_x_extension
--- ../z.old/Completion/X/_x_extension	Wed Mar 22 09:13:37 2000
+++ Completion/X/_x_extension	Wed Mar 22 09:14:22 2000
@@ -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 -ru ../z.old/Completion/X/_x_font Completion/X/_x_font
--- ../z.old/Completion/X/_x_font	Wed Mar 22 09:13:37 2000
+++ Completion/X/_x_font	Wed Mar 22 09:14:22 2000
@@ -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 @@
  _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 -ru ../z.old/Completion/X/_x_keysym Completion/X/_x_keysym
--- ../z.old/Completion/X/_x_keysym	Wed Mar 22 09:13:37 2000
+++ Completion/X/_x_keysym	Wed Mar 22 09:14:23 2000
@@ -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 @@
   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 -ru ../z.old/Completion/X/_x_modifier Completion/X/_x_modifier
--- ../z.old/Completion/X/_x_modifier	Wed Mar 22 09:13:37 2000
+++ Completion/X/_x_modifier	Wed Mar 22 09:14:23 2000
@@ -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 -ru ../z.old/Completion/X/_x_window Completion/X/_x_window
--- ../z.old/Completion/X/_x_window	Wed Mar 22 09:13:37 2000
+++ Completion/X/_x_window	Wed Mar 22 09:14:23 2000
@@ -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 -ru ../z.old/Completion/X/_xmodmap Completion/X/_xmodmap
--- ../z.old/Completion/X/_xmodmap	Wed Mar 22 09:13:37 2000
+++ Completion/X/_xmodmap	Wed Mar 22 09:14:23 2000
@@ -82,9 +82,12 @@
     [[ "$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 -ru ../z.old/Completion/X/_xutils Completion/X/_xutils
--- ../z.old/Completion/X/_xutils	Wed Mar 22 09:13:38 2000
+++ Completion/X/_xutils	Wed Mar 22 09:14:23 2000
@@ -55,20 +55,23 @@
     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 -ru ../z.old/Doc/Zsh/compsys.yo Doc/Zsh/compsys.yo
--- ../z.old/Doc/Zsh/compsys.yo	Wed Mar 22 09:13:01 2000
+++ Doc/Zsh/compsys.yo	Wed Mar 22 11:30:45 2000
@@ -806,33 +806,38 @@
 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 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 @@
 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 @@
 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 @@
 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 @@
 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 @@
 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 @@
 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 @@
 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 @@
 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)',
@@ -2415,6 +2534,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
diff -ru ../z.old/Doc/Zsh/mod_zutil.yo Doc/Zsh/mod_zutil.yo
--- ../z.old/Doc/Zsh/mod_zutil.yo	Wed Mar 22 09:13:04 2000
+++ Doc/Zsh/mod_zutil.yo	Wed Mar 22 09:14:24 2000
@@ -70,7 +70,8 @@
 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 -ru ../z.old/Etc/completion-style-guide Etc/completion-style-guide
--- ../z.old/Etc/completion-style-guide	Wed Mar 22 09:13:05 2000
+++ Etc/completion-style-guide	Wed Mar 22 11:33:44 2000
@@ -9,21 +9,21 @@
 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 @@
 
 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:
-
-  _tags names || return 1
-
-  _description names expl 'name'
-  compadd "$expl[@]" - 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:
+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:
+
+  _wanted names || return 1
+
+  _loop names expl 'name' compadd - alice bob
+
+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:
+
+  _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 "$expl[@]" alice bob
+  _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 ...
 
-The more complicated case is where you can offer multiple types of
+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
+
+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 @@
   _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 (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:
-
-  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
+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.
+
+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 -ru ../z.old/Functions/Zftp/zfcd_match Functions/Zftp/zfcd_match
--- ../z.old/Functions/Zftp/zfcd_match	Wed Mar 22 09:13:48 2000
+++ Functions/Zftp/zfcd_match	Wed Mar 22 09:14:24 2000
@@ -30,8 +30,7 @@
   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 -ru ../z.old/Functions/Zftp/zfget_match Functions/Zftp/zfget_match
--- ../z.old/Functions/Zftp/zfget_match	Wed Mar 22 09:13:48 2000
+++ Functions/Zftp/zfget_match	Wed Mar 22 09:14:24 2000
@@ -17,8 +17,7 @@
     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 @@
   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 -ru ../z.old/Src/Modules/zutil.c Src/Modules/zutil.c
--- ../z.old/Src/Modules/zutil.c	Wed Mar 22 09:13:00 2000
+++ Src/Modules/zutil.c	Wed Mar 22 09:14:25 2000
@@ -430,7 +430,7 @@
 			     !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 -ru ../z.old/Src/Zle/computil.c Src/Zle/computil.c
--- ../z.old/Src/Zle/computil.c	Wed Mar 22 09:12:55 2000
+++ Src/Zle/computil.c	Wed Mar 22 09:35:37 2000
@@ -2180,6 +2180,8 @@
 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 @@
 
 	if (s->tags)
 	    freearray(s->tags);
+	zsfree(s->tag);
 	zfree(s, sizeof(*s));
 
 	s = n;
@@ -2240,12 +2243,20 @@
 /* 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 @@
 	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 @@
     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 @@
 	    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 @@
 	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 @@
 
 	    s->tags = zarrdup(args);
 	    s->next = NULL;
+	    s->ptr = NULL;
+	    s->tag = NULL;
 
 	    if ((l = comptags[lasttaglevel]->sets)) {
 		while (l->next)

--
Sven Wischnowsky                         wischnow@xxxxxxxxxxxxxxxxxxxxxxx



Messages sorted by: Reverse Date, Date, Thread, Author