about summary refs log tree commit diff
path: root/Completion
diff options
context:
space:
mode:
authorSven Wischnowsky <wischnow@users.sourceforge.net>2000-04-11 07:57:56 +0000
committerSven Wischnowsky <wischnow@users.sourceforge.net>2000-04-11 07:57:56 +0000
commitfac3086d9782e73dcaf1aa65fd36a0b63a374719 (patch)
tree7bab35e2787ca17f02ec932dffae1bfff2ffcfe3 /Completion
parent37012f06a7e5e8a64614dbf9032c77cff1bcfcfb (diff)
downloadzsh-fac3086d9782e73dcaf1aa65fd36a0b63a374719.tar.gz
zsh-fac3086d9782e73dcaf1aa65fd36a0b63a374719.tar.xz
zsh-fac3086d9782e73dcaf1aa65fd36a0b63a374719.zip
_wanted now tests both tags and labels; change places where _wanted was called without a command; allow multiple patterns per string in file-patterns; update _next_tags to work with labels (10632)
Diffstat (limited to 'Completion')
-rw-r--r--Completion/Base/_brace_parameter6
-rw-r--r--Completion/Base/_condition59
-rw-r--r--Completion/Base/_default2
-rw-r--r--Completion/Base/_describe45
-rw-r--r--Completion/Base/_first25
-rw-r--r--Completion/Base/_jobs6
-rw-r--r--Completion/Base/_values2
-rw-r--r--Completion/Builtins/_compdef16
-rw-r--r--Completion/Builtins/_hash19
-rw-r--r--Completion/Builtins/_pids4
-rw-r--r--Completion/Builtins/_popd4
-rw-r--r--Completion/Builtins/_sched4
-rw-r--r--Completion/Builtins/_signals9
-rw-r--r--Completion/Builtins/_vars12
-rw-r--r--Completion/Builtins/_zcompile3
-rw-r--r--Completion/Builtins/_zftp15
-rw-r--r--Completion/Builtins/_zpty6
-rw-r--r--Completion/Builtins/_zstyle26
-rw-r--r--Completion/Commands/_next_tags168
-rw-r--r--Completion/Core/_all_labels30
-rw-r--r--Completion/Core/_files59
-rw-r--r--Completion/Core/_next_label5
-rw-r--r--Completion/Core/_requested1
-rw-r--r--Completion/Core/_wanted19
-rw-r--r--Completion/Debian/_apt2
-rw-r--r--Completion/Debian/_deb_packages58
-rw-r--r--Completion/User/_cvs1190
-rw-r--r--Completion/User/_gdb5
-rw-r--r--Completion/User/_gprof60
-rw-r--r--Completion/User/_groups4
-rw-r--r--Completion/User/_lp35
-rw-r--r--Completion/User/_mh15
-rw-r--r--Completion/User/_mount2
-rw-r--r--Completion/User/_netscape24
-rw-r--r--Completion/User/_nslookup52
-rw-r--r--Completion/User/_rlogin8
-rw-r--r--Completion/User/_socket49
-rw-r--r--Completion/User/_tiff6
-rw-r--r--Completion/User/_urls91
-rw-r--r--Completion/User/_users6
-rw-r--r--Completion/User/_users_on6
-rw-r--r--Completion/User/_whois61
-rw-r--r--Completion/X/_x_colormapid4
-rw-r--r--Completion/X/_x_display2
-rw-r--r--Completion/X/_x_extension6
-rw-r--r--Completion/X/_x_font4
-rw-r--r--Completion/X/_x_keysym4
-rw-r--r--Completion/X/_x_window6
-rw-r--r--Completion/X/_xmodmap6
-rw-r--r--Completion/X/_xutils24
-rw-r--r--Completion/X/_xwit2
51 files changed, 1233 insertions, 1044 deletions
diff --git a/Completion/Base/_brace_parameter b/Completion/Base/_brace_parameter
index 092376e78..fde6d4f0f 100644
--- a/Completion/Base/_brace_parameter
+++ b/Completion/Base/_brace_parameter
@@ -1,5 +1,3 @@
-#defcomp -brace-parameter-
+#compdef -brace-parameter-
 
-# Simple but without spiffy suffix handling: compgen -v -S '} '
-
-compadd -S '} ' -r '-:?#%+=[/'  - "${(@)${${${(f)$(typeset)}%%\=*}##* }:gs/'//}"
+_parameters -e
diff --git a/Completion/Base/_condition b/Completion/Base/_condition
index 3e45e1b8f..b6a4eff7a 100644
--- a/Completion/Base/_condition
+++ b/Completion/Base/_condition
@@ -1,10 +1,55 @@
-#defcomp -condition-
+#compdef -condition-
 
-if [[ -current -1 -o ]]; then
-  complist -o -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}'
-elif [[ -current -1 -nt || -current -1 -ot || -current -1 -ef ]]; then
-  _files
+local prev="$words[CURRENT-1]" ret=1
+
+if [[ "$prev" = -o ]]; then
+  _tags -C -o options && _options
+elif [[ "$prev" = -([a-hkprsuwxLOGSN]|[no]t|ef) ]]; then
+  _tags -C "$prev" files && _files
 else
-  _files
-  complist -v
+  if [[ "$PREFIX" = -* ]] ||
+     ! zstyle -T ":completion:${curcontext}:options" prefix-needed; then
+
+    if [[ "$prev" = (\[\[|\|\||\&\&|\!|\() ]]; then
+      _describe -o 'condition code' \
+                '( -a:existing\ file
+	           -b:block\ special\ file
+	           -c:character\ special\ file
+	           -d:directory
+	           -e:existing\ file
+	           -f:regular\ file
+	           -g:setgid\ bit
+	           -h:symbolic\ link
+	           -k:sticky\ bit
+	           -n:non-empty\ string
+	           -o:option
+	           -p:named\ pipe
+	           -r:readable\ file
+	           -s:non-empty\ file
+	           -t:terminal\ file\ descriptor
+	           -u:setuid\ bit
+	           -w:writable\ file
+	           -x:executable\ file
+	           -z:empty\ string
+	           -L:symbolic\ link
+	           -O:own\ file
+	           -G:group-owned\ file
+	           -S:socket
+	           -N:unread\ file)' && ret=0
+    else
+      _describe -o 'condition code' \
+	        '( -nt:newer\ than
+	           -ot:older\ than
+	           -ef:same\ file
+	           -eq:numerically\ equal
+	           -ne:numerically\ not\ equal
+	           -lt:numerically\ less\ than
+	           -le:numerically\ less\ then\ or\ equal
+	           -lt:numerically\ greater\ than
+	           -le:numerically\ greater\ then\ or\ equal)' && ret=0
+    fi
+  fi
+  _alternative 'files:: _files' 'parameters:: _parameters' && ret=0
+
+  return ret
 fi
diff --git a/Completion/Base/_default b/Completion/Base/_default
index fd5869e2e..e5091a544 100644
--- a/Completion/Base/_default
+++ b/Completion/Base/_default
@@ -12,8 +12,6 @@ if { zstyle -s ":completion:${curcontext}:" use-compctl ctl ||
   compcall "$opt[@]" || return 0
 fi
 
-_wanted files || return 1
-
 _files && return 0
 
 # magicequalsubst allows arguments like <any-old-stuff>=~/foo to do
diff --git a/Completion/Base/_describe b/Completion/Base/_describe
index 6e6f4f4a9..ca2d3e4cf 100644
--- a/Completion/Base/_describe
+++ b/Completion/Base/_describe
@@ -14,8 +14,6 @@ fi
 
 # Do the tests. `showd' is set if the descriptions should be shown.
 
-_wanted "$_type" || return 1
-
 zstyle -T ":completion:${curcontext}:$_type" verbose && _showd=yes
 
 _descr="$1"
@@ -24,30 +22,35 @@ shift
 [[ "$_type" = options ]] &&
     zstyle -t ":completion:${curcontext}:options" prefix-hidden && _hide=yes
 
-while _next_label "$_type" _expl "$_descr"; do
+_tags "$_type"
+while _tags; do
+  while _next_label "$_type" _expl "$_descr"; do
 
-  if [[ -n "$_showd" ]]; then
-    compdescribe -I ' -- ' "$@"
-  else
-    compdescribe -i "$@"
-  fi
+    if [[ -n "$_showd" ]]; then
+      compdescribe -I ' -- ' "$@"
+    else
+      compdescribe -i "$@"
+    fi
 
-  while compdescribe -g _args _tmpd _tmpmd _tmps _tmpms; do
+    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
+      compadd "$_args[@]" "$_expl[@]" -ld _tmpd - "$_tmpmd[@]" && _ret=0
+      compadd "$_args[@]" "$_expl[@]" -d _tmps  - "$_tmpms[@]" && _ret=0
+    done
   done
+  (( _ret )) || return 0
 done
-return _ret
+
+return 1
diff --git a/Completion/Base/_first b/Completion/Base/_first
index d9e7ee82c..93602f307 100644
--- a/Completion/Base/_first
+++ b/Completion/Base/_first
@@ -35,28 +35,35 @@
 # and hitting TAB.
 #
 #     if [[ "$PREFIX" = *,, ]]; then
-#       local max i=1
+#       local max i=1 expl opt
 #     
 #       PREFIX="$PREFIX[1,-2]"
 #       # If a numeric prefix is given, we use it as the number of
 #       # lines (multiplied by ten below) in the history to search.
-#       if [[ NUMERIC -gt 1 ]]; then
+#       if [[ ${NUMERIC:-1} -gt 1 ]]; then
 #         max=$NUMERIC
-#         NUMERIC=1
+#         unset NUMERIC
 #       else
 #         # The default is to search the last 100 lines.
 #         max=10
 #       fi
-#       # We first search in the last ten lines, then in the last
-#       # twenty lines, and so on...
+#       # We first search in the last ten words, then in the last
+#       # twenty words, and so on...
 #       while [[ i -le max ]]; do
-#         if compgen -X "%Bhistory ($n):%b" -Q -H $(( i*10 )) ''; then
+#         if zstyle -t ":completion:${curcontext}:history-words" sort; then
+#           opt=-J
+#         else
+#           opt=-V
+#         fi
+#         if _wanted "$opt" history-words expl "history ($n)" \
+#                compadd "$expl[@]" -Q - \
+#                    "${(@)${(@)historywords:#[\$'\"]*}[1,i*10]}"; then
 #           # We have found at least one matching word, so we switch
 #           # on menu-completion and make sure that no other
-#           # completion function is called by setting _comp_skip.
+#           # completion function is called by setting _compskip.
 #           compstate[insert]=menu
-#           _comp_skip=1
-#           return
+#           _compskip=all
+#           return 0
 #         fi
 #         (( i++ ))
 #       done
diff --git a/Completion/Base/_jobs b/Completion/Base/_jobs
index 45983ad16..359cf0905 100644
--- a/Completion/Base/_jobs
+++ b/Completion/Base/_jobs
@@ -2,8 +2,6 @@
 
 local expl disp jobs job jids pfx='%' desc how expls
 
-_wanted jobs || return 1
-
 if [[ "$1" = -t ]]; then
   zstyle -T ":completion:${curcontext}:jobs" prefix-needed &&
       [[ "$PREFIX" != %* && compstate[nmatches] -ne 0 ]] && return 1
@@ -79,7 +77,7 @@ else
 fi
 
 if [[ -n "$desc" ]]; then
-  _all_labels jobs expl "$expls" compadd "$@" -ld disp - "%$^jobs[@]"
+  _wanted jobs expl "$expls" compadd "$@" -ld disp - "%$^jobs[@]"
 else
-  _all_labels jobs expl "$expls" compadd "$@" - "%$^jobs[@]"
+  _wanted jobs expl "$expls" compadd "$@" - "%$^jobs[@]"
 fi
diff --git a/Completion/Base/_values b/Completion/Base/_values
index eff7b94ce..39c8df201 100644
--- a/Completion/Base/_values
+++ b/Completion/Base/_values
@@ -18,7 +18,7 @@ if compvalues -i "$@"; then
 
   if ! compvalues -D descr action; then
 
-    _wanted values || return 1
+    _tags values || return 1
 
     curcontext="${oldcontext%:*}:values"
 
diff --git a/Completion/Builtins/_compdef b/Completion/Builtins/_compdef
index d47a560c9..6287810e5 100644
--- a/Completion/Builtins/_compdef
+++ b/Completion/Builtins/_compdef
@@ -19,15 +19,13 @@ case $state in
     _wanted commands expl 'completed command' compadd - ${(k)_comps}
   ;;
   cfun)
-    if _wanted functions; then
-      list=( ${^fpath:/.}/_(|*[^~])(N:t) )
-      if zstyle -T ":completion:${curcontext}:functions" prefix-hidden; then
-        disp=( ${list[@]#_} )
-        _all_labels functions expl 'completion function' \
-            compadd -d disp - "$list[@]"
-      else
-        _all_labels functions expl 'completion function' compadd - "$list[@]"
-      fi
+    list=( ${^fpath:/.}/_(|*[^~])(N:t) )
+    if zstyle -T ":completion:${curcontext}:functions" prefix-hidden; then
+      disp=( ${list[@]#_} )
+      _wanted functions expl 'completion function' \
+          compadd -d disp - "$list[@]"
+    else
+      _wanted functions expl 'completion function' compadd - "$list[@]"
     fi
   ;;
   style)
diff --git a/Completion/Builtins/_hash b/Completion/Builtins/_hash
index 171c5e2e8..c577fc4d7 100644
--- a/Completion/Builtins/_hash
+++ b/Completion/Builtins/_hash
@@ -1,13 +1,16 @@
-#defcomp hash
+#compdef hash
 
-if [[ -mword 1 -*d* ]]; then
-  if [[ -string 1 '=' ]]; then
-    _path_files -g '*(-/)'
+local expl
+
+if [[ "$words[2]" = -*d* ]]; then
+  if compset -P 1 '*='; then
+    _wanted -C -d-value files expl directories _path_files -/
   else
-    complist -n -q -S '='
+    _wanted -C -d named-directories expl 'named directory' \
+        compadd -q -S '=' - "${(@k)nameddirs}"
   fi
-elif [[ -string 1 '=' ]]; then
-  _files -/g '*(*)'
+elif compset -P 1 '*='; then
+  _wanted -C value values expl 'executable file' _files "$expl[@]" -g '*(-*)'
 else
-  complist -m -q -S '='
+  _wanted -C name commands expl command compadd -q -S '=' - "${(@k)commands}"
 fi
diff --git a/Completion/Builtins/_pids b/Completion/Builtins/_pids
index 7dec90e7d..1d02f5530 100644
--- a/Completion/Builtins/_pids
+++ b/Completion/Builtins/_pids
@@ -5,7 +5,7 @@
 
 local out list expl match desc listargs args
 
-_wanted processes || return 1
+_tags processes || return 1
 
 if [[ "$1" = -m ]]; then
   match="${2}*"
@@ -29,6 +29,6 @@ else
   desc=()
 fi
 
-_all_labels processes expl 'process ID' \
+_wanted processes expl 'process ID' \
     compadd "$@" "$desc[@]" - \
         ${${${(M)${(f)"${out}"}[2,-1]:#[ 	]#${PREFIX}[0-9]#${SUFFIX}[ 	]#*${~match}}## #}%% *}
diff --git a/Completion/Builtins/_popd b/Completion/Builtins/_popd
index 2a3413253..19b773173 100644
--- a/Completion/Builtins/_popd
+++ b/Completion/Builtins/_popd
@@ -12,8 +12,6 @@ local expl list lines revlines disp
 ! zstyle -T ":completion:${curcontext}:directory-stack" prefix-needed ||
     [[ $PREFIX = [-+]* ]] || 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
   # and turn the lines into an array, removing the current directory
@@ -39,5 +37,5 @@ else
   disp=()
 fi
 
-_all_labels -V directory-stack expl 'directory stack' \
+_wanted -V directory-stack expl 'directory stack' \
     compadd "$@" "$disp[@]" -Q - "$list[@]"
diff --git a/Completion/Builtins/_sched b/Completion/Builtins/_sched
index 98ecb3642..82b8a7c91 100644
--- a/Completion/Builtins/_sched
+++ b/Completion/Builtins/_sched
@@ -4,15 +4,13 @@ local expl lines disp
 
 if [[ CURRENT -eq 2 ]]; then
   if compset -P -; then
-    _wanted -C - jobs || return 1
-
     lines=(${(f)"$(sched)"})
     if zstyle -T ":completion:${curcontext}:jobs" verbose; then
       disp=( -ld lines )
     else
       disp=()
     fi
-    [[ -z $lines ]] || _all_labels jobs expl 'scheduled jobs' \
+    [[ -z $lines ]] || _wanted jobs expl 'scheduled jobs' \
                            compadd "$disp[@]" - {1..$#lines}
     return
   else
diff --git a/Completion/Builtins/_signals b/Completion/Builtins/_signals
index aa95a8499..447d9d16c 100644
--- a/Completion/Builtins/_signals
+++ b/Completion/Builtins/_signals
@@ -20,10 +20,9 @@ done
 
 [[ "$1" = -(|-) ]] && shift
 
-if _wanted signals &&
-       { [[ -z "$minus" ]] ||
-         ! zstyle -T ":completion:${curcontext}:signals" prefix-needed ||
-         [[ "$PREFIX" = -* ]] } ; then
+if [[ -z "$minus" ]] ||
+   ! zstyle -T ":completion:${curcontext}:signals" prefix-needed ||
+   [[ "$PREFIX" = -* ]]; then
   local disp tmp
 
   if zstyle -t ":completion:${curcontext}:signals" prefix-hidden; then
@@ -32,7 +31,7 @@ if _wanted signals &&
   else
     disp=()
   fi
-  _all_labels signals expl signal \
+  _wanted signals expl signal \
       compadd "$@" "$disp[@]" -M 'm:{a-z}={A-Z}' - \
               "${minus}${(@)^signals[1,last]}"
 fi
diff --git a/Completion/Builtins/_vars b/Completion/Builtins/_vars
index 43cdf5d2c..711a0a1f2 100644
--- a/Completion/Builtins/_vars
+++ b/Completion/Builtins/_vars
@@ -1,8 +1,8 @@
 #compdef getopts read unset vared
 
 # This will handle completion of keys of associative arrays, e.g. at
-# `vared compconfig[<TAB>'.  However, in this version the [ must be
-# added by hand.
+# `vared foo[<TAB>'.  However, in this version the [ must be added
+# by hand.
 
 if [[ $PREFIX = *\[* ]]; then
   local var=${PREFIX%%\[*}
@@ -16,13 +16,9 @@ if [[ $PREFIX = *\[* ]]; then
   if [[ ${(tP)var} = assoc* ]]; then
     local expl
 
-    _tags subscript association-keys || return 1
-
-    _description expl 'association key'
-    compadd "$expl[@]" $addclose - ${(kP)var}
+    _wanted -C subscript association-keys expl 'association key' \
+        compadd $addclose - ${(kP)var}
   fi
 else
-  _tags any parameters || return 1
-
   _parameters
 fi
diff --git a/Completion/Builtins/_zcompile b/Completion/Builtins/_zcompile
index 5ec6f96ce..c82226dc2 100644
--- a/Completion/Builtins/_zcompile
+++ b/Completion/Builtins/_zcompile
@@ -18,5 +18,6 @@ _arguments -s \
 if (( $+opt_args[-c] )); then
   _wanted functions expl 'function to write' compadd - ${(k)functions}
 else
-  _wanted file expl 'zsh source file' _files
+  _description files expl 'zsh source file'
+  _files "$expl[@]"
 fi
diff --git a/Completion/Builtins/_zftp b/Completion/Builtins/_zftp
index 0d6530dfc..610af2607 100644
--- a/Completion/Builtins/_zftp
+++ b/Completion/Builtins/_zftp
@@ -28,35 +28,34 @@ fi
 case $subcom in
   *(cd|ls|dir))
     # complete remote directories
-    _wanted directories && zfcd_match $PREFIX $SUFFIX
+    _tags directories && zfcd_match $PREFIX $SUFFIX
     ;;
 
   *(get(|at)|gcp|delete|remote))
     # complete remote files
-    _wanted files && zfget_match $PREFIX $SUFFIX
+    _tags files && zfget_match $PREFIX $SUFFIX
     ;;
 
   *(put(|at)|pcp))
     # complete local files
-    _wanted files && _files
+    _files
     ;;
 
   *(open|anon|params))
     # complete hosts:  should do cleverer stuff with user names
-    _wanted hosts && _hosts
+    _hosts
     ;;
 
   *(goto|mark))
     # complete bookmarks.  First decide if ncftp mode is go.
-    _wanted bookmarks || return 1
     if [[ $words[2] = -*n* ]]; then
       if [[ -f ~/.ncftp/bookmarks ]]; then
-        _all_labels bookmarks expl bookmark \
+        _wanted bookmarks expl bookmark \
             compadd - $(awk -F, 'NR > 2 { print $1 }' ~/.ncftp/bookmarks)
       fi
     else
       if [[ -f ${ZFTP_BMFILE:=${ZDOTDIR:-$HOME}/.zfbkmarks} ]]; then
-        _all_labels bookmarks expl bookmark \
+        _wanted bookmarks expl bookmark \
             compadd - $(awk '{print $1}' $ZFTP_BMFILE)
       fi
     fi
@@ -72,7 +71,7 @@ case $subcom in
     # complete arguments like sess1:file1 sess2:file2
     if [[ $PREFIX = *:* ]]; then
       # complete file in the given session
-      _wanted files || return 1
+      _tags files || return 1
       local sess=${PREFIX%%:*} oldsess=$ZFTP_SESSION
       compset -p $(( $#sess + 1 ))
       [[ -n $sess ]] && zftp session $sess
diff --git a/Completion/Builtins/_zpty b/Completion/Builtins/_zpty
index d8c77ff2e..ac631baf4 100644
--- a/Completion/Builtins/_zpty
+++ b/Completion/Builtins/_zpty
@@ -11,13 +11,13 @@ _arguments -C -s \
   '(-e -b -d -w -r)-L[list defined commands as calls]' \
   '(-r)*::args:_normal'
 
-if [[ $state = name ]] && _wanted names; then
+if [[ $state = name ]]; then
   list=( ${${(f)"$(zpty)"}#*\) } )
   names=( ${list%%:*} )
   if zstyle -T ":completion:${curcontext}" verbose; then
     zformat -a list ' --' ${${(f)"$(zpty)"}#*\) }
-    _all_labels names expl 'zpty command names' compadd -d list - "$names[@]"
+    _wanted names expl 'zpty command names' compadd -d list - "$names[@]"
   else
-    _all_labels names expl 'zpty command names' compadd - "$names[@]"
+    _wanted names expl 'zpty command names' compadd - "$names[@]"
   fi
 fi
diff --git a/Completion/Builtins/_zstyle b/Completion/Builtins/_zstyle
index b4e151d78..b19303300 100644
--- a/Completion/Builtins/_zstyle
+++ b/Completion/Builtins/_zstyle
@@ -96,20 +96,18 @@ while [[ -n $state ]]; do
 
   case "$ostate" in
     contexts)
-      if _wanted contexts; then
-        if [[ $PREFIX != :*: ]]; then
-	  _all_labels contexts expl context compadd -P : -S : completion zftp
-        elif [[ $PREFIX = :completion:* ]]; then
-          mesg=''
-          case "$PREFIX" in
-          :completion:[^:]#) mesg=function ;;
-          :completion:[^:]#:[^:]#) mesg=completer ;;
-          :completion:[^:]#:[^:]#:[^:]#) mesg='command or context' ;;
-          :completion:[^:]#:[^:]#:[^:]#:[^:]#) mesg=argument ;;
-          :completion:[^:]#:[^:]#:[^:]#:[^:]#:[^:]#) mesg=tag ;;
-	  esac
-	  [[ -n "$mesg" ]] && _message "$mesg"
-        fi
+      if [[ $PREFIX != :*: ]]; then
+	_wanted contexts expl context compadd -P : -S : completion zftp
+      elif [[ $PREFIX = :completion:* ]] && _tags contexts; then
+        mesg=''
+        case "$PREFIX" in
+        :completion:[^:]#) mesg=function ;;
+        :completion:[^:]#:[^:]#) mesg=completer ;;
+        :completion:[^:]#:[^:]#:[^:]#) mesg='command or context' ;;
+        :completion:[^:]#:[^:]#:[^:]#:[^:]#) mesg=argument ;;
+        :completion:[^:]#:[^:]#:[^:]#:[^:]#:[^:]#) mesg=tag ;;
+	esac
+	[[ -n "$mesg" ]] && _message "$mesg"
       fi
       ;;
 
diff --git a/Completion/Commands/_next_tags b/Completion/Commands/_next_tags
index d9a5f08d8..a308b307c 100644
--- a/Completion/Commands/_next_tags
+++ b/Completion/Commands/_next_tags
@@ -3,30 +3,103 @@
 # Main widget.
 
 _next_tags() {
-  local comp ins
+  local ins ops="$PREFIX$SUFFIX"
 
-  if [[ -z $compstate[old_list] ]]; then
-    comp=()
+  unfunction _all_labels _next_label
+
+  _all_labels() {
+    local gopt=-J len tmp pre suf ret=1 descr spec
+
+    if [[ "$1" = -([12]|)[VJ] ]]; then
+      gopt="$1"
+      shift
+    fi
+
+    tmp=${argv[(ib:4:)-]}
+    len=$#
+    if [[ tmp -lt len ]]; then
+      pre=$(( tmp-1 ))
+      suf=$tmp
+    elif [[ tmp -eq $# ]]; then
+      pre=-2
+      suf=$(( len+1 ))
+    else
+      pre=4
+      suf=5
+    fi
+
+    while comptags -A "$1" curtag spec; do
+      [[ "$_next_tags_not" = *\ ${spec}\ * ]] && continue
+      _comp_tags="$_comp_tags $spec "
+      if [[ "$curtag" = *:* ]]; then
+        zformat -f descr "${curtag#*:}" "d:$3"
+        _description "$gopt" "${curtag%:*}" "$2" "$descr"
+        curtag="${curtag%:*}"
+
+        "$4" "${(P@)2}" "${(@)argv[5,-1]}"
+      else
+        _description "$gopt" "$curtag" "$2" "$3"
+
+        "${(@)argv[4,pre]}" "${(P@)2}" "${(@)argv[suf,-1]}" && ret=0
+      fi
+    done
+
+    return ret
+  }
+
+  _next_label() {
+    local gopt=-J descr spec
+
+    if [[ "$1" = -([12]|)[VJ] ]]; then
+      gopt="$1"
+      shift
+    fi
+
+    if comptags -A "$1" curtag spec; then
+      [[ "$_next_tags_not" = *\ ${spec}\ * ]] && continue
+      _comp_tags="$_comp_tags $spec "
+      if [[ "$curtag" = *:* ]]; then
+        zformat -f descr "${curtag#*:}" "d:$3"
+        _description "$gopt" "${curtag%:*}" "$2" "$descr"
+        curtag="${curtag%:*}"
+        eval "${2}=( \${(P)2} \$argv[4,-1] )"
+      else
+        _description "$gopt" "$curtag" "$2" "$3"
+        eval "${2}=( \$argv[4,-1] \${(P)2} )"
+      fi
+
+      return 0
+    fi
+
+    return 1
+  }
+
+  if [[ "${LBUFFER%${PREFIX}}" = "$_next_tags_pre" ]]; then
+    PREFIX="$_next_tags_pfx"
+    SUFFIX="$_next_tags_sfx"
   else
-    comp=(_complete)
+    _next_tags_pre="${LBUFFER%${PREFIX}}"
+    if [[ "$LASTWIDGET" = (_next_tags|list-*|*complete*) ]]; then
+      PREFIX="$_lastcomp[prefix]"
+      SUFFIX="$_lastcomp[suffix]"
+    fi
   fi
 
-  (( $+_sort_tags )) || _next_tags_not=
-
-  _sort_tags=_next_tags_sort
-  _next_tags_pre="${LBUFFER%${PREFIX}}"
   _next_tags_not="$_next_tags_not $_lastcomp[tags]"
+  _next_tags_pfx="$PREFIX"
+  _next_tags_sfx="$SUFFIX"
 
   if [[ -n "$compstate[old_insert]" ]]; then
-    PREFIX="$_lastcomp[prefix]"
-    SUFFIX="$_lastcomp[suffix]"
     ins=1
+  else
+    ins=unambiguous
   fi
 
-  _main_complete "$comp[@]"
+  _main_complete _complete _next_tags_completer
 
-  [[ $compstate[insert] = automenu ]] &&
-     compstate[insert]=automenu-unambiguous
+  [[ $compstate[insert] = automenu ]] && compstate[insert]=automenu-unambiguous
+  [[ $compstate[insert] = *unambiguous && -n "$ops" &&
+     -z "$_lastcomp[unambiguous]" ]] && compadd -Uns "$SUFFIX" - "$PREFIX"
 
   compstate[insert]="$ins"
   compstate[list]='list force'
@@ -34,11 +107,19 @@ _next_tags() {
   compprefuncs=( "$compprefuncs[@]" _next_tags_pre )
 }
 
+# Completer, for wrap-around.
+
+_next_tags_completer() {
+  _next_tags_not=
+
+  _complete
+}
+
 # Pre-completion function.
 
 _next_tags_pre() {
 
-  # Probably `remove' our sort function. A better test would be nice, but
+  # Probably `remove' our label functions. A better test would be nice, but
   # I think one should still be able to edit the current word between
   # attempts to complete it.
 
@@ -47,65 +128,10 @@ _next_tags_pre() {
     compstate[insert]=menu:2
     return 0
   elif [[ ${LBUFFER%${PREFIX}} != ${_next_tags_pre}* ]]; then
-    unset _sort_tags
+    unfunction _all_labels _next_label
+    autoload -U _all_labels _next_label
   else
     compprefuncs=( "$compprefuncs[@]" _next_tags_pre )
-    [[ -n "$compstate[old_list]" && -n "$_next_tags_reset" ]] &&
-        _next_tags_not= _next_tags_reset=
-  fi
-}
-
-# Helper function for sorting tags. Most of this is copied from _tags.
-
-_next_tags_sort() {
-  local order tags tag nodef tmp
-
-  zstyle -a ":completion:${curcontext}:" tag-order order ||
-      order=('arguments values' options)
-
-  # But we also remove the tags we've already tried...
-
-  tags=( "${(@)order:#(${(j:|:)~${=_next_tags_not}})(|:*)}" )
-
-  # ... unless that would remove all offered tags.
-
-  if [[ $funcstack[4] = _files ]]; then
-    if zstyle -a ":completion:${curcontext}:" file-patterns tmp; then
-      [[ "$tags" = *${${tmp[-1]##[^\\]:}%:*}* ]] &&
-          tags=( $order ) _next_tags_reset=yes
-    else
-      [[ "$tags" = *all-files* ]] && tags=( $order ) _next_tags_reset=yes
-    fi
-  else
-     [[ $#tags -ne $#order && "$tags" != *(${(j:|:)~argv})* ]] &&
-        tags=( $order ) _next_tags_reset=yes
-  fi
-  for tag in $tags; do
-    case $tag in
-    -)     nodef=yes;;
-    *\(\)) "${${tag%%[ 	]#\(\)}##[ 	]#}" "$@";;
-    \!*)   comptry "${(@)argv:#(${(j:|:)~${=~tag[2,-1]}})}";;
-    ?*)    comptry -m "$tag";;
-    esac
-  done
-
-  if [[ -z "$nodef" ]]; then
-    if [[ $funcstack[4] = _files ]]; then
-      if zstyle -a ":completion:${curcontext}:" file-patterns tmp; then
-        [[ "$argv" = *${${tmp[-1]#*[^\\]:}%:*}* ]] && _next_tags_reset=yes
-      else
-        [[ "$argv" = *all-files* ]] && _next_tags_reset=yes
-      fi
-    fi
-    tmp=( "${(@)argv:#(${(j:|:)~${=_next_tags_not}})(|:*)}" )
-
-    # $prev is set in _tags!
-
-    if [[ -n "$prev" && ( $#tmp -ne 0 || $funcstack[4] = _files ) ]]; then
-      comptry "$tmp[@]"
-    else
-      comptry "$argv[@]"
-    fi
   fi
 }
 
diff --git a/Completion/Core/_all_labels b/Completion/Core/_all_labels
index fa7118ec4..a03112ee4 100644
--- a/Completion/Core/_all_labels
+++ b/Completion/Core/_all_labels
@@ -1,11 +1,7 @@
 #autoload
 
-local gopt=-J len tmp pre suf tloop ret=1 descr
+local gopt=-J len tmp pre suf ret=1 descr spec
 
-if [[ "$1" = -t ]]; then
-  tloop=yes
-  shift
-fi
 if [[ "$1" = -([12]|)[VJ] ]]; then
   gopt="$1"
   shift
@@ -24,21 +20,19 @@ else
   suf=5
 fi
 
-while [[ -z "$tloop" ]] || comptags -N; do
-  while comptags -A "$1" curtag; do
-    if [[ "$curtag" = *:* ]]; then
-      zformat -f descr "${curtag#*:}" "d:$3"
-      _description "$gopt" "${curtag%:*}" "$2" "$descr"
-      curtag="${curtag%:*}"
+while comptags -A "$1" curtag spec; do
+  _comp_tags="$_comp_tags $spec "
+  if [[ "$curtag" = *:* ]]; then
+    zformat -f descr "${curtag#*:}" "d:$3"
+    _description "$gopt" "${curtag%:*}" "$2" "$descr"
+    curtag="${curtag%:*}"
 
-      "$4" "${(P@)2}" "${(@)argv[5,-1]}"
-    else
-      _description "$gopt" "$curtag" "$2" "$3"
+    "$4" "${(P@)2}" "${(@)argv[5,-1]}"
+  else
+    _description "$gopt" "$curtag" "$2" "$3"
 
-      "${(@)argv[4,pre]}" "${(P@)2}" "${(@)argv[suf,-1]}" && ret=0
-    fi
-  done
-  [[ -z "$tloop" || ret -eq 0 ]] && break
+    "${(@)argv[4,pre]}" "${(P@)2}" "${(@)argv[suf,-1]}" && ret=0
+  fi
 done
 
 return ret
diff --git a/Completion/Core/_files b/Completion/Core/_files
index 8a9bbfc95..a64e5c093 100644
--- a/Completion/Core/_files
+++ b/Completion/Core/_files
@@ -6,7 +6,7 @@ zparseopts -a opts \
     '/=tmp' 'f=tmp' 'g+:-=tmp' q n 1 2 P: S: r: R: W: X+: M+: F: J+: V+:
 
 type="${(@j::M)${(@)tmp#-}#?}"
-(( $tmp[(I)-g*] )) && glob="${(j: :)${(@M)tmp:#-g*}#-g}"
+(( $tmp[(I)-g*] )) && glob="${(j:,:)${(@M)tmp:#-g*}#-g}"
 ign=$opts[(I)-F]
 if (( ign )); then
   ign=( $=opts[ign+1] )
@@ -20,56 +20,59 @@ else
 fi
 
 if zstyle -a ":completion:${curcontext}:" file-patterns tmp; then
-  [[ "$type" = */* ]] && glob="$glob *(-/)"
+  [[ "$type" = */* ]] && glob="$glob,*(-/)"
   pats=()
   for i in ${tmp//\\%p/ ${${glob:-\*}//:/\\:} }; do
     if [[ $i = *[^\\]:* ]]; then
-      pats=( "$pats[@]" " $i" )
+      pats=( "$pats[@]" " $i " )
     else
-      pats=( "$pats[@]" " ${i}:files" )
+      pats=( "$pats[@]" " ${i}:files " )
     fi
   done
 else
   if [[ "$type" = *g* ]]; then
     if [[ "$type" = */* ]]; then
-      pats=( " ${glob//:/\\:} *(-/):globbed-files" '*:all-files' )
+      pats=( " ${glob//:/\\:}:globbed-files *(-/):directories" '*:all-files ' )
     else
-      pats=( " ${glob//:/\\:}:globbed-files"
-             '*(-/):directories' '*:all-files' )
+      pats=( " ${glob//:/\\:}:globbed-files "
+             '*(-/):directories ' '*:all-files ' )
     fi
   elif [[ "$type" = */* ]]; then
-    pats=( '*(-/):directories' '*:all-files' )
+    pats=( '*(-/):directories ' '*:all-files ' )
   else
-    pats=( '*:all-files' )
+    pats=( '*:all-files ' )
   fi
 fi
 
-for def in "$pats[@]"; do ###"${(@)${(@)pats#*[^\\]:}%%:*}"; do
+for def in "$pats[@]"; do
+  def="${def##[[:blank:]]#}"
+  while [[ "$def" = *[^\\][[:blank:]]* ]]; do
+    sdef="${(M)def#*[^\\][[:blank:]]}"
+    tag="${${sdef#*[^\\]:}%%:*}"
+    pat="${${${sdef%%:${tag}*}//\\\\:/:}//,/ }"
 
-  tag="${${def#*[^\\]:}%%:*}"
-  pat="${${def%%:${tag}*}//\\\\:/:}"
-
-  if [[ "$pat" != \ # ]]; then
-    if [[ "$def" = *:${tag}:* ]]; then
-      descr="${def#*:${tag}:}"
+    if [[ "$sdef" = *:${tag}:* ]]; then
+      descr="${(Q)sdef#*:${tag}:}"
     else
       descr=file
       end=yes
     fi
-  fi
 
-  if _wanted "$tag"; then
-    _comp_ignore=()
-    while _next_label "$tag" expl "$descr"; do
-      _comp_ignore=( $_comp_ignore $ign )
-      if [[ -n "$end" ]]; then
-        _path_files -g "$pat" "$opts[@]" "$expl[@]" && ret=0
-      else
-        _path_files "$expl[@]" -g "$pat" "$opts[@]" && ret=0
-      fi
+    _tags "$tag"
+    while _tags; do
+      _comp_ignore=()
+      while _next_label "$tag" expl "$descr"; do
+        _comp_ignore=( $_comp_ignore $ign )
+        if [[ -n "$end" ]]; then
+          _path_files -g "$pat" "$opts[@]" "$expl[@]" && ret=0
+        else
+          _path_files "$expl[@]" -g "$pat" "$opts[@]" && ret=0
+        fi
+      done
     done
-    (( ret )) || return 0
-  fi
+    def="${${def#${sdef}}##[[:blank:]]#}"
+  done
+  (( ret )) || return 0
 done
 
 return 1
diff --git a/Completion/Core/_next_label b/Completion/Core/_next_label
index e309e53ea..d2d698171 100644
--- a/Completion/Core/_next_label
+++ b/Completion/Core/_next_label
@@ -1,13 +1,14 @@
 #autoload
 
-local gopt=-J descr
+local gopt=-J descr spec
 
 if [[ "$1" = -([12]|)[VJ] ]]; then
   gopt="$1"
   shift
 fi
 
-if comptags -A "$1" curtag; then
+if comptags -A "$1" curtag spec; then
+  _comp_tags="$_comp_tags $spec "
   if [[ "$curtag" = *:* ]]; then
     zformat -f descr "${curtag#*:}" "d:$3"
     _description "$gopt" "${curtag%:*}" "$2" "$descr"
diff --git a/Completion/Core/_requested b/Completion/Core/_requested
index bd838a28e..90fdec279 100644
--- a/Completion/Core/_requested
+++ b/Completion/Core/_requested
@@ -8,7 +8,6 @@ if [[ "$1" = -([12]|)[VJ] ]]; then
 fi
 
 if comptags -R "$1"; then
-  _comp_tags="$_comp_tags $1"
   if [[ $# -gt 3 ]]; then
     _all_labels "$gopt" "$@"
   elif [[ $# -gt 1 ]]; then
diff --git a/Completion/Core/_wanted b/Completion/Core/_wanted
index 32875ec57..958f9e18e 100644
--- a/Completion/Core/_wanted
+++ b/Completion/Core/_wanted
@@ -17,17 +17,10 @@ if [[ "$1" = -([12]|)[VJ] ]]; then
   shift
 fi
 
-if [[ $# -gt 3 ]]; then
-  if _tags "$targs[@]" "$1"; then
-    _comp_tags="$_comp_tags $1"
+_tags "$targs[@]" "$1"
 
-    _all_labels -t "$gopt" "$@"
-  else
-    return 1
-  fi
-elif [[ $# -gt 1 ]]; then
-  _tags -- "$targs[@]" "$1" && _comp_tags="$_comp_tags $1" &&
-    _description "$gopt" "$@"
-else
-  _tags -- "$targs[@]" "$1" && _comp_tags="$_comp_tags $1"
-fi
+while _tags; do
+  _all_labels "$gopt" "$@" && return 0
+done
+
+return 1
diff --git a/Completion/Debian/_apt b/Completion/Debian/_apt
index 169b5f5f7..66129c949 100644
--- a/Completion/Debian/_apt
+++ b/Completion/Debian/_apt
@@ -75,7 +75,7 @@ _apt_arguments () {
   nul=$'\0'
   qnul="\$'\\0'"
 
-  comp_bool='_wanted values && compadd "$expl_bool[@]" '"$bool"
+  comp_bool='_wanted values expl_bool "boolean value" compadd "$expl_bool[@]" '"$bool"
   comp_intlevel= #"_message 'intlevel'"
   comp_configfile='_files "$expl_configfile[@]"'
   comp_arbitem= #"_message 'Foo::Bar=bar'"
diff --git a/Completion/Debian/_deb_packages b/Completion/Debian/_deb_packages
index b5e4ffd85..7973d9868 100644
--- a/Completion/Debian/_deb_packages
+++ b/Completion/Debian/_deb_packages
@@ -1,7 +1,57 @@
 #autoload
 
-if (( ! $+_deb_packages )); then
-  _deb_packages=( $(awk '/^Package:/ { print $2 }' /var/lib/dpkg/status) )
-fi
+# Usage: _deb_packages expl... avail|installed|uninstalled
 
-compadd "$@" - $_deb_packages
+_deb_packages_update_avail () {
+  if (( ! $+_deb_packages_cache_avail )); then
+    _deb_packages_cache_avail=(
+      ${(f)"$(apt-cache dumpavail | awk '/^Package:/ { print $2 }')"}
+    )
+  fi
+  cachevar=_deb_packages_cache_avail
+}
+
+_deb_packages_update_installed () {
+  if (( ! $+_deb_packages_cache_installed )); then
+    _deb_packages_cache_installed=(
+      ${${${(f)"$(dpkg --get-selections)"}:#*deinstall}%%	*}
+    )
+  fi
+  cachevar=_deb_packages_cache_installed
+}
+
+_deb_packages_update_uninstalled () {
+  _deb_packages_update_avail
+  _deb_packages_update_installed
+  if (( ! $+_deb_packages_cache_uninstalled )); then
+    _deb_packages_cache_uninstalled=(
+      ${_deb_packages_cache_avail:#${(j:|:)~${_deb_packages_cache_installed:q}}}
+    )
+  fi
+  cachevar=_deb_packages_cache_uninstalled
+}
+
+_deb_packages () {
+  local command="$argv[$#]" expl cachevar pkgset
+
+  [[ "$command" = (installed|uninstalled|avail) ]] || {
+    _message "_deb_packages:unknown command: $command"
+    return
+  }
+
+  zstyle -s ":completion:${curcontext}:" packageset pkgset
+
+  [[ "$pkgset" = (installed|uninstalled|avail|available) ]] || {
+    pkgset="$command"
+  }
+
+  [[ "$pkgset" = "available" ]] && pkgset="avail"
+
+  expl=("${(@)argv[1,-2]}")
+
+  _deb_packages_update_$pkgset
+
+  _tags packages && compadd "$expl[@]" - "${(@P)cachevar}"
+}
+
+_deb_packages "$@"
diff --git a/Completion/User/_cvs b/Completion/User/_cvs
index 356c7a80a..ce928fe50 100644
--- a/Completion/User/_cvs
+++ b/Completion/User/_cvs
@@ -19,662 +19,640 @@ _cvs () {
 
 # define cvs command dispatch function.
 
-if ! builtin functions _cvs_command >&-; then
-  _cvs_command () {
-    typeset -A cmds
-    cmds=(add " ad new "          admin " adm rcs "       annotate " ann "
-	  checkout " co get "     commit " ci com "       diff " di dif "
-	  edit ""                 editors ""              export " exp ex "
-	  history " hi his "      import " im imp "       init ""
-	  log " lo rlog "         login " logon lgn "     logout ""
-	  rdiff " patch pa "      release " re rel "      remove " rm delete "
-	  status " st stat "      rtag " rt rfreeze "     tag " ta freeze "
-	  unedit ""               update " up upd "       watch ""
-	  watchers "")
-
-    if (( CURRENT == 1 )); then
-      compadd "$@" ${(k)cmds} || compadd "$@" ${(kv)=cmds}
+(( $+functions[_cvs_command] )) ||
+_cvs_command () {
+  local cmd
+  typeset -A cmds
+  cmds=(add " ad new "          admin " adm rcs "       annotate " ann "
+	checkout " co get "     commit " ci com "       diff " di dif "
+	edit ""                 editors ""              export " exp ex "
+	history " hi his "      import " im imp "       init ""
+	log " lo rlog "         login " logon lgn "     logout ""
+	rdiff " patch pa "      release " re rel "      remove " rm delete "
+	status " st stat "      rtag " rt rfreeze "     tag " ta freeze "
+	unedit ""               update " up upd "       watch ""
+	watchers "")
+
+  if (( CURRENT == 1 )); then
+    _tags commands && { compadd "$@" ${(k)cmds} || compadd "$@" ${(kv)=cmds} }
+  else
+    local curcontext="$curcontext"
+
+    cmd="${${(k)cmds[(R)* $words[1] *]}:-${(k)cmds[(i)$words[1]]}}"
+    if (( $#cmd )); then
+      curcontext="${curcontext%:*:*}:cvs-${cmd}:"
+      _cvs_$cmd
     else
-      case "${${(k)cmds[(R)* $words[1] *]}:-$words[1]}" in
-	add) _cvs_add;;
-	admin) _cvs_admin;;
-	annotate) _cvs_annotate;;
-	checkout) _cvs_checkout;;
-	commit) _cvs_commit;;
-	diff) _cvs_diff;;
-	edit) _cvs_edit;;
-	editors) _cvs_editors;;
-	export) _cvs_export;;
-	history) _cvs_history;;
-	import) _cvs_import;;
-	init) _cvs_init;;
-	log) _cvs_log;;
-	login) _cvs_login;;
-	logout) _cvs_logout;;
-	rdiff) _cvs_rdiff;;
-	release) _cvs_release;;
-	remove) _cvs_remove;;
-	status) _cvs_status;;
-	rtag) _cvs_rtag;;
-	tag) _cvs_tag;;
-	unedit) _cvs_unedit;;
-	update) _cvs_update;;
-	watch) _cvs_watch;;
-	watchers) _cvs_watchers;;
-	*) _message "unknown cvs command: $words[1]";;
-      esac
+      _message "unknown cvs command: $words[1]"
     fi
-  }
-fi
+  fi
+}
 
 # define completion functions for each cvs command
 
-if ! builtin functions _cvs_add >&-; then
-  _cvs_add () {
-    # "+k:m:"
-    _arguments -s \
-      '-k+:keyword substitution:_cvs_k' \
-      '-m+:message:_cvs_m' \
-      '*:file:_cvs_files_unmaintained' \
-  }
-fi
-
-if ! builtin functions _cvs_admin >&-; then
-  _cvs_admin () {
-    # "+ib::c:a:A:e:l::u::LUn:N:m:o:s:t::IqxV:k:"
-    _arguments -s \
-      -{i,L,U,I,q,x} \
-      '-b-:default branch:(1.1.1)' \
-      '-c+:comment leader (not used):' \
-      '-a+:login names (not work with CVS):' \
-      '-A+:access list to append (not work with CVS):' \
-      '-e+:access list to erase (not work with CVS):' \
-      '-l-:revision to lock:' \
-      '-u-:revision to unlock:' \
-      '-n+:symbolic-name[\:revision]:' \
-      '-N+:symbolic-name[\:revision]:' \
-      '-m+:revision\:msg:' \
-      '-o+:range to delete:' \
-      '-s+:state[\:revision]:' \
-      '-t-:descriptive text:_cvs_admin_t' \
-      '-V+:version (obsolete):' \
-      '-k+:keyword substitution:_cvs_k' \
-      '*:file:_cvs_files'
-  }
-fi
+(( $+functions[_cvs_add] )) ||
+_cvs_add () {
+  # "+k:m:"
+  _arguments -s \
+    '-k+:keyword substitution:_cvs_k' \
+    '-m+:message:_cvs_m' \
+    '*:file:_cvs_files_unmaintained' \
+}
 
-if ! builtin functions _cvs_admin_t >&-; then
-  _cvs_admin_t () {
-    if compset -P -; then
-      _message 'descriptive text'
-    else
-      _files "$@"
-    fi
-  }
-fi
-
-if ! builtin functions _cvs_annotate >&-; then
-  _cvs_annotate () {
-    # "+lr:D:fR"
-    _arguments -s \
-      -{l,f,R} \
-      '-r+:tag:_cvs_revisions' \
-      '-D+:date:_cvs_D' \
-      '*:file:_cvs_files'
-  }
-fi
-
-if ! builtin functions _cvs_checkout >&-; then
-  _cvs_checkout () {
-    # "+ANnk:d:flRpQqcsr:D:j:P"
-    _arguments -s \
-      -{A,N,n,f,l,R,q,c,s,P} \
-      '-k+:keyword substitution:_cvs_k' \
-      '-d+:directory:_files -/' \
-      '-r+:tag:_cvs_revisions' \
-      '-D+:date:_cvs_D' \
-      '-j+:tag:_cvs_revisions' \
-      '*:module:_cvs_modules'
-  }
-fi
-
-if ! builtin functions _cvs_commit >&-; then
-  _cvs_commit () {
-    # "+nlRm:fF:r:"
-    _arguments -s \
-      -{n,l,R,f} \
-      '-m+:message:_cvs_m' \
-      '-F+:log message file:_files' \
-      '-r+:tag:_cvs_revisions' \
-      '*:file:_cvs_files_modified'
-  }
-fi
+(( $+functions[_cvs_admin] )) ||
+_cvs_admin () {
+  # "+ib::c:a:A:e:l::u::LUn:N:m:o:s:t::IqxV:k:"
+  _arguments -s \
+    -{i,L,U,I,q,x} \
+    '-b-:default branch:(1.1.1)' \
+    '-c+:comment leader (not used):' \
+    '-a+:login names (not work with CVS):' \
+    '-A+:access list to append (not work with CVS):' \
+    '-e+:access list to erase (not work with CVS):' \
+    '-l-:revision to lock:' \
+    '-u-:revision to unlock:' \
+    '-n+:symbolic-name(\:revision):' \
+    '-N+:symbolic-name(\:revision):' \
+    '-m+:revision\:msg:' \
+    '-o+:range to delete:' \
+    '-s+:state(\:revision):' \
+    '-t-:descriptive text:_cvs_admin_t' \
+    '-V+:version (obsolete):' \
+    '-k+:keyword substitution:_cvs_k' \
+    '*:file:_cvs_files'
+}
 
-if ! builtin functions _cvs_diff >&-; then
-  _cvs_diff () {
-    # "+abcdefhilnpstuw0123456789BHNRC:D:F:I:L:U:V:W:k:r:"
-    _arguments -s \
-      -{l,R} \
-      '-D+:date:_cvs_D' \
-      '-k+:keyword substitution:_cvs_k' \
-      '-r+:tag:_cvs_revisions' \
-      -{h,p,0,1,2,3,4,5,6,7,8,9} \
-      '--binary' \
-      '--brief' \
-      '--changed-group-format=:format:' \
-      '-c' '-C+:lines:' '--context=-:lines:' \
-      '-e' '--ed' \
-      '-t' '--expand-tabs' \
-      '-f' '--forward-ed' \
-      '--horizon-lines=:lines:' \
-      '--ifdef=:name:' \
-      '-w' '--ignore-all-space' \
-      '-B' '--ignore-blank-lines' \
-      '-i' '--ignore-case' \
-      '-I+:regex:' '--ignore-matching-lines=:regex:' \
-      '-b' '--ignore-space-change' \
-      '--initial-tab' \
-      '*-L+:label:' '*--label=:label:' \
-      '--left-column' \
-      '--line-format=:format:' \
-      '-d' '--minimal' \
-      '-N' '--new-file' \
-      '--new-group-format=:format:' \
-      '--new-line-format=:format:' \
-      '--old-group-format=:format:' \
-      '--old-line-format=:format:' \
-      '--paginate' \
-      '-n' '--rcs' \
-      '-s' '--report-identical-files' \
-      '--show-c-function' \
-      '-F+:regex:' '--show-function-line=:regex:' \
-      '-y' '--side-by-side' \
-      '-H' '--speed-large-files' \
-      '--suppress-common-lines' \
-      '-a' '--text' \
-      '--unchanged-group-format=:format:' \
-      '--unchanged-line-format=:format:' \
-      '-u' '-U+:lines:' '--unified=-:lines:' \
-      '-W:columns:' '--width=:columns:' \
-      '*:file:_cvs_diff_arg'
-  }
-fi
+(( $+functions[_cvs_admin_t] )) ||
+_cvs_admin_t () {
+  if compset -P -; then
+    _message 'descriptive text'
+  else
+    _files "$@"
+  fi
+}
 
-if ! builtin functions _cvs_diff_arg >&-; then
-  _cvs_diff_arg () {
-    _cvs_files_modified || _cvs_files
-  }
-fi
+(( $+functions[_cvs_annotate] )) ||
+_cvs_annotate () {
+  # "+lr:D:fR"
+  _arguments -s \
+    -{l,f,R} \
+    '-r+:tag:_cvs_revisions' \
+    '-D+:date:_cvs_D' \
+    '*:file:_cvs_files'
+}
 
-if ! builtin functions _cvs_edit >&-; then
-  _cvs_edit () {
-    # "+lRa:"
-    _arguments -s \
-      -{l,R} \
-      '-a+:action:(edit unedit commit all none)'
-      '*:file:_cvs_files'
-  }
-fi
+(( $+functions[_cvs_checkout] )) ||
+_cvs_checkout () {
+  # "+ANnk:d:flRpQqcsr:D:j:P"
+  _arguments -s \
+    -{A,N,n,f,l,R,q,c,s,P} \
+    '-k+:keyword substitution:_cvs_k' \
+    '-d+:directory:_files -/' \
+    '-r+:tag:_cvs_revisions' \
+    '-D+:date:_cvs_D' \
+    '-j+:tag:_cvs_revisions' \
+    '*:module:_cvs_modules'
+}
 
-if ! builtin functions _cvs_editors >&-; then
-  _cvs_editors () {
-    # "+lR"
-    _arguments -s \
-      -{l,R} \
-      '*:file:_cvs_files'
-  }
-fi
-
-if ! builtin functions _cvs_export >&-; then
-  _cvs_export () {
-    # "+Nnk:d:flRQqr:D:"
-    _arguments -s \
-      -{N,n,f,l,R,Q,q} \
-      '-k+:keyword substitution:_cvs_k' \
-      '-d+:directory:_files -/' \
-      '-r+:tag:_cvs_revisions' \
-      '-D+:date:_cvs_D' \
-      '*:module:_cvs_modules'
-  }
-fi
-
-if ! builtin functions _cvs_history >&-; then
-  _cvs_history () {
-    # "+Tacelow?D:b:f:m:n:p:r:t:u:x:X:z:"
-    _arguments -s \
-      -{T,a,c,e,l,o,w,\?} \
-      '-D+:date:_cvs_D' \
-      '-b+:string:' \
-      '-f+:arg:' \
-      '-m+:module:_cvs_modules' \
-      '-n+:arg:' \
-      '*-p+:repository:' \
-      '-r+:rev:' \
-      '-t+:tag:' \
-      '-u+:user name:' \
-      '-x+:type:_cvs_history_x' \
-      '-X+:arg:' \
-      '-z+:arg:' \
-      '*:file:_cvs_files'
-  }
-fi
-
-if ! builtin functions _cvs_history_x >&-; then
-  _cvs_history_x () {
-    compset -P '*'
-
-    compadd "$@" -y '(
-    F\ --\ release
-    O\ --\ checkout
-    E\ --\ export
-    T\ --\ rtag
-    C\ --\ merge\ collision-detected
-    G\ --\ merge\ succeed
-    U\ --\ working\ file\ was\ copied
-    W\ --\ working\ file\ was\ deleted
-    A\ --\ A\ file\ was\ added
-    M\ --\ A\ file\ was\ modified
-    R\ --\ A\ file\ was\ removed
-    )' F O E T C G U W A M R
-  }
-fi
-
-if ! builtin functions _cvs_import >&-; then
-  _cvs_import () {
-    # "+Qqdb:m:I:k:W:"
-    _arguments -s \
-      -{Q,q,d} \
-      '-b+:branch:' \
-      '-m+:message:_cvs_m' \
-      '*-I+:name:_files' \
-      '-k+:keyword substitution:_cvs_k' \
-      '*-W+:spec:' \
-      ':repository:_cvs_modules' \
-      ':vendor tag:' \
-      ':release tag:'
-  }
-fi
+(( $+functions[_cvs_commit] )) ||
+_cvs_commit () {
+  # "+nlRm:fF:r:"
+  _arguments -s \
+    -{n,l,R,f} \
+    '-m+:message:_cvs_m' \
+    '-F+:log message file:_files' \
+    '-r+:tag:_cvs_revisions' \
+    '*:file:_cvs_files_modified'
+}
 
-if ! builtin functions _cvs_init >&-; then
-  _cvs_init () {
-    false
-  }
-fi
+(( $+functions[_cvs_diff] )) ||
+_cvs_diff () {
+  # "+abcdefhilnpstuw0123456789BHNRC:D:F:I:L:U:V:W:k:r:"
+  _arguments -s \
+    -{l,R} \
+    '-D+:date:_cvs_D' \
+    '-k+:keyword substitution:_cvs_k' \
+    '-r+:tag:_cvs_revisions' \
+    -{h,p,0,1,2,3,4,5,6,7,8,9} \
+    '--binary' \
+    '--brief' \
+    '--changed-group-format=:format:' \
+    '-c' '-C+:lines:' '--context=-:lines:' \
+    '-e' '--ed' \
+    '-t' '--expand-tabs' \
+    '-f' '--forward-ed' \
+    '--horizon-lines=:lines:' \
+    '--ifdef=:name:' \
+    '-w' '--ignore-all-space' \
+    '-B' '--ignore-blank-lines' \
+    '-i' '--ignore-case' \
+    '-I+:regex:' '--ignore-matching-lines=:regex:' \
+    '-b' '--ignore-space-change' \
+    '--initial-tab' \
+    '*-L+:label:' '*--label=:label:' \
+    '--left-column' \
+    '--line-format=:format:' \
+    '-d' '--minimal' \
+    '-N' '--new-file' \
+    '--new-group-format=:format:' \
+    '--new-line-format=:format:' \
+    '--old-group-format=:format:' \
+    '--old-line-format=:format:' \
+    '--paginate' \
+    '-n' '--rcs' \
+    '-s' '--report-identical-files' \
+    '--show-c-function' \
+    '-F+:regex:' '--show-function-line=:regex:' \
+    '-y' '--side-by-side' \
+    '-H' '--speed-large-files' \
+    '--suppress-common-lines' \
+    '-a' '--text' \
+    '--unchanged-group-format=:format:' \
+    '--unchanged-line-format=:format:' \
+    '-u' '-U+:lines:' '--unified=-:lines:' \
+    '-W:columns:' '--width=:columns:' \
+    '*:file:_cvs_diff_arg'
+}
 
-if ! builtin functions _cvs_login >&-; then
-  _cvs_login () {
-    false
-  }
-fi
+(( $+functions[_cvs_diff_arg] )) ||
+_cvs_diff_arg () {
+  _cvs_files_modified || _cvs_files
+}
 
-if ! builtin functions _cvs_logout >&-; then
-  _cvs_logout () {
-    false
-  }
-fi
-
-if ! builtin functions _cvs_rdiff >&-; then
-  _cvs_rdiff () {
-    # "+V:k:cuftsQqlRD:r:"
-    _arguments -s \
-      -{c,u,f,t,s,Q,q,l,R} \
-      '-V+:version:' \
-      '-k+:keyword substitution:_cvs_k' \
-      '*-D+:date:_cvs_D' \
-      '*-r+:tag:_cvs_revisions' \
-      '*:module:_cvs_modules'
-  }
-fi
-
-if ! builtin functions _cvs_release >&-; then
-  _cvs_release () {
-    # "+Qdq"
-    _arguments -s \
-      -{Q,d,q} \
-      '*:directory:_files -/'
-  }
-fi
-
-if ! builtin functions _cvs_remove >&-; then
-  _cvs_remove () {
-    # "+flR"
-    _arguments -s \
-      -{f,l,R} \
-      '*:file:_cvs_files_removed'
-  }
-fi
+(( $+functions[_cvs_edit] )) ||
+_cvs_edit () {
+  # "+lRa:"
+  _arguments -s \
+    -{l,R} \
+    '-a+:action:(edit unedit commit all none)' \
+    '*:file:_cvs_files'
+}
 
-if ! builtin functions _cvs_status >&-; then
-  _cvs_status () {
-    # "+vlR"
-    _arguments -s \
-      -{v,l,R} \
-      '*:file:_cvs_files'
-  }
-fi
-
-if ! builtin functions _cvs_tag >&-; then
-  _cvs_tag () {
-    # "+FQqlRcdr:D:bf"
-    _arguments -s \
-      -{F,Q,q,l,R,c,d,b,f} \
-      '-r+:tag:_cvs_revisions' \
-      '-D+:date:_cvs_D' \
-      '*:file:_cvs_files'
-  }
-fi
+(( $+functions[_cvs_editors] )) ||
+_cvs_editors () {
+  # "+lR"
+  _arguments -s \
+    -{l,R} \
+    '*:file:_cvs_files'
+}
+
+(( $+functions[_cvs_export] )) ||
+_cvs_export () {
+  # "+Nnk:d:flRQqr:D:"
+  _arguments -s \
+    -{N,n,f,l,R,Q,q} \
+    '-k+:keyword substitution:_cvs_k' \
+    '-d+:directory:_files -/' \
+    '-r+:tag:_cvs_revisions' \
+    '-D+:date:_cvs_D' \
+    '*:module:_cvs_modules'
+}
+
+(( $+functions[_cvs_history] )) ||
+_cvs_history () {
+  # "+Tacelow?D:b:f:m:n:p:r:t:u:x:X:z:"
+  _arguments -s \
+    -{T,a,c,e,l,o,w,\?} \
+    '-D+:date:_cvs_D' \
+    '-b+:string:' \
+    '-f+:file:_cvs_files' \
+    '-m+:module:_cvs_modules' \
+    '-n+:module:_cvs_modules' \
+    '*-p+:repository:' \
+    '-r+:rev:' \
+    '-t+:tag:' \
+    '-u+:user name:' \
+    '-x+:type:_cvs_history_x' \
+    '-X+:arg:' \
+    '-z+:timezone:' \
+    '*:file:_cvs_files'
+}
+
+(( $+functions[_cvs_history_x] )) ||
+_cvs_history_x () {
+  _values -s '' 'type' \
+    'F[release]' \
+    'O[checkout]' \
+    'E[export]' \
+    'T[rtag]' \
+    'C[merge collision-detected]' \
+    'G[merge succeed]' \
+    'U[working file was copied]' \
+    'W[working file was deleted]' \
+    'A[A file was added]' \
+    'M[A file was modified]' \
+    'R[A file was removed]'
+}
+
+(( $+functions[_cvs_import] )) ||
+_cvs_import () {
+  # "+Qqdb:m:I:k:W:"
+  _arguments -s \
+    -{Q,q,d} \
+    '-b+:branch:' \
+    '-m+:message:_cvs_m' \
+    '*-I+:name:_files' \
+    '-k+:keyword substitution:_cvs_k' \
+    '*-W+:spec:' \
+    ':repository:_cvs_modules' \
+    ':vendor tag:' \
+    ':release tag:'
+}
+
+(( $+functions[_cvs_init] )) ||
+_cvs_init () {
+  false
+}
+
+(( $+functions[_cvs_log] )) ||
+_cvs_log () {
+  # "+bd:hlNRr::s:tw::"
+  _arguments -s \
+    -{b,h,l,N,R,t} \
+    '-d+:dates:' \
+    '-r-:revisions:' \
+    '-s+:states:' \
+    '-w-:logins:' \
+    '*:file:_cvs_files'
+}
+
+(( $+functions[_cvs_login] )) ||
+_cvs_login () {
+  false
+}
+
+(( $+functions[_cvs_logout] )) ||
+_cvs_logout () {
+  false
+}
+
+(( $+functions[_cvs_rdiff] )) ||
+_cvs_rdiff () {
+  # "+V:k:cuftsQqlRD:r:"
+  _arguments -s \
+    -{c,u,f,t,s,Q,q,l,R} \
+    '-V+:version:' \
+    '-k+:keyword substitution:_cvs_k' \
+    '*-D+:date:_cvs_D' \
+    '*-r+:tag:_cvs_revisions' \
+    '*:module:_cvs_modules'
+}
+
+(( $+functions[_cvs_release] )) ||
+_cvs_release () {
+  # "+Qdq"
+  _arguments -s \
+    -{Q,d,q} \
+    '*:directory:_files -/'
+}
+
+(( $+functions[_cvs_remove] )) ||
+_cvs_remove () {
+  # "+flR"
+  _arguments -s \
+    -{f,l,R} \
+    '*:file:_cvs_files_removed'
+}
+
+(( $+functions[_cvs_rtag] )) ||
+_cvs_rtag () {
+  # "+FanfQqlRdbr:D:"
+  _arguments -s \
+    -{F,a,n,f,Q,q,l,R,d,b} \
+    '*-D+:date:_cvs_D' \
+    '*-r+:tag:_cvs_revisions' \
+    ':tag:' \
+    '*:module:_cvs_modules'
+}
+
+(( $+functions[_cvs_status] )) ||
+_cvs_status () {
+  # "+vlR"
+  _arguments -s \
+    -{v,l,R} \
+    '*:file:_cvs_files'
+}
+
+(( $+functions[_cvs_tag] )) ||
+_cvs_tag () {
+  # "+FQqlRcdr:D:bf"
+  _arguments -s \
+    -{F,Q,q,l,R,c,d,b,f} \
+    '-r+:tag:_cvs_revisions' \
+    '-D+:date:_cvs_D' \
+    ':tag:' \
+    '*:file:_cvs_files'
+}
+
+(( $+functions[_cvs_unedit] )) ||
+_cvs_unedit () {
+  # "+lR"
+  _arguments -s \
+    -{l,R} \
+    '*:file:_cvs_files'
+}
+
+(( $+functions[_cvs_update] )) ||
+_cvs_update () {
+  # "+ApCPflRQqduk:r:D:j:I:W:"
+  _arguments -s \
+    -{A,C,p,P,f,l,R,Q,q,d,u} \
+    '-k+:keyword substitution:_cvs_k' \
+    '-r+:tag:_cvs_revisions' \
+    '-D+:date:_cvs_D' \
+    '-j+:tag:_cvs_revisions' \
+    '*-I+:name:_files' \
+    '*-W+:spec:' \
+    '*:file:_cvs_files'
+}
+
+(( $+functions[_cvs_watch] )) ||
+_cvs_watch () {
+  local expl
+
+  if (( CURRENT == 2 )); then
+    _wanted values expl 'watch command' compadd on off add remove
+  else
+    case "$words[2]" in
+      on|off) # "+lR"
+	_arguments -s \
+	    -{l,R} \
+	    ':watch command:' \
+	    '*:file:_cvs_files'
+	;;
+      add|remove) # "+lRa:"
+	_arguments -s \
+	    -{l,R} \
+	    '*-a+:action:(edit unedit commit all none)' \
+	    ':watch command:' \
+	    '*:file:_cvs_files'
+	;;
+    esac
+  fi
+}
 
-if ! builtin functions _cvs_unedit >&-; then
-  _cvs_unedit () {
-    # "+lR"
-    _arguments -s \
+(( $+functions[_cvs_watchers] )) ||
+_cvs_watchers () {
+  # "+lR"
+  _arguments -s \
       -{l,R} \
       '*:file:_cvs_files'
-  }
-fi
-
-if ! builtin functions _cvs_update >&-; then
-  _cvs_update () {
-    # "+ApPflRQqduk:r:D:j:I:W:"
-    _arguments -s \
-      -{A,p,P,f,l,R,Q,q,d,u} \
-      '-k+:keyword substitution:_cvs_k' \
-      '-r+:tag:_cvs_revisions' \
-      '-D+:date:_cvs_D' \
-      '-j+:tag:_cvs_revisions' \
-      '*-I+:name:_files' \
-      '*-W+:spec:' \
-      '*:file:_cvs_files'
-  }
-fi
+}
 
-if ! builtin functions _cvs_watch >&-; then
-  _cvs_watch () {
-    if (( CURRENT == 2 )); then
-      compadd on off add remove
-    else
-      case "$words[2]" in
-	on|off) # "+lR"
-	  _arguments -s \
-	  -{l,R} \
-	  ':watch command:' \
-	  ':*:file:_cvs_files'
-	  ;;
-	add|remove) # "+lRa:"
-	  _arguments -s \
-	  -{l,R} \
-	  '*-a+:action:(edit unedit commit all none)' \
-	  ':watch command:' \
-	  ':*:file:_cvs_files'
-	  ;;
-      esac
-    fi
-  }
-fi
+(( $+functions[_cvs_loadstat] )) ||
+_cvs_loadstat () {
+  zstyle -t ":completion:${curcontext}:" disable-stat && return
+  (( $+_cvs_loadstat_tried )) && return
+  _cvs_loadstat_tried=yes
 
-if ! builtin functions _cvs_watchers >&-; then
-  _cvs_watchers () {
-    # "+lR"
-    _arguments -s \
-      -{l,R} \
-      ':*:file:_cvs_files'
-  }
-fi
+  zmodload -i zsh/stat 2>/dev/null
+}
 
-if ! builtin functions _cvs_root >&-; then
-  _cvs_root () {
-    compadd "$@" $_cvs_roots || _files "$@" -/
-  }
-fi
+(( $+functions[_cvs_root] )) ||
+_cvs_root () {
+  local cvspassfile id
 
-if ! builtin functions _cvs_tempdir >&-; then
-  _cvs_tempdir () {
-    compadd "$@" $TMPPREFIX:h $TMPDIR /tmp
-  }
-fi
+  typeset -gU _cvs_roots
 
-if ! builtin functions _cvs_user_variable >&-; then
-  _cvs_user_variable () {
-    if compset -P '*='; then
-      _default
+  if [[ -f "${cvspassfile::=${CVS_PASSFILE:-$HOME/.cvspass}}" ]]; then
+    _cvs_loadstat
+    if (( $+builtins[stat] )); then
+      id="$(LC_ALL=C builtin stat -g +mtime -F '%Y/%m/%d-%T' "$cvspassfile")"
     else
-      _message "variable=value"
+      id="$(LC_ALL=C ls -l "$cvspassfile")"
+    fi
+    if [[ "$id" != "$_cvs_pass_id" ]]; then
+      _cvs_roots=($_cvs_roots ${${(f)"$(<$cvspassfile)"}%% *})
+      _cvs_pass_id="$id"
     fi
+  fi
+
+  _tags files && {
+    compadd -M 'r:|[:@./]=* r:|=*' "$@" $_cvs_roots || _files "$@" -/
   }
-fi
+}
+
+(( $+functions[_cvs_tempdir] )) ||
+_cvs_tempdir () {
+  _tags directories && compadd "$@" $TMPPREFIX:h $TMPDIR /tmp
+}
+
+(( $+functions[_cvs_user_variable] )) ||
+_cvs_user_variable () {
+  if compset -P '*='; then
+    _default
+  else
+    _message "variable=value"
+  fi
+}
 
 # define completion functions for cvs global options.
 
-if ! builtin functions _cvs_bindir >&-; then
-  _cvs_bindir () {
-    compadd "$@" /usr/local/bin || _files "$@" -/
-  }
-fi
+(( $+functions[_cvs_bindir] )) ||
+_cvs_bindir () {
+  _tags directories && { compadd "$@" /usr/local/bin || _files "$@" -/ }
+}
 
-if ! builtin functions _cvs_editor >&-; then
-  _cvs_editor () {
-    compadd "$@" vi
-  }
-fi
+(( $+functions[_cvs_editor] )) ||
+_cvs_editor () {
+  _tags commands && compadd "$@" vi
+}
 
-if ! builtin functions _cvs_gzip_level >&-; then
-  _cvs_gzip_level () {
-    compadd "$@" 9
-  }
-fi
+(( $+functions[_cvs_gzip_level] )) ||
+_cvs_gzip_level () {
+  _tags values && compadd "$@" 9
+}
 
 # define completion functions for cvs common options and arguments.
 
-if ! builtin functions _cvs_D >&-; then
-  _cvs_D () {
-    compadd "$@" today yesterday week\ ago month\ ago
-  }
-fi
+(( $+functions[_cvs_D] )) ||
+_cvs_D () {
+  _tags values && compadd "$@" today yesterday week\ ago month\ ago
+}
 
-if ! builtin functions _cvs_k >&-; then
-  _cvs_k () {
-    compadd "$@" kv kvl k o b v
-  }
-fi
+(( $+functions[_cvs_k] )) ||
+_cvs_k () {
+  _tags values && compadd "$@" kv kvl k o b v
+}
 
-if ! builtin functions _cvs_m >&-; then
-  _cvs_m () {
-    _message "log message"
-  }
-fi
+(( $+functions[_cvs_m] )) ||
+_cvs_m () {
+  _message "log message"
+}
 
-if ! builtin functions _cvs_modules >&-; then
-  _cvs_modules () {
-    local root=$CVSROOT
-    [[ -f CVS/Root ]] && root=$(<CVS/Root)
+(( $+functions[_cvs_modules] )) ||
+_cvs_modules () {
+  local root=$CVSROOT expl
 
-    if [[ $root = :* || ! -d $root ]]; then
-      _message "module name"
-    else
-      compadd - \
-	$root/^CVSROOT(:t) \
-	${${(M)${(f)"$(<$root/CVSROOT/modules)"}:#[^#]*}%%[ 	]*}
-    fi
-  }
-fi
+  [[ -f CVS/Root ]] && root=$(<CVS/Root)
 
-if ! builtin functions _cvs_revisions >&-; then
-  _cvs_revisions () {
-    compadd - ${${${(M)${(f)"$(cvs -q status -vl .)"}:#	*}##[ 	]##}%%[ 	]*}
-  }
-fi
+  if [[ $root = :* || ! -d $root ]]; then
+    _message "module name"
+  else
+    _wanted modules expl module \
+        compadd - $root/^CVSROOT(:t) \
+            ${${(M)${(f)"$(<$root/CVSROOT/modules)"}:#[^#]*}%%[ 	]*}
+  fi
+}
+
+(( $+functions[_cvs_revisions] )) ||
+_cvs_revisions () {
+  local expl
+
+  _wanted values expl revision \
+      compadd - ${${${(M)${(f)"$(cvs -q status -vl .)"}:#	*}##[ 	]##(No Tags Exist)#}%%[ 	]*}
+}
 
 # define completion functions for files maintained by cvs.
 
-if ! builtin functions _cvs_setup_prefix >&-; then
-  _cvs_setup_prefix () {
-    if [[ -prefix */ ]]; then
-      qpref="${PREFIX%/*}/"
-      pref=$~qpref
-    else
-      qpref=
-      pref=./
-    fi
-  }
-fi
+(( $+functions[_cvs_setup_prefix] )) ||
+_cvs_setup_prefix () {
+  if [[ -prefix */ ]]; then
+    qpref="${PREFIX%/*}/"
+    pref=$~qpref
+  else
+    qpref=
+    pref=./
+  fi
+}
 
-if ! builtin functions _cvs_extract_directory_entries >&-; then
-  _cvs_extract_directory_entries () {
-    entries=($entries ${${${(M)rawentries:#D/*}#D/}%%/*})
-  }
-fi
+(( $+functions[_cvs_extract_directory_entries] )) ||
+_cvs_extract_directory_entries () {
+  entries=($entries ${${${(M)rawentries:#D/*}#D/}%%/*})
+}
 
-if ! builtin functions _cvs_extract_file_entries >&-; then
-  _cvs_extract_file_entries () {
-    entries=($entries ${${${(M)rawentries:#/*}#/}%%/*})
-  }
-fi
-
-if ! builtin functions _cvs_extract_modifiedfile_entries >&-; then
-  _cvs_extract_modifiedfile_entries () {
-    if [[ -n "$compconfig[_cvs_disable_stat]" ]] ||
-      ! { zmodload -e stat || zmodload stat }; then
-      _cvs_extract_file_entries
-      return
-    fi
+(( $+functions[_cvs_extract_file_entries] )) ||
+_cvs_extract_file_entries () {
+  entries=($entries ${${${(M)rawentries:#/*}#/}%%/*})
+}
 
-    local ents pats
-    ents=(${${${${(M)rawentries:#/*}#/}/\\/[^\\/]#\\///}%/[^/]#/[^/]#})
-    pats=(${${${(f)"$(LANG=C builtin stat -gn +mtime -F '%a %b %e %T %Y' ${pref}*(D))"}##*/}/ //})
-    eval 'ents=(${ents:#('${(j:|:)${(@)pats:q}}')})'
-    entries=($entries ${ents%%/*})
-  }
-fi
-
-if ! builtin functions _cvs_setup_allentries >&-; then
-  _cvs_setup_allentries () {
-    entries=()
-    if [[ -f ${pref}CVS/Entries ]]; then
-      local rawentries
-      rawentries=(${(f)"$(<${pref}CVS/Entries)"})
-      _cvs_extract_file_entries
-      _cvs_extract_directory_entries
-    fi
-  }
-fi
-
-if ! builtin functions _cvs_setup_direntries >&-; then
-  _cvs_setup_direntries () {
-    entries=()
-    if [[ -f ${pref}CVS/Entries ]]; then
-      local rawentries
-      rawentries=(${(f)"$(<${pref}CVS/Entries)"})
-      _cvs_extract_directory_entries
-    fi
-  }
-fi
-
-if ! builtin functions _cvs_setup_modentries >&-; then
-  _cvs_setup_modentries () {
-    entries=()
-    if [[ -f ${pref}CVS/Entries ]]; then
-      local rawentries
-      rawentries=(${(f)"$(<${pref}CVS/Entries)"})
-      _cvs_extract_modifiedfile_entries
-      _cvs_extract_directory_entries
-    fi
-  }
-fi
+(( $+functions[_cvs_extract_modifiedfile_entries] )) ||
+_cvs_extract_modifiedfile_entries () {
+  _cvs_loadstat
+  if (( ! $+builtins[stat] )); then
+    _cvs_extract_file_entries
+    return
+  fi
 
-if ! builtin functions _cvs_directories >&-; then
-  _cvs_directories () {
-    if [[ -d ${pref}CVS ]]; then
-      _cvs_setup_direntries
-      (( $#entries )) && compgen "$@" -g "${(j:|:)${(@)entries:q}}"
-    else
-      _files "$@"
-    fi
-  }
-fi
-
-if ! builtin functions _cvs_files >&-; then
-  _cvs_files () {
-    local qpref pref entries
-    _cvs_setup_prefix
-    if [[ -d ${pref}CVS ]]; then
-      _cvs_setup_allentries
-      (( $#entries )) && compgen "$@" -g "${(j:|:)${(@)entries:q}}"
-    else
-      _files "$@"
-    fi
-  }
-fi
-
-if ! builtin functions _cvs_files_modified >&-; then
-  _cvs_files_modified () {
-    local qpref pref entries
-    _cvs_setup_prefix
-    if [[ -d ${pref}CVS ]]; then
-      _cvs_setup_modentries
-      (( $#entries )) && compgen "$@" -g "${(j:|:)${(@)entries:q}}"
-    else
-      _files "$@"
-    fi
-  }
-fi
-
-if ! builtin functions _cvs_files_removed >&-; then
-  _cvs_files_removed () {
-    local qpref pref entries
-    _cvs_setup_prefix
-    if [[ -d ${pref}CVS ]]; then
-      _cvs_setup_allentries
-      setopt localoptions unset
-      local omit
-      omit=(${pref}*(D:t))
-      eval 'entries=(${entries:#('${(j:|:)${(@)omit:q}}')})'
-      compadd "$@" -P "$qpref" - ${entries:q} ||
-      _cvs_directories "$@"
-    else
-      _files "$@"
-    fi
-  }
-fi
-
-if ! builtin functions _cvs_files_unmaintained >&-; then
-  _cvs_files_unmaintained () {
-    local qpref pref entries
-    _cvs_setup_prefix
-    if [[ -d ${pref}CVS ]]; then
-      _cvs_setup_allentries
-      setopt localoptions unset
-      local omit
-      omit=($_cvs_ignore_default ${entries:q} ${=cvsignore})
-      [[ -r ~/.cvsignore ]] && omit=($omit $(<~/.cvsignore))
-      [[ -r ${pref}.cvsignore ]] && omit=($omit $(<${pref}.cvsignore))
-      compgen "$@" -g '*~(*/|)('${(j:|:)omit}')(D)' ||
-      compgen "$@" -g '*~(*/|)('${(j:|:)${(@)entries:q}}')(D)' ||
-      _cvs_directories "$@"
-    else
-      _files "$@"
-    fi
-  }
-fi
+  local ents pats
+  ents=(${${${${(M)rawentries:#/*}#/}/\\/[^\\/]#\\///}%/[^/]#/[^/]#})
+  pats=(${${${(f)"$(LC_ALL=C builtin stat -gn +mtime -F '%a %b %e %T %Y' ${pref}*(D))"}##*/}/ //})
+  eval 'ents=(${ents:#('${(j:|:)${(@)pats:q}}')})'
+  entries=($entries ${ents%%/*})
+}
 
-# define configuration variables.
+(( $+functions[_cvs_setup_allentries] )) ||
+_cvs_setup_allentries () {
+  entries=()
+  if [[ -f ${pref}CVS/Entries ]]; then
+    local rawentries
+    rawentries=(${(f)"$(<${pref}CVS/Entries)"})
+    _cvs_extract_file_entries
+    _cvs_extract_directory_entries
+  fi
+}
+
+(( $+functions[_cvs_setup_direntries] )) ||
+_cvs_setup_direntries () {
+  entries=()
+  if [[ -f ${pref}CVS/Entries ]]; then
+    local rawentries
+    rawentries=(${(f)"$(<${pref}CVS/Entries)"})
+    _cvs_extract_directory_entries
+  fi
+}
+
+(( $+functions[_cvs_setup_modentries] )) ||
+_cvs_setup_modentries () {
+  entries=()
+  if [[ -f ${pref}CVS/Entries ]]; then
+    local rawentries
+    rawentries=(${(f)"$(<${pref}CVS/Entries)"})
+    _cvs_extract_modifiedfile_entries
+    _cvs_extract_directory_entries
+  fi
+}
 
-if (( ! $+_cvs_roots )); then
-  if [[ -f ~/.cvspass ]]; then
-    _cvs_roots=(${${(f)"$(<~/.cvspass)"}%% *})
+(( $+functions[_cvs_directories] )) ||
+_cvs_directories () {
+  if [[ -d ${pref}CVS ]]; then
+    _cvs_setup_direntries
+    (( $#entries )) && _files "$@" -g "${(j:|:)${(@)entries:q}}"
   else
-    _cvs_roots=()
+    _files "$@"
   fi
-fi
+}
+
+(( $+functions[_cvs_files] )) ||
+_cvs_files () {
+  local qpref pref entries
+  _cvs_setup_prefix
+  if [[ -d ${pref}CVS ]]; then
+    _cvs_setup_allentries
+    (( $#entries )) && _files "$@" -g "${(j:|:)${(@)entries:q}}"
+  else
+    _files "$@"
+  fi
+}
+
+(( $+functions[_cvs_files_modified] )) ||
+_cvs_files_modified () {
+  local qpref pref entries
+  _cvs_setup_prefix
+  if [[ -d ${pref}CVS ]]; then
+    _cvs_setup_modentries
+    (( $#entries )) && _files "$@" -g "${(j:|:)${(@)entries:q}}"
+  else
+    _files "$@"
+  fi
+}
+
+(( $+functions[_cvs_files_removed] )) ||
+_cvs_files_removed () {
+  local qpref pref entries
+  _cvs_setup_prefix
+  if [[ -d ${pref}CVS ]]; then
+    _cvs_setup_allentries
+    setopt localoptions unset
+    local omit
+    omit=(${pref}*(D:t))
+    eval 'entries=(${entries:#('${(j:|:)${(@)omit:q}}')})'
+    _tags directories && compadd "$@" -P "$qpref" - ${entries:q} ||
+        _cvs_directories "$@"
+  else
+    _files "$@"
+  fi
+}
+
+(( $+functions[_cvs_files_unmaintained] )) ||
+_cvs_files_unmaintained () {
+  local qpref pref entries
+  _cvs_setup_prefix
+  if [[ -d ${pref}CVS ]]; then
+    _cvs_setup_allentries
+    setopt localoptions unset
+    local omit
+    omit=($_cvs_ignore_default ${entries:q} ${=cvsignore})
+    [[ -r ~/.cvsignore ]] && omit=($omit $(<~/.cvsignore))
+    [[ -r ${pref}.cvsignore ]] && omit=($omit $(<${pref}.cvsignore))
+    _path_files "$@" -g '*~(*/|)('${(j:|:)omit}')(D)' ||
+        _path_files "$@" -g '*~(*/|)('${(j:|:)${(@)entries:q}}')(D)' ||
+        _cvs_directories "$@"
+  else
+    _files "$@"
+  fi
+}
+
+# define configuration variables.
 
-if (( ! $+_cvs_ignore_default )); then
-  _cvs_ignore_default=(
-    RCS SCCS CVS CVS.adm RCSLOG 'cvslog.*' tags TAGS .make.state .nse_depinfo
-    '*\~' '\#*' '.\#*' ',*' '_$*' '*$' '*.old' '*.bak' '*.BAK' '*.orig' '*.rej'
-    '.del-*' '*.a' '*.olb' '*.o' '*.obj' '*.so' '*.exe' '*.Z' '*.elc' '*.ln'
-    core
-  )
-fi
+(( $+_cvs_ignore_default )) ||
+_cvs_ignore_default=(
+  RCS SCCS CVS CVS.adm RCSLOG 'cvslog.*' tags TAGS .make.state .nse_depinfo
+  '*\~' '\#*' '.\#*' ',*' '_$*' '*$' '*.old' '*.bak' '*.BAK' '*.orig' '*.rej'
+  '.del-*' '*.a' '*.olb' '*.o' '*.obj' '*.so' '*.exe' '*.Z' '*.elc' '*.ln'
+  core
+)
 
 # call real _cvs.
 
-_cvs "$@"
+[[ -o kshautoload ]] || _cvs "$@"
diff --git a/Completion/User/_gdb b/Completion/User/_gdb
index a29eaf8b2..0445e18e9 100644
--- a/Completion/User/_gdb
+++ b/Completion/User/_gdb
@@ -17,7 +17,8 @@ elif compset -P '-(exec|se)='; then
 elif compset -P '-(symbols|core|command)='; then
   _files
 elif [[ "$PREFIX" = -* ]]; then
-  if _wanted options; then
+  _tags options
+  while _tags; do
     while _next_label options expl option; do
       compadd "$expl[@]" -QS '' - -symbols\= -exec\= -se\= -core\= -command\= \
                                   -directory\= -cd\= -tty\= && ret=0
@@ -25,7 +26,7 @@ elif [[ "$PREFIX" = -* ]]; then
 	    		          -batch -fullname -f -b && ret=0
     done
     (( ret )) || return 0
-  fi
+  done
 else
   prev="$words[CURRENT-1]"
 
diff --git a/Completion/User/_gprof b/Completion/User/_gprof
index 0a1d621be..659e921e8 100644
--- a/Completion/User/_gprof
+++ b/Completion/User/_gprof
@@ -1,12 +1,58 @@
 #compdef gprof
 
-_arguments -s -{a,b,c,D,h,i,l,L,s,T,v,w,x,y,z} \
-           -{A,C,e,E,f,F,J,n,N,O,p,P,q,Q,Z}:'function name: _exec_funcs' \
+local curcontext="$curcontext" state line ret=1
+typeset -A opt_args
+
+_arguments -C -s -{a,b,c,D,h,i,l,L,s,T,v,w,x,y,z} \
+           -{A,C,e,E,f,F,J,n,N,O,p,P,q,Q,Z}:'function name:->funcs' \
 	   '-I:directory:_dir_list' \
-	   '-d-:debug level:' '-k:function names: _exec_funcs -p' \
+	   '-d-:debug level:' '-k:function names:->pair' \
 	   '-m:minimum execution count:' \
-	   ':executable:_files -g *(*)' \
-	   ':profile file:_files -g gmon.*' \
+	   ':executable:_files -g \*\(\*\)' \
+	   ':profile file:_files -g gmon.\*' \
 	   -- -s '(#--[no-] --)' \
-           '*=name*:function name: _exec_funcs' \
-	   '*=dirs*:directory:_dir_list'
+           '*=name*:function name:->funcs' \
+	   '*=dirs*:directory:_dir_list' && ret=0
+
+if [[ -n "$state" ]]; then
+  local cmd pair expl
+
+  _tags functions || return 1
+
+  [[ "$state" = pair ]] && pair=yes
+
+  if [[ $#line -gt 1 ]]; then
+    cmd="$line[2]"
+  else
+    return 1
+  fi
+
+  if [[ -n "$cmd" ]]; then
+    if [[ "$cmd" = /* ]]; then
+      tmp="$cmd"
+    else
+      tmp="$PWD/$cmd"
+    fi
+
+    if [[ "$tmp" != "$_gprof_command" ]]; then
+      _gprof_command="$tmp"
+      _gprof_funcs=( "${(@)${(@M)${(@f)$(nm $cmd)}:#[^ ]# [tT] ([^_]|_[^_])*}##* }" )
+    fi
+  
+    if [[ -n "$pair" ]]; then
+      if compset -P '*/'; then
+        expl='call arc to function'
+      else
+        expl='call arc from function'
+      fi
+    else
+      expl=function
+    fi
+    _wanted functions expl "$expl" \
+        compadd "$expl[@]" -M 'r:|_=* r:|=*' - "$_gprof_funcs[@]" && ret=0
+  else
+    return 1
+  fi
+fi
+
+return ret
diff --git a/Completion/User/_groups b/Completion/User/_groups
index 27444d26d..7ee9969cd 100644
--- a/Completion/User/_groups
+++ b/Completion/User/_groups
@@ -2,7 +2,7 @@
 
 local expl groups tmp
 
-_wanted groups || return 1
+_tags groups || return 1
 
 if ! zstyle -a ":completion:${curcontext}:" groups groups; then
   (( $+_cache_groups )) ||
@@ -16,4 +16,4 @@ if ! zstyle -a ":completion:${curcontext}:" groups groups; then
   groups=( "$_cache_groups[@]" )
 fi
 
-_all_labels groups expl group compadd "$@" - "$groups[@]"
+_wanted groups expl group compadd "$@" - "$groups[@]"
diff --git a/Completion/User/_lp b/Completion/User/_lp
index e996507ce..60cf8cfd0 100644
--- a/Completion/User/_lp
+++ b/Completion/User/_lp
@@ -36,28 +36,27 @@ if (( ! $+_lp_cache )); then
 fi
 
 if compset -P -P || [[ "$words[CURRENT-1]" = -P ]]; then
-  if _wanted printers; then
-    if zstyle -T ":completion:${curcontext}:printers" verbose; then
-      zformat -a list ' -- ' "$_lp_cache[@]"
-      disp=(-ld list)
-    else
-      disp=()
-    fi
-    _all_labels printers expl printer \
-        compadd "$disp[@]" - "${(@)_lp_cache%%:*}" && return 0
+  if zstyle -T ":completion:${curcontext}:printers" verbose; then
+    zformat -a list ' -- ' "$_lp_cache[@]"
+    disp=(-ld list)
+  else
+    disp=()
+  fi
+  _wanted printers expl printer \
+      compadd "$disp[@]" - "${(@)_lp_cache%%:*}" && return 0
 
-    (( $+_lp_alias_cache )) || return 1
+  (( $+_lp_alias_cache )) || return 1
 
-    if zstyle -T ":completion:${curcontext}:printers" verbose; then
-      zformat -a list ' -- ' "$_lp_alias_cache[@]"
-      disp=(-ld list)
-    else
-      disp=()
-    fi
-    compadd "$expl[@]" "$disp[@]" - "${(@)_lp_alias_cache%%:*}"
+  if zstyle -T ":completion:${curcontext}:printers" verbose; then
+    zformat -a list ' -- ' "$_lp_alias_cache[@]"
+    disp=(-ld list)
   else
-    return 1
+    disp=()
   fi
+  _wanted printers expl printer \
+      compadd "$disp[@]" - "${(@)_lp_alias_cache%%:*}" && return 0
+
+  return 1
 else
   if [[ "${words[1]:t}" = (lpq|lprm) ]]; then
     if [[ "$words" = *-P* ]]; then
diff --git a/Completion/User/_mh b/Completion/User/_mh
index 724b45e5a..29d6bc2a1 100644
--- a/Completion/User/_mh
+++ b/Completion/User/_mh
@@ -17,16 +17,13 @@ if compset -P 1 -; then
   # get list of options, which MH commands can generate themselves
   # awk is just too icky to use for this, sorry.  send me one if
   # you come up with it.
-  if _wanted options; then
-    _all_labels options expl option \
-        compadd - $($words[1] -help | perl -ne 'if (/^\s*-\(?(\S+)/) {
+  _wanted 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
-  fi
-  return 1
+  return
 elif compset -P 1 '[+@]' || [[ "$prev" = -draftfolder ]]; then
   # Complete folder names.
   local mhpath
@@ -72,13 +69,15 @@ else
     # leaving foldnam empty works here
   fi
 
-  if _wanted sequences; then
+  _tags sequences
+  while _tags; do
     while _next_label 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
     done
-  fi
+    (( ret )) || return 0
+  done
   return ret
 fi
diff --git a/Completion/User/_mount b/Completion/User/_mount
index a148fff27..418b7974f 100644
--- a/Completion/User/_mount
+++ b/Completion/User/_mount
@@ -543,7 +543,7 @@ fstype)
       compadd "$expl[@]" -qS, -M 'L:|no=' - "$fss[@]" && ret=0
   ;;
 fsopt)
-  _wanted options || return 1
+  _tags options || return 1
 
   eval 'tmp=(' '"$_fs_'${(s:,:)^${opt_args[$typeops]:-${deffs}}}'[@]"' ')'
   tmp=( "$_fs_any[@]" "${(@)tmp:#}" )
diff --git a/Completion/User/_netscape b/Completion/User/_netscape
index 82fa4509a..ed2bccc75 100644
--- a/Completion/User/_netscape
+++ b/Completion/User/_netscape
@@ -56,16 +56,14 @@ if [[ "$state" = "remote" ]]; then
       fi
     ;;
     *)
-      if _wanted commands; then
-        if [[ -z "$QIPREFIX" ]]; then
-	  _all_labels commands expl 'remote commands' \
-  	      compadd  -s'(' -S '' -M 'm:{a-zA-Z}={A-Za-z}' - \
-                      $remote_commands && ret=0
-        else
-	  _all_labels commands expl 'remote commands' \
-              compadd -qS '(' -M 'm:{a-zA-Z}={A-Za-z}' - \
-                      $remote_commands && ret=0
-	fi
+      if [[ -z "$QIPREFIX" ]]; then
+	_wanted commands expl 'remote commands' \
+  	    compadd -s'(' -S '' -M 'm:{a-zA-Z}={A-Za-z}' - \
+                    $remote_commands && ret=0
+      else
+	_wanted commands expl 'remote commands' \
+            compadd -qS '(' -M 'm:{a-zA-Z}={A-Za-z}' - \
+                    $remote_commands && ret=0
       fi
     ;;
   esac
@@ -78,12 +76,14 @@ if [[ "$state" = "urls" ]]; then
         compadd authors blank cache document fonts global hype image-cache \
             license logo memory-cache mozilla plugins && ret=0
   else
-    if _wanted prefixes; then
+    _tags prefixes
+    while _tags; do
       while _next_label prefixes expl 'URL prefix'; do
         compadd "$expl[@]" -S '' about: mocha: javascript: && ret=0
         _urls "$@" && ret=0
       done
-    fi
+      (( ret )) || return 0
+    done
   fi
 fi
 
diff --git a/Completion/User/_nslookup b/Completion/User/_nslookup
index 7d2a12142..44ab4cacc 100644
--- a/Completion/User/_nslookup
+++ b/Completion/User/_nslookup
@@ -19,9 +19,7 @@
 # other characters than lower case letters, we try to call the function
 # `_nslookup_host'.
 
-setopt localoptions extendedglob
-
-local state expl ret=1 setopts
+local context curstate="$curcontext" expl ret=1 setopts
 
 setopts=(
   'all[print current values]' \
@@ -40,7 +38,7 @@ setopts=(
   '(noignoretc)ignoretc[ignore packet truncation errors]' \
   '(ignoretc)noignoretc[don'"'"'t ignore packet truncation errors]' \
   'class[change query class]:query class:((in\:Internet\ class chaos\:CHAOS\ class hesiod\:MIT\ Athena\ Hesiod\ class any\:wildcard\ \(any\ of\ the\ above\)))'
-  'domain[change default domain]:default domain:_hosts'
+  "domain[change default domain]:default domain:_domains"
   'srchlist[change default domain and search list]: :->srchlist'
   'port[change name server port]:name server port:'
   {query,}type'[change type of information query]:query information type:((a\:internet\ address cname\:canonical\ name\ for\ alias hinfo\:CPU\ and\ operating\ system\ type minfo\:mailbox\ or\ mail\ list\ information mx\:mail\ exchanger ns\:name\ server\ for\ zone ptr\:host\ name\ or\ other\ information soa\:domain\'"'"'s\ \`start-of-authority\'"'"'\ information txt\:text\ information uinfo\:user\ information wks\:supported\ well-known\ services))'
@@ -52,23 +50,25 @@ setopts=(
 if [[ -n "$compcontext" ]]; then
   if [[ CURRENT -eq 1 ]]; then
 
-    funcall ret _nslookup_command && return ret
+    _funcall ret _nslookup_command && return ret
 
-    _description expl 'command'
-    compadd "$expl[@]" - server lserver root finger ls view help set && ret=0
-    _hosts && ret=0
+    _alternative \
+        'commands:command:(server lserver root finger ls view help set exit)' \
+	'hosts:: _hosts' && ret=0
     return ret
   elif [[ "$compstate[context]" = redirect ]]; then
 
-    funcall ret _nslookup_redirect && return ret
+    _funcall ret _nslookup_redirect && return ret
+
+    _tags -C redirection files || return 1
 
     if [[ "$words[1]" != (finger|ls) ]]; then
       _message "redirection not allowed for command \`$words[1]'"
       return 1
     elif [[ "$compstate[redirect]" = '>' ]]; then
-      _description expl 'write to file'
+      _description files expl 'write to file'
     elif [[ "$compstate[redirect]" = '>>' ]]; then
-      _description expl 'append to file'
+      _description files expl 'append to file'
     else
       _message "unknown redirection operator \`$compstate[redirect]'"
       return 1
@@ -79,15 +79,14 @@ if [[ -n "$compcontext" ]]; then
   fi
 
   if [[ "$words[1]" = [a-z]## ]]; then
-    funcall ret _nslookup_$words[1] && return ret
+    _funcall ret _nslookup_$words[1] && return ret
   else
-    funcall ret _nslookup_host && return ret
+    _funcall ret _nslookup_host && return ret
   fi
 
   case "$words[1]" in
   (|l)server)
-    _description expl 'new default server'
-    _hosts "$expl[@]"
+    _wanted hosts expl 'new default server' _hosts
     return
     ;;
   root|exit|help|\?)
@@ -104,24 +103,23 @@ if [[ -n "$compcontext" ]]; then
      '-d[all records]' \
      '-h[CPU and operating system information]' \
      '-s[well-known services]' \
-     ':domain:_hosts'
+     ":domain:_domains"
     return
     ;;
   view)
-    _description expl 'view file'
+    _description files expl 'view file'
     _files "$expl[@]"
     return
     ;;
   set)
-    typeset -A values
+    typeset -A val_args
 
     _values 'state information' "$setopts[@]" && ret=0
 
     [[ -z "$state" ]] && return ret
     ;;
   *)
-    _description expl 'server'
-    _hosts "$expl[@]"
+    _wanted hosts expl 'server' _hosts
     return
   esac
 fi
@@ -130,9 +128,9 @@ fi
 
 if [[ -z "$state" ]]; then
   local line
-  typeset -A options
+  typeset -A opt_args
 
-  _arguments \
+  _arguments -C \
     "-${(@)^${(@M)setopts:#*\]:*}/\[/=[}" \
     "-${(@)^setopts:#(\(|*\]:)*}" \
     "${(@)^${(@)${(@M)setopts:#\(*}/\)/)-}/\(/(-}" \
@@ -143,15 +141,17 @@ fi
 # This is completion after `srchlist' for both types.
 
 if [[ -n "$state" ]]; then
+  _tags domains || return 1
+
   if compset -P '*/'; then
-    _description expl 'search list entry'
+    _description domains expl 'search list entry'
   else
-    _description expl 'default domain name and first search list entry'
+    _description domains expl 'default domain name and first search list entry'
   fi
   if [[ -n "$_vals_cache_multi" ]]; then
-    _hosts "$expl[@]" -qS/ -r "/\\- \\t\\n$_vals_cache_multi"
+    _domains "$expl[@]" -qS/ -r "/\\- \\t\\n$_vals_cache_multi"
   else
-    _hosts "$expl[@]" -qS/
+    _domains "$expl[@]" -qS/
   fi
   return
 fi
diff --git a/Completion/User/_rlogin b/Completion/User/_rlogin
index bf8ff751d..2509bd79c 100644
--- a/Completion/User/_rlogin
+++ b/Completion/User/_rlogin
@@ -28,7 +28,7 @@ _rlogin () {
     return ret
     ;;
   rcp)
-    local curcontext="$curcontext" state line ret=1
+    local curcontext="$curcontext" state line ret=1 expl
     typeset -A opt_args
 
     _arguments -C -s \
@@ -40,7 +40,7 @@ _rlogin () {
       if compset -P '*:'; then
 	_files && ret=0
       elif compset -P '*@'; then
-        _wanted hosts && _rlogin_hosts -S: -q && ret=0
+        _wanted hosts expl host _rlogin_hosts -S: -q && ret=0
       else
         _alternative \
 	    'files:: _files' \
@@ -54,11 +54,11 @@ _rlogin () {
 }
 
 _rlogin_users () {
-  _wanted users && _combination -s '[:@]' my-accounts users-hosts users "$@"
+  _tags users && _combination -s '[:@]' my-accounts users-hosts users "$@"
 }
 
 _rlogin_hosts () {
-  _wanted hosts &&
+  _tags hosts &&
       if [[ "$IPREFIX" == *@ ]]; then
         _combination -s '[:@]' my-accounts users-hosts "users=${IPREFIX/@}" hosts "$@"
       else
diff --git a/Completion/User/_socket b/Completion/User/_socket
index 353a66fd5..af9c8ab0a 100644
--- a/Completion/User/_socket
+++ b/Completion/User/_socket
@@ -1,34 +1,55 @@
 #compdef socket
 
-local state line expl
-typeset -A options
+# Style used:
+#
+#  hosts-ports
+#    The style that contains pairs `host:port'.
 
-_arguments -s \
-  -{b,c,f,q,r,v,w} \
-  -{s,l} \
-  '-p:command:->command' \
+local curcontext="$curcontext" state line expl
+typeset -A opt_args
+
+[[ $CURRENT -eq 2 ]] &&
+    { ! zstyle -T ":completion:${curcontext}:options" prefix-needed ||
+      [[ "$PREFIX" = -* ]] } &&
+    _wanted options expl option \
+        compadd -M 'r:|[_-]=* r:|=*' "$expl[@]" - -version
+
+_arguments -C -s \
+  '-b[background]' \
+  '-c[crlf]' \
+  '-f[fork]' \
+  '-q[quit]' \
+  '-r[read only]' \
+  '-v[verbose]' \
+  '-w[write only]' \
+  '-s[server]' \
+  '-l[loop]' \
+  '-p[program]:command:->command' \
   ':arg1:->arg1' \
   ':arg2:->arg2'
 
 case "$state" in
 command)
   compset -q
-  _normal
+  if [[ $CURRENT -eq 1 ]]; then
+    _command_names -e "$@"
+  else
+    _normal
+  fi
   ;;
 
 arg1)
-  if (( $+options[-s] )); then
-    _message 'port'
+  if (( $+opt_args[-s] )); then
+    _ports
   else
-    _description expl 'host'
-    _hosts "$expl[@]"
+    _wanted hosts expl 'host' _combination '' hosts-ports hosts -
   fi
   ;;
 
 arg2)
-  if (( ! $+options[-s] )); then
-    _description expl 'port'
-    _hostports $line[2] "$expl[@]"
+  if (( ! $+opt_args[-s] )); then
+    _wanted ports expl 'port to connect' \
+        _combination '' hosts-ports hosts="${line[1]:q}" ports -
   fi
   ;;
 esac
diff --git a/Completion/User/_tiff b/Completion/User/_tiff
index 9616009c3..608325fdf 100644
--- a/Completion/User/_tiff
+++ b/Completion/User/_tiff
@@ -195,12 +195,14 @@ if [[ -n "$state" ]]; then
       ;;
     esac
   else
-    if _wanted values; then
+    _tags values
+    while _tags; do
       while _next_label values expl 'compression scheme'; do
         compadd "$expl[@]" - none g4 packbits && ret=0
         compadd "$expl[@]" -qS: - lzw zip jpeg g3 && ret=0
       done
-    fi
+      (( ret )) || return 0
+    done
   fi
 fi
 
diff --git a/Completion/User/_urls b/Completion/User/_urls
index 3989f2219..4234aa274 100644
--- a/Completion/User/_urls
+++ b/Completion/User/_urls
@@ -49,18 +49,22 @@ local localhttp_userdir="$localhttp[3]"
 
 if [[ "$1" = -f ]]; then
   shift
-  _wanted -C -f files && _files "$@" && return
+  _wanted -C -f files _files "$@" && return 0
 fi
 
 ipre="$IPREFIX"
 
-if ! compset -P '(#b)([-+.a-z0-9]#):' && _wanted -C argument prefixes; then
-  while _next_label prefixes expl 'URL prefix' "$@"; do
-    [[ -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]#):'; then
+  _tags -C argument prefixes
+  while _tags; do
+    while _next_label prefixes expl 'URL prefix' "$@"; do
+      [[ -d $urls_path/bookmark ]] &&
+        compadd "$expl[@]" -S '' bookmark: && ret=0
+      compadd "$expl[@]" -S '' file: ftp:// gopher:// http:// && ret=0
+    done
+    (( ret )) || return 0
   done
-  return ret
+  return 1
 fi
 scheme="$match[1]"
 
@@ -73,17 +77,19 @@ case "$scheme" in
   ;;
   file)
     if ! compset -P //; then
-      _wanted -C file files || return 1
-
-      while _next_label 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
+      _tags -C file files
+      while _tags; do
+        while _next_label 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
+        done
+	(( ret )) || return 0
       done
-      return ret
+      return 1
     fi
   ;;
   bookmark)
@@ -93,34 +99,40 @@ case "$scheme" in
           compadd "$@" -U - \
               "$ipre$(<"$urls_path/$scheme/${(Q)PREFIX}${(Q)SUFFIX}")" && ret=0
     else
-      if _wanted -C bookmark files; then
+      _tags -C bookmark files
+      while _tags; do
         while _next_label 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
         done
-      fi
+	(( ret )) || return 0
+      done
     fi
     return ret
   ;;
 esac
 
 # Complete hosts
-if ! compset -P '(#b)([^/]#)/' && _wanted hosts; then
+if ! compset -P '(#b)([^/]#)/'; then
   uhosts=($urls_path/$scheme/$PREFIX*$SUFFIX(/:t))
 
-  while _next_label hosts expl host "$@"; do
-    (( $#uhosts )) || _hosts -S/ && ret=0
-    [[ "$scheme" = http ]] && uhosts=($uhosts $localhttp_servername)
-    compadd "$expl[@]" -S/ - $uhosts && ret=0
+  _tags hosts
+  while _tags; do
+    while _next_label hosts expl host "$@"; do
+      (( $#uhosts )) || _hosts -S/ && ret=0
+      [[ "$scheme" = http ]] && uhosts=($uhosts $localhttp_servername)
+      compadd "$expl[@]" -S/ - $uhosts && ret=0
+    done
+    (( ret )) || return 0
   done
-  return ret
+  return 1
 fi
 host="$match[1]"
 
 # Complete part after hostname
 
-_wanted -C local files || return 1
+_tags -C local files || return 1
 
 if [[ "$localhttp_servername" = "$host" ]]; then
   if compset -P \~; then
@@ -129,20 +141,29 @@ if [[ "$localhttp_servername" = "$host" ]]; then
       return
     fi
     user="$match[1]"
-    while _next_label 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
+    while _tags; do
+      while _next_label 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
+      done
+      (( ret )) || return 0
     done
   else
-    while _next_label files expl 'local file'; do
-      _path_files "$expl[@]" -W $localhttp_documentroot -g '*(^/)' && ret=0
-      _path_files "$expl[@]" -W $localhttp_documentroot -S/ -r '/' -/ && ret=0
+    while _tags; do
+      while _next_label files expl 'local file'; do
+        _path_files "$expl[@]" -W $localhttp_documentroot -g '*(^/)' && ret=0
+        _path_files "$expl[@]" -W $localhttp_documentroot -S/ -r '/' -/ && ret=0
+      done
+      (( ret )) || return 0
     done
   fi
 else
-  while _next_label 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
+  while _tags; do
+    while _next_label 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
+    done
+    (( ret )) || return 0
   done
 fi
 return $ret
diff --git a/Completion/User/_users b/Completion/User/_users
index d04731af9..dce0fd584 100644
--- a/Completion/User/_users
+++ b/Completion/User/_users
@@ -2,9 +2,7 @@
 
 local expl users
 
-_wanted users || return 1
-
 zstyle -a ":completion:${curcontext}:" users users &&
-    _all_labels users expl user compadd "$@" - "$users[@]" && return 0
+    _wanted users expl user compadd "$@" - "$users[@]" && return 0
 
-_all_labels users expl user compadd "$@" - "${(@k)userdirs}"
+_wanted users expl user compadd "$@" - "${(@k)userdirs}"
diff --git a/Completion/User/_users_on b/Completion/User/_users_on
index b19cff6e7..b5c05e12b 100644
--- a/Completion/User/_users_on
+++ b/Completion/User/_users_on
@@ -2,10 +2,8 @@
 
 local expl
 
-_wanted users || return 1
-
-if which users >/dev/null; then
-  _all_labels users expl 'users logged on' \
+if (( $+commands[users] )); then
+  _wanted users expl 'users logged on' \
       compadd "$@" - $(_call users users) && return 0
 else
   # Other methods of finding out users logged on should be added here
diff --git a/Completion/User/_whois b/Completion/User/_whois
index 827ebe627..4b6d73b86 100644
--- a/Completion/User/_whois
+++ b/Completion/User/_whois
@@ -1,12 +1,14 @@
-#compdef whois
+#compdef whois fwhois
 
 _whois () {
-  setopt localoptions extendedglob
   _whois_setup
-  $_whois_comp
+  case "$0" in
+  fwhois) _whois_fwhois;;
+  *) $_whois_comp;;
+  esac
 }
 
-builtin functions _whois_setup >&- ||
+(( $+functions[_whois_setup] )) ||
 _whois_setup () {
   (( $+_whois_defaultserver )) ||
     _whois_defaultserver='whois.internic.net'
@@ -65,6 +67,7 @@ _whois_setup () {
   (( $+_whois_arguments )) || {
     local help="$(whois </dev/null 2>&1)"
     local tmp opt opts
+    local hostopt=-h+
 
     if [[ $help = *"user[@<whois.server>]"* ]]; then
       _whois_comp=_whois_fwhois
@@ -72,6 +75,7 @@ _whois_setup () {
       _whois_comp=_whois_multi
     else
       _whois_comp=_whois_single
+      hostopt=-h
     fi
 
     _whois_arguments=()
@@ -96,25 +100,29 @@ _whois_setup () {
     for opt in $tmp; do
       opts=(-${^tmp:#$opt})
       if (( $#opts )); then opts="($opts)"; else opts=; fi
-      _whois_arguments=("$_whois_arguments[@]"
-	"${opts}-${opt}[${${${(@M)_whois_servers:#*:$opt}%:?}:-specify host}]${(M)${(M)opt:#h}/h/:host:_whois_hosts}"
-      )
+      if [[ $opt = h ]]; then
+	_whois_arguments=("$_whois_arguments[@]"
+	  "${opts}${hostopt}:host:_whois_hosts")
+      else
+	_whois_arguments=("$_whois_arguments[@]"
+	  "${opts}-${opt}[${${(@M)_whois_servers:#*:$opt}%:?}]")
+      fi
     done
   }
 }
 
 _whois_single () {
-  local state line expl
+  local curcontext="$curcontext" state line expl
   typeset -A opt_args
   local tmp host
 
-  _arguments \
+  _arguments -C \
     "$_whois_arguments[@]" \
     ':identifier:->identifier'
 
   case "$state" in
   identifier)
-    if [[ -z "$QIPREFIX" ]]; then
+    if [[ -z "$QIPREFIX" && -z "$PREFIX" ]]; then
       compadd -QS '' \'
       return
     fi
@@ -126,7 +134,7 @@ _whois_single () {
         break
       fi
     done
-    if builtin functions "_whois:$host" >&-; then
+    if (( $+functions[_whois:$host] )); then
       "_whois:$host" "$expl[@]"
     else
       _message "identifier"
@@ -136,11 +144,11 @@ _whois_single () {
 }
 
 _whois_multi () {
-  local state line expl
+  local curcontext="$curcontext" state line expl
   typeset -A opt_args
   local tmp host
 
-  _arguments \
+  _arguments -C \
     "$_whois_arguments[@]" \
     '*::identifier:->identifier'
 
@@ -153,7 +161,7 @@ _whois_multi () {
         break
       fi
     done
-    if builtin functions "_whois:$host" >&-; then
+    if (( $+functions[_whois:$host] )); then
       "_whois:$host" "$expl[@]"
     else
       _message "identifier"
@@ -166,13 +174,13 @@ _whois_fwhois () {
   if compset -P '*@'; then
     _whois_hosts "$@"
   else
-    if [[ -z "$QIPREFIX" ]]; then
+    if [[ -z "$QIPREFIX" && -z "$PREFIX" ]]; then
       compadd -QS '' \'
       return
     fi
     compset -q
     host="$_whois_defaultserver"
-    if builtin functions "_whois:$host" >&-; then
+    if (( $+functions[_whois:$host] )); then
       "_whois:$host" "$@"
     else
       _message "identifier"
@@ -181,28 +189,33 @@ _whois_fwhois () {
 }
 
 _whois_hosts () {
-  compadd "$@" \
-    -M 'm:{a-zA-Z}={A-Za-z} r:|.=* r:|=*' \
-    - ${_whois_servers%:?} || _hosts "$@"
+  _tags hosts &&
+    compadd "$@" \
+      -M 'm:{a-zA-Z}={A-Za-z} r:|.=* r:|=*' \
+      - ${_whois_servers%:?} || _hosts "$@"
 }
 
 _whois_ports () {
-  compadd "$@" - whois || _ports "$@"
+  _tags ports && compadd "$@" - whois || _ports "$@"
 }
 
-builtin functions _whois:whois.internic.net >&- ||
+(( $+functions[_whois:whois.internic.net] )) ||
 _whois:whois.internic.net () {
   if (( CURRENT == 1 )); then
-    compadd HELP DOMAIN HOST
+    local expl
+
+    _wanted strings expl string compadd HELP DOMAIN HOST
   else
     _message 'string'
   fi
 }
 
-builtin functions _whois:whois.nic.ad.jp >&- ||
+(( $+functions[_whois:whois.nic.ad.jp] )) ||
 _whois:whois.nic.ad.jp () {
   if (( CURRENT == 1 )); then
-    compadd HELP DOM NET HOST PERSON CONN COM
+    local expl
+
+    _wanted strings expl string compadd HELP DOM NET HOST PERSON CONN COM
   else
     _message 'string'
   fi
diff --git a/Completion/X/_x_colormapid b/Completion/X/_x_colormapid
index 3c637c1d9..61b0a72f1 100644
--- a/Completion/X/_x_colormapid
+++ b/Completion/X/_x_colormapid
@@ -2,7 +2,7 @@
 
 local expl list desc
 
-_wanted colormapids || return 1
+_tags colormapids || return 1
 
 list=(${(f)"$(xprop -root -f RGB_COLOR_MAP 32xcccccccxx ': $0\n'|awk -F'[ ():]' '/^[a-zA-Z_]+\(RGB_COLOR_MAP\)/ {print $5, "--", $1}')"})
 
@@ -12,5 +12,5 @@ else
   desc=()
 fi
 
-_all_labels colormapids expl 'colormap id' \
+_wanted colormapids expl 'colormap id' \
     compadd "$@" "$desc[@]" - "${(@)list%% *}" 
diff --git a/Completion/X/_x_display b/Completion/X/_x_display
index 94c3fa9a4..f547a64fa 100644
--- a/Completion/X/_x_display
+++ b/Completion/X/_x_display
@@ -1,3 +1,3 @@
 #autoload
 
-_wanted displays && _hosts -S ':0 ' -r :
+_tags displays && _hosts -S ':0 ' -r :
diff --git a/Completion/X/_x_extension b/Completion/X/_x_extension
index 11e53fa6c..5b742a78c 100644
--- a/Completion/X/_x_extension
+++ b/Completion/X/_x_extension
@@ -2,18 +2,18 @@
 
 local expl
 
-_wanted extensions || return 1
+_tags 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
 
-  _all_labels extensions expl 'X extensions' \
+  _wanted extensions expl 'X extensions' \
       compadd "$@" -M 'm:{a-z}={A-Z} r:|-=* r:|=*' - all "$_xe_cache[@]"
 else
   [[ "$1" = - ]] && shift
 
-  _all_labels extensions expl 'X extensions' \
+  _wanted extensions expl 'X extensions' \
       compadd "$@" -M 'm:{a-z}={A-Z} r:|-=* r:|=*' - "$_xe_cache[@]"
 fi
diff --git a/Completion/X/_x_font b/Completion/X/_x_font
index 43a713b34..228542bd2 100644
--- a/Completion/X/_x_font
+++ b/Completion/X/_x_font
@@ -2,7 +2,7 @@
 
 local expl
 
-_wanted fonts || return 1
+_tags fonts || return 1
 
 # This *has* to be improved some day...
 
@@ -12,5 +12,5 @@ if (( ! $+_font_cache )); then
  _font_cache=( "${(@)^${(@f)$(_call fonts xlsfonts)}%%--*}--" )
 fi
 
-_all_labels fonts expl font \
+_wanted fonts expl font \
     compadd -M 'r:|-=* r:|=*' "$@" -S '' - "$_font_cache[@]"
diff --git a/Completion/X/_x_keysym b/Completion/X/_x_keysym
index f50762f7e..8d4cfa1f8 100644
--- a/Completion/X/_x_keysym
+++ b/Completion/X/_x_keysym
@@ -2,7 +2,7 @@
 
 local expl
 
-_wanted keysyms || return 1
+_tags keysyms || return 1
 
 if (( ! $+_keysym_cache )); then
   local file
@@ -18,5 +18,5 @@ if (( ! $+_keysym_cache )); then
   fi
 fi
 
-_all_labels keysyms expl 'key symbol' \
+_wanted keysyms expl 'key symbol' \
     compadd "$@" -M 'm:{a-z}={A-Z} r:|-=* r:|=*' - $_keysym_cache
diff --git a/Completion/X/_x_window b/Completion/X/_x_window
index 1862db9a7..24d6048a7 100644
--- a/Completion/X/_x_window
+++ b/Completion/X/_x_window
@@ -2,17 +2,17 @@
 
 local list expl
 
-_wanted windows || return 1
+_tags windows || return 1
 
 list=( "${(@)${(M@)${(@f)$(_call windows xwininfo -root -tree)}:#[ 	]#0x[0-9a-f]# \"*}##[ 	]#}" )
 
 if [[ "$1" = -n ]]; then
   shift
 
-  _all_labels windows expl 'window name' \
+  _wanted windows expl 'window name' \
       compadd "$@" -d list - "${(@)${(@)list#*\"}%%\"*}"
 else
   [[ "$1" = - ]] && shift
 
-  _all_labels windows expl 'window ID' compadd "$@" -d list - "${(@)list%% *}"
+  _wanted windows expl 'window ID' compadd "$@" -d list - "${(@)list%% *}"
 fi
diff --git a/Completion/X/_xmodmap b/Completion/X/_xmodmap
index 6595d5adf..5c7fcf3fe 100644
--- a/Completion/X/_xmodmap
+++ b/Completion/X/_xmodmap
@@ -82,12 +82,14 @@ if [[ -n "$state" ]]; then
     [[ "$what" = *ksym* ]] && _x_keysym "$suf[@]" && ret=0
 
   else
-    if _wanted commands; then
+    _tags commands
+    while _tags; do
       while _next_label commands expl command; do
         compadd "$expl[@]" -S ' ' keycode keysym clear add remove && ret=0
         compadd "$expl[@]" -S ' = ' pointer && ret=0
       done
-    fi
+      (( ret )) || return 0
+    done
   fi
 fi
 
diff --git a/Completion/X/_xutils b/Completion/X/_xutils
index a57f7be36..c0d94a998 100644
--- a/Completion/X/_xutils
+++ b/Completion/X/_xutils
@@ -55,23 +55,29 @@ xhost)
     if [[ "$tmp" = *:* ]]; then
       if compset -P '(#b)(*):'; then
 	type="$match[1]"
-	_wanted displays &&
-            while _next_label displays expl 'disallow access'; do
+	_tags displays
+	while _tags; do
+          while _next_label 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
+	            _hosts "$expl[@]" } && ret=0
+	  done
+	  (( ret )) || return 0
+        done
       else
 	_alternative \
 	    'types:name family:compadd -S: ${(L)tmp%%:*}' \
 	    'hosts:host:compadd ${(@)tmp#*:}' && ret=0
       fi
     else
-      _wanted displays &&
-          while _next_label displays expl 'disallow access'; do
-	    { compadd "$expl[@]" -M 'm:{a-z}={A-Z} r:|[:.]=* r:|=*' - $tmp ||
-              _hosts "$expl[@]" } && return 0
-          done
+      _tags displays
+      while _tags; do
+        while _next_label displays expl 'disallow access'; do
+	  { compadd "$expl[@]" -M 'm:{a-z}={A-Z} r:|[:.]=* r:|=*' - $tmp ||
+            _hosts "$expl[@]" } && ret=0
+        done
+	(( ret )) || return 0
+      done
     fi
   else
     compset -P +
diff --git a/Completion/X/_xwit b/Completion/X/_xwit
index 998627869..69b210e5b 100644
--- a/Completion/X/_xwit
+++ b/Completion/X/_xwit
@@ -17,7 +17,7 @@ _xwit_guard () {
 _xwit_compopts () {
   local expl
   _wanted options expl option compadd - ${(k)no[(R)*~0]} ||
-      _all_labels options expl option compadd - ${(k)no}
+      _wanted options expl option compadd - ${(k)no}
 }
 
 _regex_arguments _xwit_parse \