about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTanaka Akira <akr@users.sourceforge.net>1999-08-19 11:18:05 +0000
committerTanaka Akira <akr@users.sourceforge.net>1999-08-19 11:18:05 +0000
commit9867c4091e71e6ed69889a9bfaee07275d2fa04e (patch)
tree37318116ff90f7b90df7cb9e894790d96be0849b
parent04979daf4f9b9645f22df1dfbb5974ab82294868 (diff)
downloadzsh-9867c4091e71e6ed69889a9bfaee07275d2fa04e.tar.gz
zsh-9867c4091e71e6ed69889a9bfaee07275d2fa04e.tar.xz
zsh-9867c4091e71e6ed69889a9bfaee07275d2fa04e.zip
manual/7448
-rw-r--r--Completion/Base/_arguments388
-rw-r--r--Completion/Base/_brace_parameter3
-rw-r--r--Completion/Base/_command_names11
-rw-r--r--Completion/Base/_condition5
-rw-r--r--Completion/Base/_equal7
-rw-r--r--Completion/Base/_long_options79
-rw-r--r--Completion/Base/_math11
-rw-r--r--Completion/Base/_parameter6
-rw-r--r--Completion/Base/_subscript13
-rw-r--r--Completion/Base/_tilde14
-rw-r--r--Completion/Base/_vars9
-rw-r--r--Completion/Builtins/_aliases5
-rw-r--r--Completion/Builtins/_arrays5
-rw-r--r--Completion/Builtins/_autoload5
-rw-r--r--Completion/Builtins/_bg_jobs5
-rw-r--r--Completion/Builtins/_bindkey8
-rw-r--r--Completion/Builtins/_builtin5
-rw-r--r--Completion/Builtins/_cd8
-rw-r--r--Completion/Builtins/_command5
-rw-r--r--Completion/Builtins/_disable22
-rw-r--r--Completion/Builtins/_echotc6
-rw-r--r--Completion/Builtins/_enable22
-rw-r--r--Completion/Builtins/_fc5
-rw-r--r--Completion/Builtins/_functions5
-rw-r--r--Completion/Builtins/_hash8
-rw-r--r--Completion/Builtins/_jobs5
-rw-r--r--Completion/Builtins/_kill11
-rw-r--r--Completion/Builtins/_limits5
-rw-r--r--Completion/Builtins/_sched4
-rw-r--r--Completion/Builtins/_set8
-rw-r--r--Completion/Builtins/_stat10
-rw-r--r--Completion/Builtins/_trap8
-rw-r--r--Completion/Builtins/_unhash22
-rw-r--r--Completion/Builtins/_vars_eq5
-rw-r--r--Completion/Builtins/_wait8
-rw-r--r--Completion/Builtins/_which9
-rw-r--r--Completion/Builtins/_zftp19
-rw-r--r--Completion/Builtins/_zle8
-rw-r--r--Completion/Builtins/_zmodload7
-rw-r--r--Completion/Commands/_history_complete_word6
-rw-r--r--Completion/Core/_description22
-rw-r--r--Completion/Core/_main_complete18
-rw-r--r--Completion/Core/_message19
-rw-r--r--Completion/Core/_normal41
-rw-r--r--Completion/Core/_options5
-rw-r--r--Completion/Core/_parameters8
-rw-r--r--Completion/Core/_path_files8
-rw-r--r--Completion/Core/_set_options5
-rw-r--r--Completion/Core/_unset_options5
-rw-r--r--Completion/Core/compdump6
-rw-r--r--Completion/Core/compinit29
-rw-r--r--Completion/Pbmplus/_asciitopnm3
-rw-r--r--Completion/Pbmplus/_fitstopgm3
-rw-r--r--Completion/Pbmplus/_fitstopnm4
-rw-r--r--Completion/Pbmplus/_g3topbm3
-rw-r--r--Completion/Pbmplus/_giftopnm4
-rw-r--r--Completion/Pbmplus/_macptopbm3
-rw-r--r--Completion/Pbmplus/_pbm_file20
-rw-r--r--Completion/Pbmplus/_pbmclean3
-rw-r--r--Completion/Pbmplus/_pbmmake3
-rw-r--r--Completion/Pbmplus/_pbmmask3
-rw-r--r--Completion/Pbmplus/_pbmpscale3
-rw-r--r--Completion/Pbmplus/_pbmreduce4
-rw-r--r--Completion/Pbmplus/_pbmtext3
-rw-r--r--Completion/Pbmplus/_pbmto10x3
-rw-r--r--Completion/Pbmplus/_pbmtobg3
-rw-r--r--Completion/Pbmplus/_pbmtoepsi3
-rw-r--r--Completion/Pbmplus/_pbmtolj3
-rw-r--r--Completion/Pbmplus/_pbmtoln035
-rw-r--r--Completion/Pbmplus/_pbmtolps3
-rw-r--r--Completion/Pbmplus/_pbmtomacp4
-rw-r--r--Completion/Pbmplus/_pbmtopgm3
-rw-r--r--Completion/Pbmplus/_pbmtopk11
-rw-r--r--Completion/Pbmplus/_pbmupc4
-rw-r--r--Completion/Pbmplus/_pgmcrater5
-rw-r--r--Completion/Pbmplus/_pgmkernel3
-rw-r--r--Completion/Pbmplus/_pgmnoise3
-rw-r--r--Completion/Pbmplus/_pgmnorm5
-rw-r--r--Completion/Pbmplus/_pgmoil3
-rw-r--r--Completion/Pbmplus/_pgmramp3
-rw-r--r--Completion/Pbmplus/_pgmtexture3
-rw-r--r--Completion/Pbmplus/_pgmtopbm5
-rw-r--r--Completion/Pbmplus/_pgmtoppm21
-rw-r--r--Completion/Pbmplus/_pktopbm4
-rw-r--r--Completion/Pbmplus/_pnmalias6
-rw-r--r--Completion/Pbmplus/_pnmarith3
-rw-r--r--Completion/Pbmplus/_pnmcat4
-rw-r--r--Completion/Pbmplus/_pnmcomp5
-rw-r--r--Completion/Pbmplus/_pnmconvol3
-rw-r--r--Completion/Pbmplus/_pnmcrop3
-rw-r--r--Completion/Pbmplus/_pnmcut3
-rw-r--r--Completion/Pbmplus/_pnmdepth3
-rw-r--r--Completion/Pbmplus/_pnmenlarge3
-rw-r--r--Completion/Pbmplus/_pnmflip5
-rw-r--r--Completion/Pbmplus/_pnmgamma16
-rw-r--r--Completion/Pbmplus/_pnmhistmap4
-rw-r--r--Completion/Pbmplus/_pnmindex4
-rw-r--r--Completion/Pbmplus/_pnmmargin4
-rw-r--r--Completion/Pbmplus/_pnmnlfilt3
-rw-r--r--Completion/Pbmplus/_pnmpad6
-rw-r--r--Completion/Pbmplus/_pnmpaste6
-rw-r--r--Completion/Pbmplus/_pnmrotate3
-rw-r--r--Completion/Pbmplus/_pnmscale16
-rw-r--r--Completion/Pbmplus/_pnmshear3
-rw-r--r--Completion/Pbmplus/_pnmtile3
-rw-r--r--Completion/Pbmplus/_pnmtoddif4
-rw-r--r--Completion/Pbmplus/_pnmtofits3
-rw-r--r--Completion/Pbmplus/_pnmtops5
-rw-r--r--Completion/Pbmplus/_pnmtorast3
-rw-r--r--Completion/Pbmplus/_pnmtosgi3
-rw-r--r--Completion/Pbmplus/_pnmtotiff5
-rw-r--r--Completion/Pbmplus/_pnmtoxwd4
-rw-r--r--Completion/Pbmplus/_ppm3d4
-rw-r--r--Completion/Pbmplus/_ppmbrighten3
-rw-r--r--Completion/Pbmplus/_ppmchange15
-rw-r--r--Completion/Pbmplus/_ppmdim3
-rw-r--r--Completion/Pbmplus/_ppmdist3
-rw-r--r--Completion/Pbmplus/_ppmdither7
-rw-r--r--Completion/Pbmplus/_ppmflash3
-rw-r--r--Completion/Pbmplus/_ppmforge13
-rw-r--r--Completion/Pbmplus/_ppmmake3
-rw-r--r--Completion/Pbmplus/_ppmmix3
-rw-r--r--Completion/Pbmplus/_ppmntsc3
-rw-r--r--Completion/Pbmplus/_ppmpat4
-rw-r--r--Completion/Pbmplus/_ppmquant26
-rw-r--r--Completion/Pbmplus/_ppmquantall3
-rw-r--r--Completion/Pbmplus/_ppmshift3
-rw-r--r--Completion/Pbmplus/_ppmspread3
-rw-r--r--Completion/Pbmplus/_ppmtoacad4
-rw-r--r--Completion/Pbmplus/_ppmtobmp3
-rw-r--r--Completion/Pbmplus/_ppmtogif3
-rw-r--r--Completion/Pbmplus/_ppmtoicr4
-rw-r--r--Completion/Pbmplus/_ppmtoilbm3
-rw-r--r--Completion/Pbmplus/_ppmtomap3
-rw-r--r--Completion/Pbmplus/_ppmtomitsu7
-rw-r--r--Completion/Pbmplus/_ppmtopj6
-rw-r--r--Completion/Pbmplus/_ppmtopjxl9
-rw-r--r--Completion/Pbmplus/_ppmtosixel3
-rw-r--r--Completion/Pbmplus/_ppmtotga3
-rw-r--r--Completion/Pbmplus/_ppmtouil3
-rw-r--r--Completion/Pbmplus/_ppmtoyuvsplit3
-rw-r--r--Completion/Pbmplus/_psidtopgm4
-rw-r--r--Completion/Pbmplus/_pstopnm10
-rw-r--r--Completion/Pbmplus/_rawtopgm5
-rw-r--r--Completion/Pbmplus/_rawtoppm6
-rw-r--r--Completion/Pbmplus/_rgb3toppm16
-rw-r--r--Completion/Pbmplus/_sgitopnm3
-rw-r--r--Completion/Pbmplus/_sldtoppm7
-rw-r--r--Completion/Pbmplus/_yuvsplittoppm3
-rw-r--r--Completion/Pbmplus/_yuvtoppm3
-rw-r--r--Completion/Pbmplus/_zeisstopnm3
-rw-r--r--Completion/User/_a2ps26
-rw-r--r--Completion/User/_bunzip25
-rw-r--r--Completion/User/_bzip25
-rw-r--r--Completion/User/_chown8
-rw-r--r--Completion/User/_colors6
-rw-r--r--Completion/User/_compress5
-rw-r--r--Completion/User/_configure4
-rw-r--r--Completion/User/_cursors5
-rw-r--r--Completion/User/_dd17
-rw-r--r--Completion/User/_find27
-rw-r--r--Completion/User/_gdb35
-rw-r--r--Completion/User/_groups5
-rw-r--r--Completion/User/_gunzip5
-rw-r--r--Completion/User/_gzip3
-rw-r--r--Completion/User/_hosts5
-rw-r--r--Completion/User/_make5
-rw-r--r--Completion/User/_man5
-rw-r--r--Completion/User/_mh27
-rw-r--r--Completion/User/_pdf5
-rw-r--r--Completion/User/_ps5
-rw-r--r--Completion/User/_pspdf7
-rw-r--r--Completion/User/_rcs5
-rw-r--r--Completion/User/_rlogin8
-rw-r--r--Completion/User/_strip5
-rw-r--r--Completion/User/_stty8
-rw-r--r--Completion/User/_su9
-rw-r--r--Completion/User/_tar15
-rw-r--r--Completion/User/_tar_archive10
-rw-r--r--Completion/User/_tex5
-rw-r--r--Completion/User/_uncompress3
-rw-r--r--Completion/User/_use_lo6
-rw-r--r--Completion/User/_x_options5
-rw-r--r--Completion/User/_xfig5
-rw-r--r--Completion/User/_xsetroot17
-rw-r--r--Doc/Zsh/compsys.yo164
-rw-r--r--Doc/Zsh/mod_parameter.yo2
187 files changed, 1691 insertions, 254 deletions
diff --git a/Completion/Base/_arguments b/Completion/Base/_arguments
new file mode 100644
index 000000000..5170acb84
--- /dev/null
+++ b/Completion/Base/_arguments
@@ -0,0 +1,388 @@
+#autoload
+
+# Complete the arguments of the current command according to the
+# descriptions given as arguments to this function.
+
+local long args rest ws cur nth def nm expl descr action opt arg tmp
+
+# Associative arrays used to collect information about the options.
+
+typeset -A opts mopts dopts dmopts odopts odmopts
+
+# See if we support long options, too.
+
+nth=$argv[(I)--]
+if (( nth )); then
+  long=( "${(@)argv[nth+1,-1]}" )
+  argv=("${(@)argv[1,nth-1]}")
+else
+  long=()
+fi
+
+# Now parse the arguments...
+
+args=()
+nth=1
+while (( $# )); do
+
+  # This describes a one-shot option.
+
+  if [[ "$1" = [-+]* ]]; then
+    if [[ "$1" = *:* ]]; then
+
+      # If the option name ends in a `-', the first argument comes
+      # directly after the option, if it ends in a `+', the first
+      # argument *may* come directly after the option, otherwise it
+      # is in the next word.
+
+      if [[ "$1" = [^:]##-:* ]]; then
+        dopts[${${1%%:*}[1,-2]}]="${1#*:}"
+      elif [[ "$1" = [^:]##+:* ]]; then
+        odopts[${${1%%:*}[1,-2]}]="${1#*:}"
+      else
+        opts[${1%%:*}]="${1#*:}"
+      fi
+    else
+      opts[$1]=''
+    fi
+  elif [[ "$1" = \*[-+]* ]]; then
+
+    # The same for options that may appear more than once.
+
+    if [[ "$1" = *:* ]]; then
+      if [[ "$1" = [^:]##-:* ]]; then
+        dmopts[${${1[2,-1]%%:*}[1,-2]}]="${1#*:}"
+      elif [[ "$1" = [^:]##+:* ]]; then
+        odmopts[${${1[2,-1]%%:*}[1,-2]}]="${1#*:}"
+      else
+        mopts[${1[2,-1]%%:*}]="${1#*:}"
+      fi
+    else
+      mopts[${1[2,-1]}]=''
+    fi
+  elif [[ "$1" = \*:* ]]; then
+
+    # This is `*:...', describing `all other arguments'.
+
+    rest="${1[3,-1]}"
+  elif [[ "$1" = :* ]]; then
+
+    # This is `:...', describing `the next argument'.
+
+    args[nth++]="${1#*:}"
+  else
+
+    # And this is `n:...', describing the `n'th argument.
+
+    args[${1%%:*}]="${1#*:}"
+    nth=$(( ${1%%:*} + 1 ))
+  fi
+  shift
+done
+
+if [[ $#long -ne 0 && "$PREFIX" = --* ]]; then
+
+   # If the current words starts with `--' and we should use long
+   # options, just call...
+
+  _long_options "$long[@]"
+else
+
+  # Otherwise parse the command line...
+
+  ws=( "${(@)words[2,-1]}" )
+  cur=$(( CURRENT-2 ))
+  nth=1
+
+  # ...until the current word is reached.
+
+  while [[ cur -gt 0 ]]; do
+
+    # `def' holds the description for the option we are currently after.
+    # Check if the next argument for the option is optional.
+
+    if [[ "$def" = :* ]]; then
+      opt=yes
+    else
+      opt=''
+    fi
+    arg=''
+
+    # Remove one description/action pair from `def' if that isn't empty.
+
+    if [[ -n "$def" ]]; then
+      if [[ "$def" = ?*:*:* ]]; then
+        def="${def#?*:*:}"
+      else
+        def=''
+      fi
+    else
+
+      # If it is empty, and the word starts with `--' and we should
+      # complete long options, just ignore this word, otherwise make sure
+      # we test for options below and handle normal arguments.
+
+      if [[ $#long -eq 0 || "$ws[1]" != --* ]]; then
+        opt=yes
+	arg=yes
+      else
+        def=''
+      fi
+    fi
+
+    if [[ -n "$opt" ]]; then
+
+      # `opt' was set above if we have to test if the word is an option.
+      # We first test for the simple options -- those without arguments or
+      # those whose arguments have to be given as separate words.
+
+      if (( $+opts[$ws[1]] )); then
+
+        # Options that may only be given once are removed from the
+        # associative array so that we are not offered them again.
+
+        def="$opts[$ws[1]]"
+        unset "opts[$ws[1]]"
+      elif (( $+mopts[$ws[1]] )); then
+        def="$mopts[$ws[1]]"
+      else
+
+        # If the word is none of the simple options, test for those
+        # whose first argument has to or may come directly after the
+        # option. This is done in four loops looking very much alike.
+
+        if (( $#dopts )); then
+
+	  # First we get the option names.
+
+	  tmp=( "${(@k)dopts}" )
+
+	  # Then we loop over them and see if the current word begins
+	  # with one of the option names.
+
+	  while (( $#tmp )); do
+	    [[ "$ws[1]" = ${tmp[1]}* ]] && break
+	    shift 1 tmp
+	  done
+
+	  if (( $#tmp )); then
+
+	    # It does. So use the description for it, but only from
+	    # the second argument on, because we are searching the
+	    # description for the next command line argument.
+
+	    opt=''
+	    def="$dopts[$tmp[1]]"
+	    unset "dopts[$tmp[1]]"
+	    if [[ "$def" = ?*:*:* ]]; then
+              def="${def#?*:*:}"
+            else
+              def=''
+	    fi
+          fi
+        fi
+	if [[ -n "$opt" && $#dmopts -ne 0 ]]; then
+	  tmp=( "${(@k)dmopts}" )
+	  while (( $#tmp )); do
+	    [[ "$ws[1]" = ${tmp[1]}* ]] && break
+	    shift 1 tmp
+	  done
+
+	  if (( $#tmp )); then
+	    opt=''
+	    def="$dmopts[$tmp[1]]"
+	    if [[ "$def" = ?*:*:* ]]; then
+              def="${def#?*:*:}"
+            else
+              def=''
+            fi
+          fi
+	fi
+        if [[ -n "$opt" && $#odopts -ne 0 ]]; then
+	  tmp=( "${(@k)odopts}" )
+	  while (( $#tmp )); do
+	    [[ "$ws[1]" = ${tmp[1]}* ]] && break
+	    shift 1 tmp
+	  done
+
+	  if (( $#tmp )); then
+	    opt=''
+	    def="$odopts[$tmp[1]]"
+	    unset "odopts[$tmp[1]]"
+
+	    # For options whose first argument *may* come after the
+	    # option, we skip over the first description only if there
+	    # is something after the option name on the line.
+
+	    if [[ "$ws[1]" != "$tmp[1]" ]]; then
+	      if [[ "$def" = ?*:*:* ]]; then
+                def="${def#?*:*:}"
+              else
+                def=''
+              fi
+	    fi
+          fi
+        fi
+	if [[ -n "$opt" && $#odmopts -ne 0 ]]; then
+	  tmp=( "${(@k)odmopts}" )
+	  while (( $#tmp )); do
+	    [[ "$ws[1]" = ${tmp[1]}* ]] && break
+	    shift 1 tmp
+	  done
+
+	  if (( $#tmp )); then
+	    opt=''
+	    def="$odmopts[$tmp[1]]"
+	    if [[ "$ws[1]" != "$tmp[1]" ]]; then
+	      if [[ "$def" = ?*:*:* ]]; then
+                def="${def#?*:*:}"
+              else
+                def=''
+              fi
+            fi
+          fi
+	fi
+
+	# If we didn't find a matching option description and we were
+	# told to use normal argument descriptions, just increase
+	# our counter `nth'.
+
+        if [[ -n "$opt" && -n "$arg" ]]; then
+          def=''
+	  (( nth++ ))
+        fi
+      fi
+    fi
+
+    shift 1 ws
+    (( cur-- ))
+  done
+
+  # Now generate the matches.
+
+  nm="$compstate[nmatches]"
+
+  if [[ -z "$def" || "$def" = :* ]]; then
+
+    # We either don't have a description for an argument of an option
+    # or we have a description for a optional argument.
+
+    if [[ -z "$def" ]]; then
+
+      # If we have none at all, use the one for this argument position.
+
+      def="$args[nth]"
+      [[ -z "$def" ]] && def="$rest"
+    fi
+
+    # In any case, we have to complete option names here, but we may
+    # be in a string that starts with an option names and continues with
+    # the first argument, test that (again, four loops).
+
+    opt=yes
+    if (( $#dopts )); then
+
+      # Get the option names.
+
+      tmp=( "${(@k)dopts}" )
+      while (( $#tmp )); do
+        if compset -P "$tmp[1]"; then
+
+	  # The current string starts with the option name, so ignore
+	  # that and complete the rest of the string.
+
+	  def="$dopts[$tmp[1]]"
+	  opt=''
+	  break
+        fi
+	shift 1 tmp
+      done
+    fi
+    if [[ -n "$opt" && $#dmopts -ne 0 ]]; then
+      tmp=( "${(@k)dmopts}" )
+      while (( $#tmp )); do
+        if compset -P "$tmp[1]"; then
+	  def="$dmopts[$tmp[1]]"
+	  opt=''
+	  break
+        fi
+	shift 1 tmp
+      done
+    fi
+    if [[ -n "$opt" && $#odopts -ne 0 ]]; then
+      tmp=( "${(@k)odopts}" )
+      while (( $#tmp )); do
+        if compset -P "$tmp[1]"; then
+	  def="$odopts[$tmp[1]]"
+	  opt=''
+	  break
+        fi
+	shift 1 tmp
+      done
+    fi
+    if [[ -n "$opt" && $#odmopts -ne 0 ]]; then
+      tmp=( "${(@k)odmopts}" )
+      while (( $#tmp )); do
+        if compset -P "$tmp[1]"; then
+	  def="$odmopts[$tmp[1]]"
+	  opt=''
+	  break
+        fi
+	shift 1 tmp
+      done
+    fi
+    if [[ -n "$opt" ]]; then
+
+      # We aren't in an argument directly after a option name, so
+      # all option names are possible matches.
+
+      _description expl option
+      compadd "$expl[@]" - "${(@k)opts}" "${(@k)mopts}" \
+                           "${(@k)dopts}" "${(@k)dmopts}" \
+			   "${(@k)odopts}" "${(@k)odmopts}"
+    fi
+  fi
+
+  # Now add the matches from the description, if any.
+
+  if [[ -n "$def" ]]; then
+
+    # Ignore the leading colon describing optional arguments.
+
+    [[ "$def" = :* ]] && def="$def[2,-1]"
+
+    # Get the description and the action.
+
+    descr="${def%%:*}"
+    action="${${def#*:}%%:*}"
+
+    _description expl "$descr"
+
+    if [[ -z "$action" ]]; then
+
+      # An empty action means that we should just display a message.
+      _message "$descr"
+      return 1
+    elif [[ "$action[1]" = \( ]]; then
+
+      # Anything inside `(...)' is added directly.
+
+      compadd "$expl[@]" - ${=action[2,-2]}
+    elif [[ "$action" = \ * ]]; then
+
+      # If the action starts with a space, we just call it.
+
+      $=action
+    else
+
+      # Otherwise we call it with the description-arguments built above.
+
+      action=( $=action )
+      "$action[1]" "$expl[@]" "${(@)action[2,-1]}"
+    fi
+  fi
+
+  # Set the return value.
+
+  [[  nm -ne "$compstate[nmatches]" ]]
+fi
diff --git a/Completion/Base/_brace_parameter b/Completion/Base/_brace_parameter
index 9dfe46bd6..767743281 100644
--- a/Completion/Base/_brace_parameter
+++ b/Completion/Base/_brace_parameter
@@ -7,7 +7,8 @@ local lp ls n q suf=''
 if [[ "$SUFFIX" = *\}* ]]; then
   ISUFFIX="${SUFFIX#*\}}$ISUFFIX"
   SUFFIX="${SUFFIX%%\}*}"
-elif [[ "$LBUFFER" = *\$\{[^}]#\$\{[^}]#$PREFIX ]]; then
+elif [[ "$LBUFFER" = *\$\{[^}]#\$\{[^}]#$PREFIX ||
+        "$compstate[insert]" = *menu* ]]; then
   suf='}'
 else
   suf='} '
diff --git a/Completion/Base/_command_names b/Completion/Base/_command_names
index 61fea56dd..a0ec90262 100644
--- a/Completion/Base/_command_names
+++ b/Completion/Base/_command_names
@@ -1,18 +1,21 @@
 #compdef -command-
 
-local nm=$compstate[nmatches] ret=1
+local nm=$compstate[nmatches] ret=1 expl
 
 
 # Complete jobs in implicit fg and bg
 if [[ "$PREFIX[1]" = "%" ]]; then
-  compgen -j -P '%'
+  _description expl job
+  compgen "$expl[@]" -j -P '%'
   [[ nm -ne compstate[nmatches] ]] && return
 fi
 
-compgen -c && ret=0
+_description expl command
+compgen "$expl[@]" -c && ret=0
 
 if [[ nm -eq compstate[nmatches] ]]; then
-  _path_files -/g "*(*)"
+  _description expl 'executable file or directory'
+  _path_files "$expl[@]" -/g "*(*)"
 else
   return ret
 fi
diff --git a/Completion/Base/_condition b/Completion/Base/_condition
index c617d9d90..afac03195 100644
--- a/Completion/Base/_condition
+++ b/Completion/Base/_condition
@@ -7,10 +7,11 @@ if [[ "$prev" = -o ]]; then
 elif [[ "$prev" = -([no]t|ef) ]]; then
   _files
 else
-  local ret=1
+  local ret=1 expl
 
   _files && ret=0
-  compgen -v && ret=0
+  _description expl parameter
+  compgen "$expl[@]" -v && ret=0
 
   return ret
 fi
diff --git a/Completion/Base/_equal b/Completion/Base/_equal
index 0e2a11e46..14f28703c 100644
--- a/Completion/Base/_equal
+++ b/Completion/Base/_equal
@@ -1,3 +1,8 @@
 #compdef -equal-
 
-compgen -am
+local expl
+
+_description expl alias
+compgen "$expl[@]" -a
+_description expl command
+compgen "$expl[@]" -m
diff --git a/Completion/Base/_long_options b/Completion/Base/_long_options
index a50edee1c..f82de9ed5 100644
--- a/Completion/Base/_long_options
+++ b/Completion/Base/_long_options
@@ -9,9 +9,11 @@
 # For options that get an argument after a `=', the function also tries
 # to automatically find out what should be completed as the argument.
 # The possible completions for option-arguments can be described with
-# the arguments to this function. This is done by giving pairs of
-# patterns and actions as consecutive arguments. The actions specify
-# what should be done to complete arguments of those options that match 
+# the arguments to this function. Each argument contains one description
+# of the form <pattern>:<message>:<action>. The message will be printed 
+# above the possible completion if the `description_format' configuration
+# key is set (see the `_main_complete' file). The actions specify what
+# should be done to complete arguments of those options that match 
 # the pattern. The action may be a list of words in brackets or in
 # parentheses, separated by spaces. A list in brackets denotes
 # possible values for an optional argument, a list in parentheses
@@ -20,9 +22,9 @@
 # command (probably with arguments) that should be invoked to complete 
 # after the equal sign. E.g.:
 #
-#  _long_options '*\*'     '(yes no)' \
-#                '*=FILE*' '_files' \
-#                '*=DIR*'  '_files -/'
+#  _long_options '*\*:toggle:(yes no)' \
+#                '*=FILE*:file:_files' \
+#                '*=DIR*:directory:_files -/'
 #
 # This makes `yes' and `no' be completed as the argument of options
 # whose description ends in a star, file names for options that
@@ -46,23 +48,18 @@
 #      E.g. configure often lists only --enable but accepts both
 #      --enable and --disable options.
 #      _long_options -s '(#--enable- --disable)' will accept both forms.
-#
-# This function also accepts the `-X', `-J', and `-V' options which
-# are given to `compadd'. 
 
-local opt expl group test i name action ret=1 tmp suffix iopts sopts
+local opt test i name action descr expl ret=1 tmp suffix iopts sopts
 
 setopt extendedglob
 
 # Get the options.
 
-group=()
 expl=()
+
 if [[ $1 = -*~--* ]]; then
-  while getopts "J:V:X:ti:s:" opt; do
+  while getopts "ti:s:" opt; do
     case "$opt" in
-      [JV]) group=("-$opt" "$OPTARG");;
-      X)    expl=(-X "$OPTARG");;
       t)    test=yes;;
       i)    if [[ "$OPTARG[1]" = '(' ]]; then
               iopts=( ${=OPTARG[2,-2]} )
@@ -99,7 +96,7 @@ if [[ "$tmp" != $_lo_cache_cmd ]]; then
   # No, store the new command name and clear the old parameters.
 
   _lo_cache_cmd="$tmp"
-  (( $+_lo_cache_actions )) && unset "$_lo_cache_names[@]" _lo_cache_actions _lo_cache_names
+  (( $+_lo_cache_actions )) && unset "$_lo_cache_names[@]" _lo_cache_actions _lo_cache_names _lo_cache_descr
 
   local opts pattern anum=1 tmpo str
   typeset -U opts
@@ -136,16 +133,17 @@ if [[ "$tmp" != $_lo_cache_cmd ]]; then
   # use the positional parameters we were given and a few standard
   # ones. Then we loop through this table.
 
-  set -- "$@" '*=FILE*' '_files' '*=(DIR|PATH)*' '_files -/' '*' ''
+  set -- "$@" '*=FILE*:file:_files' '*=(DIR|PATH)*:directory:_files -/' '*:unknown:'
 
   while [[ $# -gt 1 ]]; do
 
     # First, we get the pattern and the action to use and take them
     # from the positional parameters.
 
-    pattern="$1"
-    action="$2"
-    shift 2
+    pattern="${1%%:*}"
+    descr="${${1#*:}%%:*}"
+    action="${1#*:*:}"
+    shift
 
     # We get all options matching the pattern and take them from the
     # list we have built. If no option matches the pattern, we
@@ -188,6 +186,7 @@ if [[ "$tmp" != $_lo_cache_cmd ]]; then
         tmpo=("${(@)${(@)tmpo%%\=*}//[^a-z0-9-]}")
         _lo_cache_names[anum]="_lo_cache_optarg_$anum"
         _lo_cache_actions[anum]="$action"
+	_lo_cache_descr[anum]="$descr"
         eval "_lo_cache_optarg_${anum}=(\"\$tmpo[@]\")"
 	(( anum++ ))
       fi
@@ -201,6 +200,7 @@ if [[ "$tmp" != $_lo_cache_cmd ]]; then
         tmpo=("${(@)${(@)tmpo%%\=*}//[^a-z0-9-]}")
         _lo_cache_names[anum]="_lo_cache_arg_$anum"
         _lo_cache_actions[anum]="$action"
+	_lo_cache_descr[anum]="$descr"
         eval "_lo_cache_arg_${anum}=(\"\$tmpo[@]\")"
 	(( anum++ ))
       fi
@@ -216,6 +216,7 @@ if [[ "$tmp" != $_lo_cache_cmd ]]; then
     if (( $#tmp )); then
       _lo_cache_names[anum]="$name"
       _lo_cache_actions[anum]="$action"
+      _lo_cache_descr[anum]="$descr"
       eval "${name}=(\"\$tmp[@]\")"
       (( anum++ ))
     fi
@@ -232,7 +233,7 @@ if [[ "$str" = *\=* ]]; then
   # It contains a `=', now we ignore anything up to it, but first save 
   # the old contents of the special parameters we change.
 
-  local oipre opre osuf pre parto parta pat patflags anum=1
+  local oipre opre osuf pre parto parta partd pat patflags anum=1
 
   oipre="$IPREFIX"
   opre="$PREFIX"
@@ -247,14 +248,23 @@ if [[ "$str" = *\=* ]]; then
 
   for name in "$_lo_cache_names[@]"; do
     action="$_lo_cache_actions[anum]"
+    descr="$_lo_cache_descr[anum]"
     if (( ${(@)${(@P)name}[(I)$pre]} )); then
       IPREFIX="${oipre}${pre}="
       PREFIX="${str#*\=}"
       SUFFIX=""
+
+      _description expl "$descr"
+
       if [[ "$action[1]" = (\[|\() ]]; then
-        compadd - ${=action[2,-2]}
+        compadd "$expl[@]" - ${=action[2,-2]}
       elif (( $#action )); then
-        $=action
+        if [[ "$action" = \ * ]]; then
+          $=action
+        else
+	  action=($=action)
+	  $action[1] "$expl[@]" $action[2,-1]
+        fi
       fi
 
       # We found the option string, return.
@@ -276,6 +286,7 @@ if [[ "$str" = *\=* ]]; then
       if [[ -z "$parto" ]]; then
         parto="$tmp[1]"
 	parta="$action"
+	partd="$descr"
       else
         parto=-
       fi
@@ -292,11 +303,17 @@ if [[ "$str" = *\=* ]]; then
     IPREFIX="${oipre}${parto}="
     PREFIX="${str#*\=}"
     SUFFIX=""
+
+    _description expl "$partd"
+
     if (( $#parta )); then
       if [[ "$parta[1]" = (\[|\() ]]; then
-        compadd - ${=parta[2,-2]}
-      else
+        compadd "$expl[@]" - ${=parta[2,-2]}
+      elif [[ "$parta" = \ * ]]; then
         $=parta
+      else
+	action=($=parta)
+	$action[1] "$expl[@]" $action[2,-1]
       fi
     else
       compadd -S '' - "$PREFIX"
@@ -329,15 +346,17 @@ anum=1
 for name in "$_lo_cache_names[@]"; do
   action="$_lo_cache_actions[anum]"
 
+  _description expl option
+
   if [[ "$name" = *_optarg_* ]]; then
-    compadd -M 'r:|-=* r:|=*' -Qq "$suffix[@]" -s "$str" - \
-            "${(@P)name}" && ret=0
+    compadd "$expl[@]" -M 'r:|-=* r:|=*' \
+            -Qq "$suffix[@]" -s "$str" - "${(@P)name}" && ret=0
   elif [[ "$name" = *_arg_* ]]; then
-    compadd -M 'r:|-=* r:|=*' -Q "$suffix[@]" -s "$str" - \
-            "${(@P)name}" && ret=0
+    compadd "$expl[@]" -M 'r:|-=* r:|=*' \
+            -Q "$suffix[@]" -s "$str" - "${(@P)name}" && ret=0
   elif [[ -z "$str" ]]; then
-    compadd -M 'r:|-=* r:|=*' -Q - \
-            "${(@P)name}" && ret=0
+    compadd "$expl[@]" -M 'r:|-=* r:|=*' - \
+            -Q "${(@P)name}" && ret=0
   fi
   (( anum++ ))
 done
diff --git a/Completion/Base/_math b/Completion/Base/_math
index 90a2c5f7b..82b97fe4a 100644
--- a/Completion/Base/_math
+++ b/Completion/Base/_math
@@ -1,5 +1,7 @@
 #compdef -math-
 
+local expl
+
 if [[ "$PREFIX" = *[^a-zA-Z0-9_]* ]]; then
   IPREFIX="$IPREFIX${PREFIX%%[a-zA-Z0-9_]#}"
   PREFIX="${PREFIX##*[^a-zA-Z0-9_]}"
@@ -9,10 +11,5 @@ if [[ "$SUFFIX" = *[^a-zA-Z0-9_]* ]]; then
   SUFFIX="${SUFFIX%%[^a-zA-Z0-9_]*}"
 fi
 
-compgen -v
-#compdef -math-
-
-IPREFIX="$IPREFIX${PREFIX%[a-zA-Z0-9_]*}"
-PREFIX="${PREFIX##*[^a-zA-Z0-9_]}"
-
-compgen -v
+_description expl parameter
+compgen "$expl[@]" -v
diff --git a/Completion/Base/_parameter b/Completion/Base/_parameter
index b235a5fee..5f6f56db2 100644
--- a/Completion/Base/_parameter
+++ b/Completion/Base/_parameter
@@ -1,3 +1,7 @@
 #compdef -parameter-
 
-_parameters -S ' ' -r '['
+if [[ "$compstate[insert]" = *menu* ]]; then
+  _parameters
+else
+  _parameters -S ' ' -r '['
+fi
diff --git a/Completion/Base/_subscript b/Completion/Base/_subscript
index be5f08f62..090a5f07a 100644
--- a/Completion/Base/_subscript
+++ b/Completion/Base/_subscript
@@ -1,17 +1,22 @@
 #compdef -subscript-
 
+local expl
+
 if [[ "$PREFIX" = :* ]]; then
+  _description expl 'character class'
   compadd -p: -S ':]' alnum alpha blank cntrl digit graph lower print punct \
       space upper xdigit
 elif [[ ${(Pt)${compstate[parameter]}} = assoc* ]]; then
+  _description expl 'association key'
   if [[ "$RBUFFER" = \]* ]]; then
-    compadd -S '' - "${(@kP)${compstate[parameter]}}"
+    compadd "$expl[@]" -S '' - "${(@kP)${compstate[parameter]}}"
   else
-    compadd -S ']' - "${(@kP)${compstate[parameter]}}"
+    compadd "$expl[@]" -S ']' - "${(@kP)${compstate[parameter]}}"
   fi
 elif [[ ${(Pt)${compstate[parameter]}} = array* ]]; then
   local list i j
 
+  _description expl 'array index'
   ind=( {1..${#${(P)${compstate[parameter]}}}} )
   list=()
   for i in "$ind[@]"; do
@@ -21,9 +26,9 @@ elif [[ ${(Pt)${compstate[parameter]}} = array* ]]; then
   done
 
   if [[ "$RBUFFER" = \]* ]]; then
-    compadd -S '' -V default -y list - "$ind[@]"
+    compadd "$expl[@]" -S '' -V default -y list - "$ind[@]"
   else
-    compadd -S ']' -V default -y list - "$ind[@]"
+    compadd "$expl[@]" -S ']' -V default -y list - "$ind[@]"
   fi
 else
   _compalso -math-
diff --git a/Completion/Base/_tilde b/Completion/Base/_tilde
index d03030821..f249d4ffa 100644
--- a/Completion/Base/_tilde
+++ b/Completion/Base/_tilde
@@ -7,7 +7,7 @@
 #   `(( compstate[nmatches] )) || compgen -nu -qS/'
 # below that.
 
-local c s dirs list
+local d c s dirs list
 
 if [[ "$SUFFIX" = */* ]]; then
   ISUFFIX="/${SUFFIX#*/}$ISUFFIX"
@@ -24,6 +24,8 @@ if compset -P +; then
   				        printf("%s\t%s\n", $1, $2); }' <<<$dirs)"
   list=("${(@)list%	*}")
   c=(-y '$dirs' -k "($list)")
+
+  _description d 'directory stack'
 elif compset -P -; then
   dirs="$(dirs -v)"
   list=("${(f)dirs}")
@@ -31,8 +33,16 @@ elif compset -P -; then
 					  printf("%s\t%s\n", $1, $2); }' <<<$dirs)"
   list=("${(@)list%	*}")
   c=(-y '$dirs' -k "($list)")
+
+  _description d 'directory stack'
 else
   c=(-nu)
+
+  if (( $# )); then
+    d=( "$@" )
+  else
+    _description d user
+  fi
 fi
 
-compgen "$c[@]" "$s[@]"
+compgen "$d[@]" "$c[@]" "$s[@]"
diff --git a/Completion/Base/_vars b/Completion/Base/_vars
index a40df7699..5a06488a5 100644
--- a/Completion/Base/_vars
+++ b/Completion/Base/_vars
@@ -4,17 +4,22 @@
 # `vared compconfig[<TAB>'.  However, in this version the [ must be
 # added by hand.
 
+local expl
+
 if [[ $PREFIX = *\[* ]]; then
   local var=${PREFIX%%\[*}
   local elt="${PREFIX#*\]}${SUFFIX%\]}"
   local addclose
+
   compset -p $(( ${#var} + 1 ))
   if ! compset -S \]; then
     addclose=(-S ']')
   fi
   if [[ ${(tP)var} = assoc* ]]; then
-    compadd $addclose - ${(kP)var}
+    _description expl 'association key'
+    compadd "$expl[@]" $addclose - ${(kP)var}
   fi
 else
-  compgen -v
+  _description expl parameter
+  compgen "$expl[@]" -v
 fi
diff --git a/Completion/Builtins/_aliases b/Completion/Builtins/_aliases
index 990f43457..3e4b789b6 100644
--- a/Completion/Builtins/_aliases
+++ b/Completion/Builtins/_aliases
@@ -1,3 +1,6 @@
 #compdef alias unalias
 
-compgen -a
+local expl
+
+_description expl alias
+compgen "$expl[@]" -a
diff --git a/Completion/Builtins/_arrays b/Completion/Builtins/_arrays
index b79bf711c..20681f527 100644
--- a/Completion/Builtins/_arrays
+++ b/Completion/Builtins/_arrays
@@ -1,3 +1,6 @@
 #compdef shift
 
-compgen -A
+local expl
+
+_description expl array
+compgen "$expl[@]" -A
diff --git a/Completion/Builtins/_autoload b/Completion/Builtins/_autoload
index f10fc34e7..4a97b2aec 100644
--- a/Completion/Builtins/_autoload
+++ b/Completion/Builtins/_autoload
@@ -1,3 +1,6 @@
 #compdef autoload
 
-compadd - ${^fpath}/*(N:t)
+local expl
+
+_description expl 'shell function'
+compadd "$expl[@]" - ${^fpath}/*(N:t)
diff --git a/Completion/Builtins/_bg_jobs b/Completion/Builtins/_bg_jobs
index ef1cd4d3c..65f21b483 100644
--- a/Completion/Builtins/_bg_jobs
+++ b/Completion/Builtins/_bg_jobs
@@ -1,3 +1,6 @@
 #compdef bg
 
-compgen -z -P '%'
+local expl
+
+_description expl 'suspended job'
+compgen "$expl[@]" -z -P '%'
diff --git a/Completion/Builtins/_bindkey b/Completion/Builtins/_bindkey
index 91ecfcc28..891e2cedb 100644
--- a/Completion/Builtins/_bindkey
+++ b/Completion/Builtins/_bindkey
@@ -7,8 +7,12 @@
 #
 # Where appropriate, will complete keymaps instead of widgets.
 
+local expl
+
 if [[ "$words[2]" = -*[DAN]* || "$words[CURRENT-1]" = -*M ]]; then
-  compadd - $(bindkey -l)
+  _description expl keymap
+  compadd "$expl[@]" - $(bindkey -l)
 else
-  compgen -b -M 'r:|-=* r:|=*'
+  _description expl widget
+  compgen "$expl[@]" -b -M 'r:|-=* r:|=*'
 fi
diff --git a/Completion/Builtins/_builtin b/Completion/Builtins/_builtin
index 0e6d613be..f925b88a8 100644
--- a/Completion/Builtins/_builtin
+++ b/Completion/Builtins/_builtin
@@ -5,5 +5,8 @@ if (( $CURRENT > 2 )); then
   (( CURRENT -- ))
   _normal
 else
-  compgen -eB
+  local expl
+
+  _description expl 'builtin command'
+  compgen "$expl[@]" -eB
 fi
diff --git a/Completion/Builtins/_cd b/Completion/Builtins/_cd
index 9ac29b8f8..92a14ec31 100644
--- a/Completion/Builtins/_cd
+++ b/Completion/Builtins/_cd
@@ -14,6 +14,8 @@
 emulate -L zsh
 setopt extendedglob nonomatch
 
+local expl
+
 if [[ CURRENT -eq 3 ]]; then
   # cd old new: look for old in $PWD and see what can replace it
   local rep
@@ -21,7 +23,8 @@ if [[ CURRENT -eq 3 ]]; then
   rep=(${~PWD/$words[2]/*}~$PWD(-/N))
   # Now remove all the common parts of $PWD and the completions from this
   rep=(${${rep#${PWD%%$words[2]*}}%${PWD#*$words[2]}})
-  (( ! $#rep )) || compadd $rep
+  _description expl replacement
+  (( ! $#rep )) || compadd "$expl[@]" $rep
 elif [[ $PREFIX = [-+]* ]]; then
   # pushd: just complete the numbers, but show the full directory list with
   # numbers.
@@ -50,7 +53,8 @@ elif [[ $PREFIX = [-+]* ]]; then
   lines="${(F)list}"
   # get the array of numbers only
   list=(${list%%[ 	]*})
-  compgen -y '$lines' -Q -k list && ret=0
+  _description expl 'directory stack index'
+  compgen "$expl[@]" -y '$lines' -Q -k list && ret=0
   [[ -z $compstate[list] ]] && compstate[list]=list && ret=0
   [[ -n $compstate[insert] ]] && compstate[insert]=menu && ret=0
 
diff --git a/Completion/Builtins/_command b/Completion/Builtins/_command
index 6103ee81f..4ae274f1f 100644
--- a/Completion/Builtins/_command
+++ b/Completion/Builtins/_command
@@ -4,5 +4,8 @@ if [[ CURRENT -ge 3 ]]; then
   compset -n 2
   _normal
 else
-  compgen -em
+  local expl
+
+  _description expl command
+  compgen "$expl[@]" -em
 fi
diff --git a/Completion/Builtins/_disable b/Completion/Builtins/_disable
index 5572fbcf3..b219f4b7e 100644
--- a/Completion/Builtins/_disable
+++ b/Completion/Builtins/_disable
@@ -1,10 +1,22 @@
 #compdef disable
 
-local prev="$words[CURRENT-1]" ret=1
+local prev="$words[CURRENT-1]" ret=1 expl
 
-[[ "$prev" = -*a* ]] && compgen -ea && ret=0
-[[ "$prev" = -*f* ]] && compgen -eF && ret=0
-[[ "$prev" = -*r* ]] && compgen -ew && ret=0
-[[ "$prev" != -* ]]  && compgen -eB && ret=0
+if [[ "$prev" = -*a* ]]; then
+  _description expl alias
+  compgen "$expl[@]" -ea && ret=0
+fi
+if [[ "$prev" = -*f* ]]; then
+  _description expl 'shell function'
+  compgen "$expl[@]" -eF && ret=0
+fi
+if [[ "$prev" = -*r* ]]; then
+  _description expl 'reserved word'
+  compgen "$expl[@]" -ew && ret=0
+fi
+if [[ "$prev" != -* ]]; then
+  _description expl 'builtin command'
+  compgen "$expl[@]" -eB && ret=0
+fi
 
 return ret
diff --git a/Completion/Builtins/_echotc b/Completion/Builtins/_echotc
index 15dfcef08..46bf38261 100644
--- a/Completion/Builtins/_echotc
+++ b/Completion/Builtins/_echotc
@@ -1,3 +1,7 @@
 #compdef echotc
 
-compadd al dc dl do le up al bl cd ce cl cr dc dl do ho is le ma nd nl se so up
+local expl
+
+_description expl 'terminal capability'
+compadd "$expl[@]" \
+        al dc dl do le up al bl cd ce cl cr dc dl do ho is le ma nd nl se so up
diff --git a/Completion/Builtins/_enable b/Completion/Builtins/_enable
index 483661efe..a698a3895 100644
--- a/Completion/Builtins/_enable
+++ b/Completion/Builtins/_enable
@@ -1,10 +1,22 @@
 #compdef enable
 
-local prev="$words[CURRENT-1]" ret=1
+local prev="$words[CURRENT-1]" ret=1 expl
 
-[[ "$prev" = -*a* ]] && compgen -da && ret=0
-[[ "$prev" = -*f* ]] && compgen -dF && ret=0
-[[ "$prev" = -*r* ]] && compgen -dw && ret=0
-[[ "$prev" != -* ]]  && compgen -dB && ret=0
+if [[ "$prev" = -*a* ]]; then
+  _description expl alias
+  compgen "$expl[@]" -da && ret=0
+fi
+if [[ "$prev" = -*f* ]]; then
+  _description expl 'shell function'
+  compgen "$expl[@]" -dF && ret=0
+fi
+if [[ "$prev" = -*r* ]]; then
+  _description expl 'reserved word'
+  compgen "$expl[@]" -dw && ret=0
+fi
+if [[ "$prev" != -* ]]; then
+  _description expl 'builtin command'
+  compgen "$expl[@]" -dB && ret=0
+fi
 
 return ret
diff --git a/Completion/Builtins/_fc b/Completion/Builtins/_fc
index 5b493dc3b..8d5c82763 100644
--- a/Completion/Builtins/_fc
+++ b/Completion/Builtins/_fc
@@ -1,9 +1,10 @@
 #compdef fc
 
-local prev="$words[CURRENT-1]"
+local prev="$words[CURRENT-1]" expl
 
 if [[ "$prev" = -*e ]]; then
-  compgen -c
+  _description expl command
+  compgen "$expl[@]" -c
 elif [[ "$prev" = -[ARWI]## ]]; then
   _files
 fi
diff --git a/Completion/Builtins/_functions b/Completion/Builtins/_functions
index 52c37952b..7aa30b7bc 100644
--- a/Completion/Builtins/_functions
+++ b/Completion/Builtins/_functions
@@ -1,3 +1,6 @@
 #compdef functions unfunction
 
-compgen -F
+local expl
+
+_description expl 'shell function'
+compgen "$expl[@]" -F
diff --git a/Completion/Builtins/_hash b/Completion/Builtins/_hash
index b03cf7fb9..c8169c590 100644
--- a/Completion/Builtins/_hash
+++ b/Completion/Builtins/_hash
@@ -1,13 +1,17 @@
 #compdef hash
 
+local expl
+
 if [[ "$words[2]" = -*d* ]]; then
   if compset -P 1 '*\='; then
     _path_files -g '*(-/)'
   else
-    compgen -n -q -S '='
+    _description expl 'named directory'
+    compgen "$expl[@]" -n -q -S '='
   fi
 elif compset -P 1 '*\='; then
   _files -/g '*(*)'
 else
-  compgen -m -q -S '='
+  _description expl command
+  compgen "$expl[@]" -m -q -S '='
 fi
diff --git a/Completion/Builtins/_jobs b/Completion/Builtins/_jobs
index 9e2da24c6..b1ff31b4a 100644
--- a/Completion/Builtins/_jobs
+++ b/Completion/Builtins/_jobs
@@ -1,3 +1,6 @@
 #compdef disown fg jobs
 
-compgen -j -P '%'
+local expl
+
+_description expl job
+compgen "$expl[@]" -j -P '%'
diff --git a/Completion/Builtins/_kill b/Completion/Builtins/_kill
index 26f6bf5cd..264253e0a 100644
--- a/Completion/Builtins/_kill
+++ b/Completion/Builtins/_kill
@@ -1,15 +1,18 @@
 #compdef kill
 
-local list
+local list expl
 
 if compset -P 1 -; then
-  compadd $signals[1,-3]
+  _description expl signal
+  compadd "$expl[@]" $signals[1,-3]
 else
   local ret=1
 
-  compgen -P '%' -j && ret=0
+  _description expl job
+  compgen "$expl[@]" -P '%' -j && ret=0
   list=("${(@Mr:COLUMNS-1:)${(f)$(ps ${compconfig[ps_listargs]:-$compconfig[ps_args]} 2>/dev/null)}[2,-1]:#[ 	]#${PREFIX}[0-9]#${SUFFIX}[ 	]*}")
-  compadd -y list - ${${${(f)"$(ps $compconfig[ps_args] 2>/dev/null)"}[2,-1]## #}%% *} &&
+  _description expl 'process ID'
+  compadd "$expl[@]" -y list - ${${${(f)"$(ps $compconfig[ps_args] 2>/dev/null)"}[2,-1]## #}%% *} &&
     ret=0
 
   return ret
diff --git a/Completion/Builtins/_limits b/Completion/Builtins/_limits
index 0b8837d67..0072438c3 100644
--- a/Completion/Builtins/_limits
+++ b/Completion/Builtins/_limits
@@ -1,3 +1,6 @@
 #compdef limit unlimit
 
-compadd ${${(f)"$(limit)"}%% *}
+local expl
+
+_description expl 'process limits'
+compadd "$expl[@]" ${${(f)"$(limit)"}%% *}
diff --git a/Completion/Builtins/_sched b/Completion/Builtins/_sched
index 581438b0e..83aa744ce 100644
--- a/Completion/Builtins/_sched
+++ b/Completion/Builtins/_sched
@@ -1,3 +1,7 @@
 #compdef sched
 
+if [[ CURRENT -eq 2 ]]; then
+  _message 'time specification'
+  return 1
+fi
 compset -n 3 && _normal
diff --git a/Completion/Builtins/_set b/Completion/Builtins/_set
index 59a38b654..297a15d3b 100644
--- a/Completion/Builtins/_set
+++ b/Completion/Builtins/_set
@@ -1,9 +1,11 @@
 #compdef set
 
-local prev="$words[CURRENT-1]"
+local prev="$words[CURRENT-1]" expl
 
 if [[ "$prev" = [-+]o ]]; then
-  compgen -o
+  _description expl 'zsh option'
+  compgen "$expl[@]" -o
 elif [[ "$prev" = -A ]]; then
-  compgen -A
+  _description expl array
+  compgen "$expl[@]" -A
 fi
diff --git a/Completion/Builtins/_stat b/Completion/Builtins/_stat
index 3cdbb2618..5a39e56e5 100644
--- a/Completion/Builtins/_stat
+++ b/Completion/Builtins/_stat
@@ -1,10 +1,14 @@
 #compdef stat
 
+local expl
+
 if [[ "$words[CURRENT-1]" = -[AH] ]]; then
-  compgen -A
+  _description expl array
+  compgen "$expl[@]" -A
 else
+  _description expl 'inode element'
   [[ "$PREFIX[1]" = + ]] &&
-      compadd - +device +inode +mode +nlink +uid +gid +rdev +size \
-                +atime +mtime +ctime +blksize +block +link
+      compadd "$expl[@]" - +device +inode +mode +nlink +uid +gid +rdev +size \
+                           +atime +mtime +ctime +blksize +block +link
   _files
 fi
diff --git a/Completion/Builtins/_trap b/Completion/Builtins/_trap
index bb0630638..d6fc7b388 100644
--- a/Completion/Builtins/_trap
+++ b/Completion/Builtins/_trap
@@ -1,7 +1,11 @@
 #compdef trap
 
+local expl
+
 if [[ CURRENT -eq 2 ]]; then
-  compgen -c
+  _description expl command
+  compgen "$expl[@]" -c
 else
-  compgen -k signals
+  _description expl signal
+  compgen "$expl[@]" -k signals
 fi
diff --git a/Completion/Builtins/_unhash b/Completion/Builtins/_unhash
index 825c130b2..eb1787936 100644
--- a/Completion/Builtins/_unhash
+++ b/Completion/Builtins/_unhash
@@ -1,10 +1,22 @@
 #compdef unhash
 
-local fl="$words[2]" ret=1
+local fl="$words[2]" ret=1 expl
 
-[[ "$fl" = -*d* ]] && compgen -n && ret=0
-[[ "$fl" = -*a* ]] && compgen -a && ret=0
-[[ "$fl" = -*f* ]] && compgen -F && ret=0
-[[ "$fl" != -* ]]  && compgen -m && ret=0
+if [[ "$fl" = -*d* ]]; then
+  _description expl 'named directory'
+  compgen "$expl[@]" -n && ret=0
+fi
+if [[ "$fl" = -*a* ]]; then
+  _description expl alias
+  compgen "$expl[@]" -a && ret=0
+fi
+if [[ "$fl" = -*f* ]]; then
+  _description expl 'shell function'
+  compgen "$expl[@]" -F && ret=0
+fi
+if [[ "$fl" != -* ]]; then
+  _description expl command
+  compgen "$expl[@]" -m && ret=0
+fi
 
 return ret
diff --git a/Completion/Builtins/_vars_eq b/Completion/Builtins/_vars_eq
index 892c1f57e..16a55595e 100644
--- a/Completion/Builtins/_vars_eq
+++ b/Completion/Builtins/_vars_eq
@@ -1,3 +1,6 @@
 #compdef declare export integer local readonly typeset
 
-compgen -v -q -S '='
+local expl
+
+_description expl parameter
+compgen "$expl[@]" -v -q -S '='
diff --git a/Completion/Builtins/_wait b/Completion/Builtins/_wait
index 8f9339ebd..bcd39963f 100644
--- a/Completion/Builtins/_wait
+++ b/Completion/Builtins/_wait
@@ -11,10 +11,12 @@
 #    options for the ps command that are to be used when creating
 #    the list to display during completion.
 
-local list ret=1
+local list ret=1 expl
 
-compgen -P '%' -j && ret=0
+_description expl job
+compgen "$expl[@]" -P '%' -j && ret=0
 list=("${(@Mr:COLUMNS-1:)${(f)$(ps ${compconfig[ps_listargs]:-$compconfig[ps_args]} 2>/dev/null)}[2,-1]:#[ 	]#${PREFIX}[0-9]#${SUFFIX}[ 	]*}")
-compadd -y list - ${${${(f)"$(ps $compconfig[ps_args] 2>/dev/null)"}[2,-1]## #}%% *} && ret=0
+_description expl 'process ID'
+compadd "$expl[@]" -y list - ${${${(f)"$(ps $compconfig[ps_args] 2>/dev/null)"}[2,-1]## #}%% *} && ret=0
 
 return ret
diff --git a/Completion/Builtins/_which b/Completion/Builtins/_which
index db5271653..d67af7316 100644
--- a/Completion/Builtins/_which
+++ b/Completion/Builtins/_which
@@ -1,3 +1,10 @@
 #compdef which whence where type
 
-compgen -caF
+local expl
+
+_description expl command
+compgen "$expl[@]" -c
+_description expl alias
+compgen "$expl[@]" -a
+_description expl 'shell function'
+compgen "$expl[@]" -F
diff --git a/Completion/Builtins/_zftp b/Completion/Builtins/_zftp
index 32d32c2b7..e6f7ea683 100644
--- a/Completion/Builtins/_zftp
+++ b/Completion/Builtins/_zftp
@@ -7,11 +7,12 @@ _compskip=all
 # zfcd_match and zfget_match (used for old-style completion)
 # need to be installed for remote file and directory completion to work.
 
-local subcom
+local subcom expl
 
 if [[ $words[1] = zftp ]]; then
   if [[ $CURRENT -eq 2 ]]; then
-    compadd open params user login type ascii binary mode put \
+    _description expl sub-command
+    compadd "$expl[@]" open params user login type ascii binary mode put \
       putat get getat append appendat ls dir local remote mkdir rmdir
     return
   fi
@@ -24,13 +25,15 @@ case $subcom in
   *(cd|ls|dir))
    # complete remote directories; we could be smarter about hiding prefixes
    zfcd_match $PREFIX $SUFFIX
-   (( $#reply )) && compadd -S/ -q - $reply
+   _description expl 'remote directory'
+   (( $#reply )) && compadd "$expl[@]" -S/ -q - $reply
    ;;
 
   *(get(|at)|gcp|delete|remote))
    # complete remote files
    zfget_match $PREFIX $SUFFIX
-   (( $#reply )) && compadd -F fignore - $reply
+   _description expl 'remote file'
+   (( $#reply )) && compadd "$expl[@]" -F fignore - $reply
    ;;
 
   *(put(|at)|pcp))
@@ -40,18 +43,20 @@ case $subcom in
 
   *(open|anon|params))
   # complete hosts:  should do cleverer stuff with user names
-  compgen -k hosts
+  _description expl host
+  compgen "$expl[@]" -k hosts
   ;;
 
   *(goto|mark))
   # complete bookmarks.  First decide if ncftp mode is go.
+  _description expl bookmark
   if [[ $words[2] = -*n* ]]; then
     if [[ -f ~/.ncftp/bookmarks ]]; then
-      compadd - $(awk -F, 'NR > 2 { print $1 }' ~/.ncftp/bookmarks)
+      compadd "$expl[@]" - $(awk -F, 'NR > 2 { print $1 }' ~/.ncftp/bookmarks)
     fi
   else
     if [[ -f ${ZFTP_BMFILE:=${ZDOTDIR:-$HOME}/.zfbkmarks} ]]; then
-      compadd - $(awk '{print $1}' $ZFTP_BMFILE)
+      compadd "$expl[@]" - $(awk '{print $1}' $ZFTP_BMFILE)
     fi
   fi
   ;;
diff --git a/Completion/Builtins/_zle b/Completion/Builtins/_zle
index f0860c5e3..06e8fcad3 100644
--- a/Completion/Builtins/_zle
+++ b/Completion/Builtins/_zle
@@ -1,7 +1,11 @@
 #compdef zle
 
+local expl
+
 if [[ "$words[2]" = -N && CURRENT -eq 3 ]]; then
-  compgen -F
+  _description expl 'widget shell function'
+  compgen "$expl[@]" -F
 else
-  compgen -b
+  _description expl widget
+  compgen "$expl[@]" -b
 fi
diff --git a/Completion/Builtins/_zmodload b/Completion/Builtins/_zmodload
index d3a39b5de..9bac1484e 100644
--- a/Completion/Builtins/_zmodload
+++ b/Completion/Builtins/_zmodload
@@ -1,11 +1,14 @@
 #compdef zmodload
 
-local fl="$words[2]"
+local fl="$words[2]" expl
 
 if [[ "$fl" = -*(a*u|u*a)* || "$fl" = -*a* && CURRENT -ge 4 ]]; then
-  compgen -B
+  _description expl 'builtin command'
+  compgen "$expl[@]" -B
 elif [[ "$fl" = -*u* ]]; then
+  _description expl module
   compadd - $(zmodload)
 else
+  _description expl 'module file'
   compadd - ${^module_path}/*(N:t:r)
 fi
diff --git a/Completion/Commands/_history_complete_word b/Completion/Commands/_history_complete_word
index 8e99aec17..fb1c502c8 100644
--- a/Completion/Commands/_history_complete_word
+++ b/Completion/Commands/_history_complete_word
@@ -1,2 +1,6 @@
 #compdef -kn complete-word \e/
-compgen -Q -H 0 ''
+
+local expl
+
+_description expl 'history word'
+compgen "$expl[@]" -Q -H 0 ''
diff --git a/Completion/Core/_description b/Completion/Core/_description
new file mode 100644
index 000000000..874ba8a96
--- /dev/null
+++ b/Completion/Core/_description
@@ -0,0 +1,22 @@
+#autoload
+
+local gropt=-J
+
+if [[ "$1" = -V ]]; then
+  gropt=-V
+  shift
+fi
+
+if [[ -n "$compconfig[group_matches]" ]]; then
+  if [[ -n "$compconfig[description_format]" ]]; then
+    eval "$1=($gropt ${(q)2} -X ${(q)compconfig[description_format]//\\%d/$2})"
+  else
+    eval "$1=($gropt ${(q)2})"
+  fi
+else
+  if [[ -n "$compconfig[description_format]" ]]; then
+    eval "$1=(-X ${(q)compconfig[description_format]//\\%d/$2})"
+  else
+    eval "$1=()"
+  fi
+fi
diff --git a/Completion/Core/_main_complete b/Completion/Core/_main_complete
index 4ac45d2cc..6e84818ee 100644
--- a/Completion/Core/_main_complete
+++ b/Completion/Core/_main_complete
@@ -22,6 +22,24 @@
 #  last_prompt
 #    If this is set to `always' the cursor is moved up to the last prompt
 #    after printing a list even if a numeric argument was given.
+#
+#
+# Also, most completion functions use the configuration keys:
+#
+#  description_format
+#    If this is set to a non-empty string, it will be displayed above
+#    all matches generated. The sequence `%d' in this string is replaced
+#    by a short description of what is completed in the current position
+#    of the command line.
+#
+#  message_format
+#    Like `description_format', but used in places where no completions
+#    can automatically be generated but the completion system still wants
+#    to give a hint what is expected in that position.
+#
+#  group_matches
+#    If this is set to a non-empty string, different types of matches will
+#    be put in different groups.
 
 
 # If you want to complete only set or unset options for the unsetopt
diff --git a/Completion/Core/_message b/Completion/Core/_message
new file mode 100644
index 000000000..0837cdf2f
--- /dev/null
+++ b/Completion/Core/_message
@@ -0,0 +1,19 @@
+#autoload
+
+local format
+
+format="$compconfig[message_format]"
+[[ -z "$format" ]] && "$compconfig[description_format]"
+
+if [[ -n "$format" ]]; then
+  if [[ $compstate[nmatches] -eq 0 ]]; then
+    compstate[list]=list
+    compstate[insert]=''
+    compadd -UX "${format//\\%d/$1}" -n ''
+  else
+    compadd -X "${format//\\%d/$1}" -n ''
+  fi
+  compstate[force_list]=yes
+else
+  compadd -n ''
+fi
diff --git a/Completion/Core/_normal b/Completion/Core/_normal
index d4e948e41..ffacc8f04 100644
--- a/Completion/Core/_normal
+++ b/Completion/Core/_normal
@@ -29,13 +29,15 @@ fi
 
 # See if there are any matching pattern completions.
 
-if [[ "$_compskip" != *patterns* ]]; then
+if [[ "$_compskip" != (all|*patterns*) ]]; then
   for i in "$_patcomps[@]"; do
     pat="${i% *}"
     val="${i#* }"
     if [[ "$cmd1" == $~pat || "$cmd2" == $~pat ]]; then
       "$val" && ret=0
-      if [[ "$_compskip" = *patterns* || "$_compskip" = all ]]; then
+      if [[ "$_compskip" = *patterns* ]]; then
+        break
+      elif [[ "$_compskip" = all ]]; then
         unset _compskip
         return ret
       fi
@@ -55,15 +57,36 @@ fi
 
 # And generate the matches, probably using default completion.
 
-if [[ -z "$comp" ]]; then
-  if [[ "$_compskip" = *default* ]]; then
-    unset _compskip
-    return 1
+if [[ -n "$comp" ]]; then
+  _compskip=patterns
+  "$comp" && ret=0
+  [[ "$_compskip" = (all|*patterns*) ]] && return ret
+else
+  if [[ "$_compskip" != *default* ]]; then
+    name=-default-
+    comp="$_comps[-default-]"
   fi
-  name=-default-
-  comp="$_comps[-default-]"
 fi
-[[ -z "$comp" ]] || "$comp" && ret=0
+  
+if [[ "$_compskip" != (all|*patterns*) ]]; then
+  for i in "$_postpatcomps[@]"; do
+    pat="${i% *}"
+    val="${i#* }"
+    if [[ "$cmd1" == $~pat || "$cmd2" == $~pat ]]; then
+      _compskip=default
+      "$val" && ret=0
+      if [[ "$_compskip" = *patterns* ]]; then
+	break
+      elif [[ "$_compskip" = all ]]; then
+        unset _compskip
+        return ret
+      fi
+    fi
+  done
+fi
+
+[[ "$name" = -default- && -n "$comp" && "$_compskip" != (all|*default*) ]] &&
+  "$comp" && ret=0
 
 unset _compskip
 
diff --git a/Completion/Core/_options b/Completion/Core/_options
index 0a852e6ce..356cd70db 100644
--- a/Completion/Core/_options
+++ b/Completion/Core/_options
@@ -2,4 +2,7 @@
 
 # This should be used to complete all option names.
 
-compgen "$@" -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o
+local expl
+
+_description expl 'zsh option'
+compgen "$expl[@]" "$@" -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o
diff --git a/Completion/Core/_parameters b/Completion/Core/_parameters
index a579e5ead..824d8dbc9 100644
--- a/Completion/Core/_parameters
+++ b/Completion/Core/_parameters
@@ -4,9 +4,13 @@
 # extra options of compadd. It completes only non-local parameters. All
 # arguments are given to compadd.
 
+local expl
+
+_description expl parameter
+
 if zmodload -e parameter; then
   setopt localoptions extendedglob
-  compadd "$@" - ${(k)parameters[(R)^*local*]}
+  compadd "$expl[@]" "$@" - ${(k)parameters[(R)^*local*]}
 else
-  compadd "$@" - ${${${(f)"$(typeset +)"}:#*local *}##* }
+  compadd "$expl[@]" "$@" - ${${${(f)"$(typeset +)"}:#*local *}##* }
 fi
diff --git a/Completion/Core/_path_files b/Completion/Core/_path_files
index 9494d5a4a..9aebc89d0 100644
--- a/Completion/Core/_path_files
+++ b/Completion/Core/_path_files
@@ -91,6 +91,14 @@ while getopts "P:S:qr:R:W:F:J:V:X:f/g:" opt; do
   esac
 done
 
+if (( ! ( $#group + $#expl ) )); then
+  if [[ "$sopt" = -/ ]]; then
+    _description expl directory
+  else
+    _description expl file
+  fi
+fi
+
 [[ -n "$tmp1" && $#addsfx -ne 0 ]] && addsfx[1]=-qS
 
 # If we were given no file selection option, we behave as if we were given
diff --git a/Completion/Core/_set_options b/Completion/Core/_set_options
index 5f634a2cd..947afdeae 100644
--- a/Completion/Core/_set_options
+++ b/Completion/Core/_set_options
@@ -4,4 +4,7 @@
 # names of the options that were set when it was called in the array
 # `_set_options'.
 
-compadd "$@" -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' - $=_set_options
+local expl
+
+_description expl 'set zsh option'
+compadd "$expl[@]" "$@" -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' - $=_set_options
diff --git a/Completion/Core/_unset_options b/Completion/Core/_unset_options
index c5150c2e5..f6a1c58f0 100644
--- a/Completion/Core/_unset_options
+++ b/Completion/Core/_unset_options
@@ -4,4 +4,7 @@
 # names of the options that were set when it was called in the array
 # `_set_options'.
 
-compadd "$@" -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' - $=_unset_options
+local expl
+
+_description expl 'unset zsh option'
+compadd "$expl[@]" "$@" -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' - $=_unset_options
diff --git a/Completion/Core/compdump b/Completion/Core/compdump
index 8f8a3ee77..b4530ea8e 100644
--- a/Completion/Core/compdump
+++ b/Completion/Core/compdump
@@ -39,6 +39,12 @@ for _d_f in "$_patcomps[@]"; do
 done >> $_d_file
 print ")" >> $_d_file
 
+print "\n_postpatcomps=(" >> $_d_file
+for _d_f in "$_postpatcomps[@]"; do
+  print -r - "'${_d_f//\'/'\\''}'"
+done >> $_d_file
+print ")" >> $_d_file
+
 print >> $_d_file
 
 # Now dump the key bindings. We dump all bindings for zle widgets
diff --git a/Completion/Core/compinit b/Completion/Core/compinit
index 808c20f5b..f160e7dcf 100644
--- a/Completion/Core/compinit
+++ b/Completion/Core/compinit
@@ -68,10 +68,12 @@ while [[ $# -gt 0 && $1 = -[dDf] ]]; do
 done
 
 # The associative array containing the definitions for the commands.
-# Definitions for patterns will be stored in the normal array `_patcomps'.
+# Definitions for patterns will be stored in the normal arrays `_patcomps'
+# and `_postpatcomps'.
 
 typeset -gA _comps
 _patcomps=()
+_postpatcomps=()
 
 # The associative array use to report information about the last
 # cmpletion to the outside.
@@ -106,6 +108,9 @@ fi
 # function will be invoked when completing for a command whose name 
 # matches the pattern given as argument after the function name (in this
 # case only one argument is accepted).
+# The option `-P' is like `-p', but the function will be called after
+# trying to find a function defined for the command on the line if no
+# such function could be found.
 # With the `-k' option a function for a special completion keys is 
 # defined and immediatly bound to those keys. Here, the extra arguments
 # are the name of one of the builtin completion widgets and any number
@@ -147,11 +152,11 @@ compdef() {
 
   # Get the options.
 
-  while getopts "anpkd" opt; do
+  while getopts "anpPkd" opt; do
     case "$opt" in
     a)    autol=yes;;
     n)    new=yes;;
-    [pk]) if [[ -n "$type" ]]; then
+    [pPk]) if [[ -n "$type" ]]; then
             # Error if both `-p' and `-k' are given (or one of them
 	    # twice).
             echo "$0: type already set to $type"
@@ -159,6 +164,8 @@ compdef() {
 	  fi
 	  if [[ "$opt" = p ]]; then
 	    type=pattern
+	  elif [[ "$opt" = P ]]; then
+	    type=postpattern
 	  else
 	    type=key
 	  fi
@@ -187,6 +194,13 @@ compdef() {
 
       _patcomps=("$_patcomps[@]" "$1 $func")
       ;;
+    postpattern)
+      if [[ $# -gt 1 ]]; then
+        echo "$0: only one pattern allowed"
+	return 1
+      fi
+      _postpatcomps=("$_postpatcomps[@]" "$1 $func")
+      ;;
     key)
       if [[ $# -lt 2 ]]; then
         echo "$0: missing keys"
@@ -230,7 +244,12 @@ compdef() {
     pattern)
       # Note the space.
       for i; do
-        _patcomps=("${(@)patcomps:#$i *}")
+        _patcomps=("${(@)_patcomps:#$i *}")
+      done
+      ;;
+    postpattern)
+      for i; do
+        _postpatcomps=("${(@)_postpatcomps:#$i *}")
       done
       ;;
     key)
@@ -359,7 +378,7 @@ if [[ -z "$_i_done" ]]; then
       shift _i_line
       case $_i_tag in
       (\#compdef)
-	if [[ $_i_line[1] = -[pk](n|) ]]; then
+	if [[ $_i_line[1] = -[pPk](n|) ]]; then
 	  compdef ${_i_line[1]}a "${_i_file:t}" "${(@)_i_line[2,-1]}"
 	else
 	  compdef -na "${_i_file:t}" "${_i_line[@]}"
diff --git a/Completion/Pbmplus/_asciitopnm b/Completion/Pbmplus/_asciitopnm
new file mode 100644
index 000000000..70f95692c
--- /dev/null
+++ b/Completion/Pbmplus/_asciitopnm
@@ -0,0 +1,3 @@
+#compdef asciitopnm
+
+_arguments '-d:divisor:' ':height:' ':width:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_fitstopgm b/Completion/Pbmplus/_fitstopgm
new file mode 100644
index 000000000..de19bd9ea
--- /dev/null
+++ b/Completion/Pbmplus/_fitstopgm
@@ -0,0 +1,3 @@
+#compdef fitstopgm
+
+_arguments '-image:image number:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_fitstopnm b/Completion/Pbmplus/_fitstopnm
new file mode 100644
index 000000000..6dcd56134
--- /dev/null
+++ b/Completion/Pbmplus/_fitstopnm
@@ -0,0 +1,4 @@
+#compdef fitstopnm
+
+_arguments '-image:image number:' '-noraw' '-scanmax' '-printmax' \
+           '-min:minimum value:' '-max:maximum value:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_g3topbm b/Completion/Pbmplus/_g3topbm
new file mode 100644
index 000000000..c6cfa34fe
--- /dev/null
+++ b/Completion/Pbmplus/_g3topbm
@@ -0,0 +1,3 @@
+#compdef g3topbm
+
+_arguments '-kludge' '-reversebits' '-stretch' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_giftopnm b/Completion/Pbmplus/_giftopnm
new file mode 100644
index 000000000..1a3e6e1c3
--- /dev/null
+++ b/Completion/Pbmplus/_giftopnm
@@ -0,0 +1,4 @@
+#compdef giftopnm
+
+_arguments '-verbose' '-comments' '-image:image number:' \
+           ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_macptopbm b/Completion/Pbmplus/_macptopbm
new file mode 100644
index 000000000..ffcd280ad
--- /dev/null
+++ b/Completion/Pbmplus/_macptopbm
@@ -0,0 +1,3 @@
+#compdef macptopbm
+
+_arguments '-extraskip:number of bytes to skip:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pbm_file b/Completion/Pbmplus/_pbm_file
new file mode 100644
index 000000000..6f96d9460
--- /dev/null
+++ b/Completion/Pbmplus/_pbm_file
@@ -0,0 +1,20 @@
+#compdef -P (p[bgpn]m*|*top[bgpn]m)
+
+local expl
+
+if [[ "$words[1]" = pnm* ]]; then
+  pat='*.(#i)p[bgp]m'
+elif [[ "$words[1]" = *top[bgpn]m ]]; then
+  pat="*.(#i)${words[1]%%top[bgpn]m}"
+else
+  pat="*.(#i)${words[1][1,3]}"
+fi
+
+if (( $# )); then
+  expl=( "$@" )
+else
+  _description expl 'picture file'
+fi
+
+_path_files "$expl[@]" -g "$pat" ||
+    _files "$expl[@]" -g '*.(#i)p[bgp]m'
diff --git a/Completion/Pbmplus/_pbmclean b/Completion/Pbmplus/_pbmclean
new file mode 100644
index 000000000..8b265cb29
--- /dev/null
+++ b/Completion/Pbmplus/_pbmclean
@@ -0,0 +1,3 @@
+#compdef pbmclean
+
+_arguments '-connect' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pbmmake b/Completion/Pbmplus/_pbmmake
new file mode 100644
index 000000000..ffb437a5e
--- /dev/null
+++ b/Completion/Pbmplus/_pbmmake
@@ -0,0 +1,3 @@
+#compdef pbmmake
+
+_arguments '-white' '-black' '-gray' ':width:' ':height:'
diff --git a/Completion/Pbmplus/_pbmmask b/Completion/Pbmplus/_pbmmask
new file mode 100644
index 000000000..2207ce772
--- /dev/null
+++ b/Completion/Pbmplus/_pbmmask
@@ -0,0 +1,3 @@
+#compdef pbmmask
+
+_arguments '-expand' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pbmpscale b/Completion/Pbmplus/_pbmpscale
new file mode 100644
index 000000000..76c00b247
--- /dev/null
+++ b/Completion/Pbmplus/_pbmpscale
@@ -0,0 +1,3 @@
+#compdef pbmpscale
+
+_arguments ':scale factor:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pbmreduce b/Completion/Pbmplus/_pbmreduce
new file mode 100644
index 000000000..8a32e6a88
--- /dev/null
+++ b/Completion/Pbmplus/_pbmreduce
@@ -0,0 +1,4 @@
+#compdef pbmreduce
+
+_arguments '-floyd' '-fs' '-threshold' '-value:threshold value:' \
+           ':reduction factor:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pbmtext b/Completion/Pbmplus/_pbmtext
new file mode 100644
index 000000000..1ef1fd9f1
--- /dev/null
+++ b/Completion/Pbmplus/_pbmtext
@@ -0,0 +1,3 @@
+#compdef pbmtext
+
+_arguments '-font:font file:_files -g *.(#i)pbm' '*:text:'
diff --git a/Completion/Pbmplus/_pbmto10x b/Completion/Pbmplus/_pbmto10x
new file mode 100644
index 000000000..ce233e5ae
--- /dev/null
+++ b/Completion/Pbmplus/_pbmto10x
@@ -0,0 +1,3 @@
+#compdef pbmto10x
+
+_arguments '-h' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pbmtobg b/Completion/Pbmplus/_pbmtobg
new file mode 100644
index 000000000..729332745
--- /dev/null
+++ b/Completion/Pbmplus/_pbmtobg
@@ -0,0 +1,3 @@
+#compdef pbmtobg pbmtobbnbg
+
+_arguments ':raster operation:' ':x position:' ':y position:'
diff --git a/Completion/Pbmplus/_pbmtoepsi b/Completion/Pbmplus/_pbmtoepsi
new file mode 100644
index 000000000..7bba77295
--- /dev/null
+++ b/Completion/Pbmplus/_pbmtoepsi
@@ -0,0 +1,3 @@
+#compdef pbmtoepsi
+
+_arguments '--bbonly' ':file: _pbmfile'
diff --git a/Completion/Pbmplus/_pbmtolj b/Completion/Pbmplus/_pbmtolj
new file mode 100644
index 000000000..6ccc63b6d
--- /dev/null
+++ b/Completion/Pbmplus/_pbmtolj
@@ -0,0 +1,3 @@
+#compdef pbmtolj
+
+_arguments '-resolution:resolution:(75 100 150 300)' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pbmtoln03 b/Completion/Pbmplus/_pbmtoln03
new file mode 100644
index 000000000..12b106dea
--- /dev/null
+++ b/Completion/Pbmplus/_pbmtoln03
@@ -0,0 +1,5 @@
+#compdef pbmtoln03
+
+_arguments '-l:left margin:' '-r:right margin:' \
+           '-t:top margin:'  '-b:bottom margin:' \
+           '-f:form length:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pbmtolps b/Completion/Pbmplus/_pbmtolps
new file mode 100644
index 000000000..801948c11
--- /dev/null
+++ b/Completion/Pbmplus/_pbmtolps
@@ -0,0 +1,3 @@
+#compdef pbmtolps
+
+_arguments '-dpi:resolution:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pbmtomacp b/Completion/Pbmplus/_pbmtomacp
new file mode 100644
index 000000000..aa9e94e73
--- /dev/null
+++ b/Completion/Pbmplus/_pbmtomacp
@@ -0,0 +1,4 @@
+#compdef pbmtomacp
+
+_arguments '-l:left offset:' '-r:right offset:' \
+           '-t:top offset:'  '-b:bottom offset:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pbmtopgm b/Completion/Pbmplus/_pbmtopgm
new file mode 100644
index 000000000..29bd5422f
--- /dev/null
+++ b/Completion/Pbmplus/_pbmtopgm
@@ -0,0 +1,3 @@
+#compdef pbmtopgm
+
+_arguments ':width:' ':height:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pbmtopk b/Completion/Pbmplus/_pbmtopk
new file mode 100644
index 000000000..913d11106
--- /dev/null
+++ b/Completion/Pbmplus/_pbmtopk
@@ -0,0 +1,11 @@
+#compdef pbmtopk
+
+# This could be improved...
+
+_arguments '-s:design size:' '-C:coding scheme:' '-F:font family:' \
+           '-f:option file:_files' '-c:character number:' \
+           '-W:width:' '-H:height:' '-D:depth:' '-I:italic correction:' \
+           '-h:horizontal escapement:' '-v:vertical escapement:' \
+	   '-x:x offset:' '-y:y offset:' \
+           ':pk file:_files -g *.(#i)pk' ':tfm file:_files -g *.(#i)tfm' \
+	   '*:file: _pbm_file'
diff --git a/Completion/Pbmplus/_pbmupc b/Completion/Pbmplus/_pbmupc
new file mode 100644
index 000000000..b77488d57
--- /dev/null
+++ b/Completion/Pbmplus/_pbmupc
@@ -0,0 +1,4 @@
+#compdef pbmupc
+
+_arguments '-s1' '-s2' ':product type:' ':manufacturer code:' \
+           ':product code:'
diff --git a/Completion/Pbmplus/_pgmcrater b/Completion/Pbmplus/_pgmcrater
new file mode 100644
index 000000000..5905ea8a2
--- /dev/null
+++ b/Completion/Pbmplus/_pgmcrater
@@ -0,0 +1,5 @@
+#compdef pgmcrater
+
+_arguments '-number:number of craters:' '-gamma:factor:' \
+           '-height:height:' '-ysize:height:' \
+	   '-width:width:'   '-xsize:width:'
diff --git a/Completion/Pbmplus/_pgmkernel b/Completion/Pbmplus/_pgmkernel
new file mode 100644
index 000000000..83a3e6ae2
--- /dev/null
+++ b/Completion/Pbmplus/_pgmkernel
@@ -0,0 +1,3 @@
+#compdef pgmkernel
+
+_arguments '-weight:weight:' ':width:' ':height:'
diff --git a/Completion/Pbmplus/_pgmnoise b/Completion/Pbmplus/_pgmnoise
new file mode 100644
index 000000000..efcd5b82b
--- /dev/null
+++ b/Completion/Pbmplus/_pgmnoise
@@ -0,0 +1,3 @@
+#compdef pgmnoise
+
+_arguments ':width:' ':height:'
diff --git a/Completion/Pbmplus/_pgmnorm b/Completion/Pbmplus/_pgmnorm
new file mode 100644
index 000000000..e088550e9
--- /dev/null
+++ b/Completion/Pbmplus/_pgmnorm
@@ -0,0 +1,5 @@
+#compdef pgmnorm ppmnorm
+
+_arguments '-bpercent:black percentage:' '-bvalue:black pixel value:' \
+           '-wpercent:white percentage:' '-wvalue:white pixel value:' \
+	   ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pgmoil b/Completion/Pbmplus/_pgmoil
new file mode 100644
index 000000000..e1c7a0c0f
--- /dev/null
+++ b/Completion/Pbmplus/_pgmoil
@@ -0,0 +1,3 @@
+#compdef pgmoil
+
+_arguments '-n:smear size:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pgmramp b/Completion/Pbmplus/_pgmramp
new file mode 100644
index 000000000..9fa7c0b54
--- /dev/null
+++ b/Completion/Pbmplus/_pgmramp
@@ -0,0 +1,3 @@
+#compdef pgmramp
+
+_arguments '-lr' '-tb' '-rectangle' '-ellipse' ':width:' ':height:'
diff --git a/Completion/Pbmplus/_pgmtexture b/Completion/Pbmplus/_pgmtexture
new file mode 100644
index 000000000..48e29066a
--- /dev/null
+++ b/Completion/Pbmplus/_pgmtexture
@@ -0,0 +1,3 @@
+#compdef pgmtexture
+
+_arguments '-d:distance:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pgmtopbm b/Completion/Pbmplus/_pgmtopbm
new file mode 100644
index 000000000..642d6277b
--- /dev/null
+++ b/Completion/Pbmplus/_pgmtopbm
@@ -0,0 +1,5 @@
+#compdef pgmtopbm
+
+_arguments '-floyd' '-fs' '-threshold' '-dither8' '-d8' '-cluster3' '-c3' \
+           '-cluster4' '-c4' '-cluster8' '-c8' '-value:threshold value:' \
+	   ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pgmtoppm b/Completion/Pbmplus/_pgmtoppm
new file mode 100644
index 000000000..c8b1abec6
--- /dev/null
+++ b/Completion/Pbmplus/_pgmtoppm
@@ -0,0 +1,21 @@
+#compdef pgmtoppm
+
+local ret=1 expl
+
+if [[ CURRENT -eq 2 ]]; then
+  if compset -P '?*-'; then
+    _colors
+    return
+  fi
+  _colors && ret=0
+
+  _description expl option
+  compadd "$expl[@]" - -map && ret=0
+
+  return ret
+elif [[ CURRENT -eq 3 && "$words[2]" = -map ]]; then
+  _description expl 'map file'
+  _files "$expl[@]" -g '*.(#i)ppm'
+else
+  _pbm_file
+fi
diff --git a/Completion/Pbmplus/_pktopbm b/Completion/Pbmplus/_pktopbm
new file mode 100644
index 000000000..5b97fdd33
--- /dev/null
+++ b/Completion/Pbmplus/_pktopbm
@@ -0,0 +1,4 @@
+#compdef pktopbm
+
+_arguments ':pk file:_file -g *.(#i)pk' '-c:character number:' \
+           '*:file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmalias b/Completion/Pbmplus/_pnmalias
new file mode 100644
index 000000000..4dda6fb9f
--- /dev/null
+++ b/Completion/Pbmplus/_pnmalias
@@ -0,0 +1,6 @@
+#compdef pnmalias
+
+_arguments '-bgcolor:background color:_colors' \
+           '-fgcolor:foreground color:_colors' \
+	   '-bonly' '-fonly' '-balias' '-falias' \
+	   '-weight:central aliasing weight:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmarith b/Completion/Pbmplus/_pnmarith
new file mode 100644
index 000000000..568c923db
--- /dev/null
+++ b/Completion/Pbmplus/_pnmarith
@@ -0,0 +1,3 @@
+#compdef pnmarith
+
+_arguments '-add' '-subtract' '-multiply' '*:file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmcat b/Completion/Pbmplus/_pnmcat
new file mode 100644
index 000000000..6d71cae10
--- /dev/null
+++ b/Completion/Pbmplus/_pnmcat
@@ -0,0 +1,4 @@
+#compdef pnmcat
+
+_arguments '-white' '-black' '-leftright' '-lr' '-topbottom' '-tb' \
+           '-jtop' '-jbottom' '-jleft' '-jright' '*:file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmcomp b/Completion/Pbmplus/_pnmcomp
new file mode 100644
index 000000000..01f8bb33e
--- /dev/null
+++ b/Completion/Pbmplus/_pnmcomp
@@ -0,0 +1,5 @@
+#compdef pnmcomp
+
+_arguments '-invert' '-xoff:x offset:' '-yoff:y offset:' \
+           '-alpha:alpha mask file:_files -g *.(#i)pgm' \
+	   ':overlay file:_pbm_file' '*:file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmconvol b/Completion/Pbmplus/_pnmconvol
new file mode 100644
index 000000000..69785b3d1
--- /dev/null
+++ b/Completion/Pbmplus/_pnmconvol
@@ -0,0 +1,3 @@
+#compdef pnmconvol
+
+_arguments ':convolution file:_pbm_file' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmcrop b/Completion/Pbmplus/_pnmcrop
new file mode 100644
index 000000000..a7a29cacb
--- /dev/null
+++ b/Completion/Pbmplus/_pnmcrop
@@ -0,0 +1,3 @@
+#compdef pnmcrop
+
+_arguments '-white' '-black' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmcut b/Completion/Pbmplus/_pnmcut
new file mode 100644
index 000000000..7e3884b59
--- /dev/null
+++ b/Completion/Pbmplus/_pnmcut
@@ -0,0 +1,3 @@
+#compdef pnmcut
+
+_arguments ':x position:' ':y position:' ':width:' ':height:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmdepth b/Completion/Pbmplus/_pnmdepth
new file mode 100644
index 000000000..76263c595
--- /dev/null
+++ b/Completion/Pbmplus/_pnmdepth
@@ -0,0 +1,3 @@
+#compdef pnmdepth
+
+_arguments ':new maximum value:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmenlarge b/Completion/Pbmplus/_pnmenlarge
new file mode 100644
index 000000000..511122f9f
--- /dev/null
+++ b/Completion/Pbmplus/_pnmenlarge
@@ -0,0 +1,3 @@
+#compdef pnmenlarge
+
+_arguments ':enlargement factor:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmflip b/Completion/Pbmplus/_pnmflip
new file mode 100644
index 000000000..ecec27dd9
--- /dev/null
+++ b/Completion/Pbmplus/_pnmflip
@@ -0,0 +1,5 @@
+#compdef pnmflip
+
+_arguments '-leftright' '-lr' '-topbottom' '-tb' '-transpose' '-xy' \
+           '-rotate90' '-r90' '-ccw' '-rotate270' '-r270' '-cw' \
+	   ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmgamma b/Completion/Pbmplus/_pnmgamma
new file mode 100644
index 000000000..c9d141535
--- /dev/null
+++ b/Completion/Pbmplus/_pnmgamma
@@ -0,0 +1,16 @@
+#compdef pnmgamma
+
+local ret=1
+
+if [[ CURRENT -eq 2 ]]; then
+  _message 'gamma value or red gamma value'
+elif [[ CURRENT -eq 3 ]]; then
+  _pbm_file && ret=0
+  _message 'green gamma value'
+elif [[ CURRENT -eq 4 ]]; then
+  _message 'blue gamma value'
+elif [[ CURRENT -eq 5 ]]; then
+  _pbm_file && ret=0
+fi
+
+return ret
diff --git a/Completion/Pbmplus/_pnmhistmap b/Completion/Pbmplus/_pnmhistmap
new file mode 100644
index 000000000..b011c2d94
--- /dev/null
+++ b/Completion/Pbmplus/_pnmhistmap
@@ -0,0 +1,4 @@
+#compdef pnmhistmap
+
+_arguments '-black' '-white' '-max:maximum value:' '-verbose' \
+           ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmindex b/Completion/Pbmplus/_pnmindex
new file mode 100644
index 000000000..39b6bacbb
--- /dev/null
+++ b/Completion/Pbmplus/_pnmindex
@@ -0,0 +1,4 @@
+#compdef pnmindex
+
+_arguments '-size:image size:' '-across:images per row:' \
+           '-colors:number of colors:' '-black' '*:file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmmargin b/Completion/Pbmplus/_pnmmargin
new file mode 100644
index 000000000..90e196f8d
--- /dev/null
+++ b/Completion/Pbmplus/_pnmmargin
@@ -0,0 +1,4 @@
+#compdef pnmmargin
+
+_arguments '-white' '-black' '-color:color: _colors' \
+           ':border width:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmnlfilt b/Completion/Pbmplus/_pnmnlfilt
new file mode 100644
index 000000000..c5a25053d
--- /dev/null
+++ b/Completion/Pbmplus/_pnmnlfilt
@@ -0,0 +1,3 @@
+#compdef pnmnlfilt
+
+_arguments ':alpha value:' ':radius:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmpad b/Completion/Pbmplus/_pnmpad
new file mode 100644
index 000000000..9516c5281
--- /dev/null
+++ b/Completion/Pbmplus/_pnmpad
@@ -0,0 +1,6 @@
+#compdef pnmpad
+
+_arguments '-black' '-white' \
+           '-l-:left border width:' '-r-:right border width:' \
+           '-t-:top border width:' '-b-:bottom border width:' \
+           ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmpaste b/Completion/Pbmplus/_pnmpaste
new file mode 100644
index 000000000..2728d959d
--- /dev/null
+++ b/Completion/Pbmplus/_pnmpaste
@@ -0,0 +1,6 @@
+#compdef pnmpaste
+
+_arguments '-replace' '-or' '-and' '-xor' \
+           ':"from" picture file:_pbm_file' \
+	   ':x position:' ':y position:' \
+	   ':"into" picture file:_pbm_file'
diff --git a/Completion/Pbmplus/_pnmrotate b/Completion/Pbmplus/_pnmrotate
new file mode 100644
index 000000000..84e568ec9
--- /dev/null
+++ b/Completion/Pbmplus/_pnmrotate
@@ -0,0 +1,3 @@
+#compdef pnmrotate
+
+_arguments '-noantialias' ':rotation angle:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmscale b/Completion/Pbmplus/_pnmscale
new file mode 100644
index 000000000..3b56071b0
--- /dev/null
+++ b/Completion/Pbmplus/_pnmscale
@@ -0,0 +1,16 @@
+#compdef pnmscale
+
+local scale
+
+if [[ "$words[2]" = -* ]]; then
+  scale=()
+else
+  scale=( ':scale factor:' )
+fi
+
+_arguments '-xsize:width:'  '-width:width:' \
+           '-ysize:height:' '-height:height:' \
+	   '-xscale:horizontal scale factor:' \
+	   '-yscale:horizontal scale factor:' \
+	   '-xysize:width::height:' "$scale[@]" \
+	   ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmshear b/Completion/Pbmplus/_pnmshear
new file mode 100644
index 000000000..a94e4347b
--- /dev/null
+++ b/Completion/Pbmplus/_pnmshear
@@ -0,0 +1,3 @@
+#compdef pnmshear
+
+_arguments '-noantialias' ':shearing angle:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmtile b/Completion/Pbmplus/_pnmtile
new file mode 100644
index 000000000..eb2a45989
--- /dev/null
+++ b/Completion/Pbmplus/_pnmtile
@@ -0,0 +1,3 @@
+#compdef pnmtile
+
+_arguments ':width:' ':height:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmtoddif b/Completion/Pbmplus/_pnmtoddif
new file mode 100644
index 000000000..c7578c792
--- /dev/null
+++ b/Completion/Pbmplus/_pnmtoddif
@@ -0,0 +1,4 @@
+#compdef pnmtoddif
+
+_arguments '-resolution:horizontal resolution::vertical resolution:' \
+           ':file: _pbm_file' ':ddif file:_files -g *.(#i)ddif'
diff --git a/Completion/Pbmplus/_pnmtofits b/Completion/Pbmplus/_pnmtofits
new file mode 100644
index 000000000..fe3e33569
--- /dev/null
+++ b/Completion/Pbmplus/_pnmtofits
@@ -0,0 +1,3 @@
+#compdef pnmtofits
+
+_arguments '-max:maximum value:' '-min:minimum value:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmtops b/Completion/Pbmplus/_pnmtops
new file mode 100644
index 000000000..4b66701a0
--- /dev/null
+++ b/Completion/Pbmplus/_pnmtops
@@ -0,0 +1,5 @@
+#compdef pnmtops
+
+_arguments '-scale:scale factor:' '-turn' '-noturn' '-rle' '-runlength' \
+           '-dpi:output resolution:' \
+           '-width:page width:' '-height:page height' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmtorast b/Completion/Pbmplus/_pnmtorast
new file mode 100644
index 000000000..e6d04db0c
--- /dev/null
+++ b/Completion/Pbmplus/_pnmtorast
@@ -0,0 +1,3 @@
+#compdef pnmtorast
+
+_arguments '-standard' '-rle' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmtosgi b/Completion/Pbmplus/_pnmtosgi
new file mode 100644
index 000000000..efbbc3886
--- /dev/null
+++ b/Completion/Pbmplus/_pnmtosgi
@@ -0,0 +1,3 @@
+#compdef pnmtosgi
+
+_arguments '-verbatim' '-rle' '-imagename:image name:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmtotiff b/Completion/Pbmplus/_pnmtotiff
new file mode 100644
index 000000000..5cc170190
--- /dev/null
+++ b/Completion/Pbmplus/_pnmtotiff
@@ -0,0 +1,5 @@
+#compdef pnmtotiff
+
+_arguments '-none' '-packbits' '-lzw' '-g3' '-g4' '-2d' '-fill' \
+           '-predictor:LZW predictor:(1 2)' '-msb2lsb' '-lsb2msb' \
+	   '-rowsperstrip:number of rows per strip:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_pnmtoxwd b/Completion/Pbmplus/_pnmtoxwd
new file mode 100644
index 000000000..1c8b2393d
--- /dev/null
+++ b/Completion/Pbmplus/_pnmtoxwd
@@ -0,0 +1,4 @@
+#compdef pnmtoxwd
+
+_arguments '-pseudodepth:depth of PseudoColor dumps:' '-directcolor' \
+           ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_ppm3d b/Completion/Pbmplus/_ppm3d
new file mode 100644
index 000000000..8f3cc0434
--- /dev/null
+++ b/Completion/Pbmplus/_ppm3d
@@ -0,0 +1,4 @@
+#compdef ppm3d
+
+_arguments ':left picture file:_pbm_file' ':right picture file:_pbm_file' \
+           ':horizontal offset:'
diff --git a/Completion/Pbmplus/_ppmbrighten b/Completion/Pbmplus/_ppmbrighten
new file mode 100644
index 000000000..0fbc6ddaf
--- /dev/null
+++ b/Completion/Pbmplus/_ppmbrighten
@@ -0,0 +1,3 @@
+#compdef ppmbrighten
+
+_arguments '-n' '-s:saturation:' '-v:value:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_ppmchange b/Completion/Pbmplus/_ppmchange
new file mode 100644
index 000000000..45c83ea2e
--- /dev/null
+++ b/Completion/Pbmplus/_ppmchange
@@ -0,0 +1,15 @@
+#compdef ppmchange
+
+local ret=1 expl
+
+_pbm_file && ret=0
+
+if (( CURRENT & 1 )); then
+  _description expl 'new color'
+else
+  _description expl 'old color'
+fi
+
+_colors "$expl[@]" && ret=0
+
+return ret
diff --git a/Completion/Pbmplus/_ppmdim b/Completion/Pbmplus/_ppmdim
new file mode 100644
index 000000000..7dd001809
--- /dev/null
+++ b/Completion/Pbmplus/_ppmdim
@@ -0,0 +1,3 @@
+#compdef ppmdim
+
+_arguments ':diminishing factor:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_ppmdist b/Completion/Pbmplus/_ppmdist
new file mode 100644
index 000000000..c825cabb3
--- /dev/null
+++ b/Completion/Pbmplus/_ppmdist
@@ -0,0 +1,3 @@
+#compdef ppmdist
+
+_arguments '-intensity' '-frequency' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_ppmdither b/Completion/Pbmplus/_ppmdither
new file mode 100644
index 000000000..94a52e68d
--- /dev/null
+++ b/Completion/Pbmplus/_ppmdither
@@ -0,0 +1,7 @@
+#compdef ppmdither
+
+_arguments '-dim:matrix size:' \
+           '-red:number of red shades:' \
+           '-green:number of green shades:' \
+           '-blue:number of blue shades:' \
+	   ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_ppmflash b/Completion/Pbmplus/_ppmflash
new file mode 100644
index 000000000..addc5e460
--- /dev/null
+++ b/Completion/Pbmplus/_ppmflash
@@ -0,0 +1,3 @@
+#compdef ppmflash
+
+_arguments ':flash factor:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_ppmforge b/Completion/Pbmplus/_ppmforge
new file mode 100644
index 000000000..ab8838afd
--- /dev/null
+++ b/Completion/Pbmplus/_ppmforge
@@ -0,0 +1,13 @@
+#compdef ppmforge
+
+_arguments '-clouds' '-night' \
+           '-dimension:fractal dimension:' '-hour:hour angle:' \
+	   '-inclination:inclination angle:' \
+	   '-tilt:inclination angle:' \
+	   '-mesh:FFT mesh size:' '-power:elevations power factor:' \
+	   '-glaciers:glacier elevation:' '-ice:polar ice cap extent:' \
+	   '-saturation:star color saturation:' \
+	   '-seed:randum number seed:' \
+	   '-stars:minimum star pixel percentage:' \
+	   '-width:width:' '-xsize:width:' \
+	   '-height:height:' '-ysize:height:'
diff --git a/Completion/Pbmplus/_ppmmake b/Completion/Pbmplus/_ppmmake
new file mode 100644
index 000000000..62512a261
--- /dev/null
+++ b/Completion/Pbmplus/_ppmmake
@@ -0,0 +1,3 @@
+#compdef ppmmake
+
+_arguments ':color: _colors' ':width:' ':height:'
diff --git a/Completion/Pbmplus/_ppmmix b/Completion/Pbmplus/_ppmmix
new file mode 100644
index 000000000..bde240b75
--- /dev/null
+++ b/Completion/Pbmplus/_ppmmix
@@ -0,0 +1,3 @@
+#compdef ppmmix
+
+_arguments ':fade factor:' ':file: _pbm_file' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_ppmntsc b/Completion/Pbmplus/_ppmntsc
new file mode 100644
index 000000000..d4583f242
--- /dev/null
+++ b/Completion/Pbmplus/_ppmntsc
@@ -0,0 +1,3 @@
+#compdef ppmntsc
+
+_arguments ':dim factor:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_ppmpat b/Completion/Pbmplus/_ppmpat
new file mode 100644
index 000000000..e1c377c3c
--- /dev/null
+++ b/Completion/Pbmplus/_ppmpat
@@ -0,0 +1,4 @@
+#compdef ppmpat
+
+_arguments -gingham{2,3} -g{2,3} -madras -tartan -poles -squig -camo -anticamo \
+           ':width:' ':height:'
diff --git a/Completion/Pbmplus/_ppmquant b/Completion/Pbmplus/_ppmquant
new file mode 100644
index 000000000..42071d959
--- /dev/null
+++ b/Completion/Pbmplus/_ppmquant
@@ -0,0 +1,26 @@
+#compdef ppmquant
+
+local ret=1 expl opt=yes
+
+if [[ "$words[2]" = -(fs|floyd) ]]; then
+  (( CURRENT-- ))
+  shift 1 words
+  opt=''
+fi
+
+if [[ CURRENT -eq 2 ]]; then
+  _description expl option
+  if [[ -n "$opt" ]]; then
+    compadd "$expl[@]" - -map -fs -floyd && ret=0
+  else
+    compadd "$expl[@]" - -map && ret=0
+  fi
+  _message 'number of colors'
+
+  return ret
+elif [[ CURRENT -eq 3 && "$words[2]" = -map ]]; then
+  _description expl 'map file'
+  _files "$expl[@]" -g '*.(#i)ppm'
+else
+  _pbm_file
+fi
diff --git a/Completion/Pbmplus/_ppmquantall b/Completion/Pbmplus/_ppmquantall
new file mode 100644
index 000000000..8fb85ab6d
--- /dev/null
+++ b/Completion/Pbmplus/_ppmquantall
@@ -0,0 +1,3 @@
+#compdef ppmquantall
+
+_arguments ':number of colors:' '*:file: _pbm_file'
diff --git a/Completion/Pbmplus/_ppmshift b/Completion/Pbmplus/_ppmshift
new file mode 100644
index 000000000..02fa9c465
--- /dev/null
+++ b/Completion/Pbmplus/_ppmshift
@@ -0,0 +1,3 @@
+#compdef ppmshift
+
+_arguments ':shift value:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_ppmspread b/Completion/Pbmplus/_ppmspread
new file mode 100644
index 000000000..d0452ba0e
--- /dev/null
+++ b/Completion/Pbmplus/_ppmspread
@@ -0,0 +1,3 @@
+#compdef ppmspread
+
+_arguments ':maximum spread amount:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_ppmtoacad b/Completion/Pbmplus/_ppmtoacad
new file mode 100644
index 000000000..245b8afcd
--- /dev/null
+++ b/Completion/Pbmplus/_ppmtoacad
@@ -0,0 +1,4 @@
+#compdef ppmtoacad
+
+_arguments '-dxb' '-poly' '-background:background color:_colors' \
+           '-white' '-aspect:pixel aspect ratio:' '-8' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_ppmtobmp b/Completion/Pbmplus/_ppmtobmp
new file mode 100644
index 000000000..0ebaef1f6
--- /dev/null
+++ b/Completion/Pbmplus/_ppmtobmp
@@ -0,0 +1,3 @@
+#compdef ppmtobmp
+
+_arguments '-os2' '-windows' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_ppmtogif b/Completion/Pbmplus/_ppmtogif
new file mode 100644
index 000000000..46e0a6663
--- /dev/null
+++ b/Completion/Pbmplus/_ppmtogif
@@ -0,0 +1,3 @@
+#compdef ppmtogif
+
+_arguments '-interlace' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_ppmtoicr b/Completion/Pbmplus/_ppmtoicr
new file mode 100644
index 000000000..4df9c26f3
--- /dev/null
+++ b/Completion/Pbmplus/_ppmtoicr
@@ -0,0 +1,4 @@
+#compdef ppmtoicr
+
+_arguments '-windowname:window name:' '-expand:expansion factor:' \
+           '-display:display screen:' '-rle' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_ppmtoilbm b/Completion/Pbmplus/_ppmtoilbm
new file mode 100644
index 000000000..ff19fa91a
--- /dev/null
+++ b/Completion/Pbmplus/_ppmtoilbm
@@ -0,0 +1,3 @@
+#compdef ppmtoilbm
+
+_arguments '-hamif' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_ppmtomap b/Completion/Pbmplus/_ppmtomap
new file mode 100644
index 000000000..0476cfb44
--- /dev/null
+++ b/Completion/Pbmplus/_ppmtomap
@@ -0,0 +1,3 @@
+#compdef ppmtomap
+
+_arguments '-sort' '-square' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_ppmtomitsu b/Completion/Pbmplus/_ppmtomitsu
new file mode 100644
index 000000000..e89047df1
--- /dev/null
+++ b/Completion/Pbmplus/_ppmtomitsu
@@ -0,0 +1,7 @@
+#compdef ppmtomitsu
+
+_arguments '-sharpness:sharpness:(1 2 3 4)' \
+           '-enlarge:enlargement factor:(1 2 3)' \
+	   '-media:output media:(A A4 AS A4S)' \
+	   '-copy:number of copies:(1 2 3 4 5 6 7 8 9)' \
+	   '-dpi300' '-tiny' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_ppmtopj b/Completion/Pbmplus/_ppmtopj
new file mode 100644
index 000000000..d5b48f5c7
--- /dev/null
+++ b/Completion/Pbmplus/_ppmtopj
@@ -0,0 +1,6 @@
+#compdef ppmtopj
+
+_arguments '-gamma:gamma value:' '-xpos:x position:' '-rle' '-center' \
+           '-ypos:y position:' '-back:background brightness:(dark lite)' \
+	   '-render:rendering algorithm:(none snap bw dither diffuse monodither monodiffuse clusterdither monoclusterdither)' \
+	   ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_ppmtopjxl b/Completion/Pbmplus/_ppmtopjxl
new file mode 100644
index 000000000..5ef79be94
--- /dev/null
+++ b/Completion/Pbmplus/_ppmtopjxl
@@ -0,0 +1,9 @@
+#compdef ppmtopjxl
+
+_arguments '-nopack' '-gamma:gamma value:' '-presentation' '-dark' \
+           '-diffuse' '-cluster' '-dither' \
+	   '-xshift:x shift:' '-yshift:y shift:' \
+	   '-xscale:x scale factor:' '-yscale:y scale factor:' \
+	   '-xsize:width:'  '-width:width:' \
+	   '-ysize:height:' '-height:height:' \
+	   ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_ppmtosixel b/Completion/Pbmplus/_ppmtosixel
new file mode 100644
index 000000000..6272661aa
--- /dev/null
+++ b/Completion/Pbmplus/_ppmtosixel
@@ -0,0 +1,3 @@
+#compdef ppmtosixel
+
+_arguments '-raw' '-margin' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_ppmtotga b/Completion/Pbmplus/_ppmtotga
new file mode 100644
index 000000000..adf09a2bd
--- /dev/null
+++ b/Completion/Pbmplus/_ppmtotga
@@ -0,0 +1,3 @@
+#compdef ppmtotga
+
+_arguments '-mono' '-cmap' '-rgb' '-norle' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_ppmtouil b/Completion/Pbmplus/_ppmtouil
new file mode 100644
index 000000000..63b1ee167
--- /dev/null
+++ b/Completion/Pbmplus/_ppmtouil
@@ -0,0 +1,3 @@
+#compdef ppmtouil ppmtoxpm
+
+_arguments '-name:name prefix:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_ppmtoyuvsplit b/Completion/Pbmplus/_ppmtoyuvsplit
new file mode 100644
index 000000000..598b78797
--- /dev/null
+++ b/Completion/Pbmplus/_ppmtoyuvsplit
@@ -0,0 +1,3 @@
+#compdef ppmtoyuvsplit
+
+_arguments ':base name:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_psidtopgm b/Completion/Pbmplus/_psidtopgm
new file mode 100644
index 000000000..0ba7328aa
--- /dev/null
+++ b/Completion/Pbmplus/_psidtopgm
@@ -0,0 +1,4 @@
+#compdef psidtopgm
+
+_arguments ':width:' ':height:' ':bits per sample:' \
+           ':postscript file:_files -g *.(#i)(ps|eps)'
diff --git a/Completion/Pbmplus/_pstopnm b/Completion/Pbmplus/_pstopnm
new file mode 100644
index 000000000..b66f4041a
--- /dev/null
+++ b/Completion/Pbmplus/_pstopnm
@@ -0,0 +1,10 @@
+#compdef pstopnm
+
+_arguments '-forceplain' '-help' '-landscape' '-portrait' '-nocrop' \
+           '-pbm' '-pgm' '-ppm' '-verbose' \
+	   '-llx:loxer left x position:' '-lly:lower left y position:' \
+	   '-urx:upper right x position:' '-ury:upper right y position:' \
+	   '-xborder:x border fraction:' '-yborder:y border fraction:' \
+	   '-xmax:maximum width:' '-ymax:maximum height' \
+	   '-xsize:width:' '-ysize:height:' \
+	   ':postscript file:_files -g *.(#i)(ps|eps)'
diff --git a/Completion/Pbmplus/_rawtopgm b/Completion/Pbmplus/_rawtopgm
new file mode 100644
index 000000000..c8e87dbde
--- /dev/null
+++ b/Completion/Pbmplus/_rawtopgm
@@ -0,0 +1,5 @@
+#compdef rawtopgm
+
+_arguments '-headerskip:header bytes to skip:' \
+           '-rowskip:row padding to skip:' \
+	   ':width:' ':height:' ':grayscale bytes:'
diff --git a/Completion/Pbmplus/_rawtoppm b/Completion/Pbmplus/_rawtoppm
new file mode 100644
index 000000000..d4a0c333c
--- /dev/null
+++ b/Completion/Pbmplus/_rawtoppm
@@ -0,0 +1,6 @@
+#compdef rawtoppm
+
+_arguments '-headerskip:header bytes to skip:' \
+           '-rowskip:row padding to skip:' \
+	   '-rgb' '-rbg' '-grb' '-gbr' '-brg' '-bgr' '-interpixel' '-interrow' \
+	   ':width:' ':height:' ':grayscale bytes:'
diff --git a/Completion/Pbmplus/_rgb3toppm b/Completion/Pbmplus/_rgb3toppm
new file mode 100644
index 000000000..ac4df434d
--- /dev/null
+++ b/Completion/Pbmplus/_rgb3toppm
@@ -0,0 +1,16 @@
+#compdef rgb3toppm
+
+local expl
+
+if [[ CURRENT -eq 2 ]]; then
+  expl='red picture file'
+elif [[ CURRENT -eq 3 ]]; then
+  expl='green picture file'
+elif [[ CURRENT -eq 4 ]]; then
+  expl='blue picture file'
+fi
+
+if [[ -n "$expl" ]]; then
+  _description expl "$expl"
+  _files "$expl" -g '*.(#i)pgm'
+fi
diff --git a/Completion/Pbmplus/_sgitopnm b/Completion/Pbmplus/_sgitopnm
new file mode 100644
index 000000000..84189acc2
--- /dev/null
+++ b/Completion/Pbmplus/_sgitopnm
@@ -0,0 +1,3 @@
+#compdef sgitopnm
+
+_arguments '-verbose' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_sldtoppm b/Completion/Pbmplus/_sldtoppm
new file mode 100644
index 000000000..0ec01860c
--- /dev/null
+++ b/Completion/Pbmplus/_sldtoppm
@@ -0,0 +1,7 @@
+#compdef sldtoppm
+
+_arguments '-adjust' '-dir' '-info' '-verbose' \
+	   '-width:width:'   '-xsize:width:' \
+           '-height:height:' '-ysize:height:' \
+	   '-scale:scale factor:' \
+	   '-lib:slide name:' '-Lib:slide name:' ':file: _pbm_file'
diff --git a/Completion/Pbmplus/_yuvsplittoppm b/Completion/Pbmplus/_yuvsplittoppm
new file mode 100644
index 000000000..83d7c4d28
--- /dev/null
+++ b/Completion/Pbmplus/_yuvsplittoppm
@@ -0,0 +1,3 @@
+#compdef yuvsplittoppm
+
+_arguments ':base name:' ':width:' ':height:' '-ccir601'
diff --git a/Completion/Pbmplus/_yuvtoppm b/Completion/Pbmplus/_yuvtoppm
new file mode 100644
index 000000000..438249d34
--- /dev/null
+++ b/Completion/Pbmplus/_yuvtoppm
@@ -0,0 +1,3 @@
+#compdef yuvtoppm
+
+_arguments ':width:' ':height:' 'image bytes:'
diff --git a/Completion/Pbmplus/_zeisstopnm b/Completion/Pbmplus/_zeisstopnm
new file mode 100644
index 000000000..f38c02b93
--- /dev/null
+++ b/Completion/Pbmplus/_zeisstopnm
@@ -0,0 +1,3 @@
+#compdef zeisstopnm
+
+_arguments '-pgm' '-ppm' ':file: _pbm_file'
diff --git a/Completion/User/_a2ps b/Completion/User/_a2ps
index 26f4d200e..956e5a0ff 100644
--- a/Completion/User/_a2ps
+++ b/Completion/User/_a2ps
@@ -22,18 +22,18 @@ if [[ "$words[1]" != "$_a2ps_cache_cmd" ]]; then
   )
 fi
 
-_long_options -t '*\*'                '(yes no)' \
-                 '*=DIRECTION'        '(rows columns)' \
-                 '*=TYPE'             '(r n nr rn any)' \
-		 '--highlight-level*' '(none normal heavy)' \
-		 '--version-control*' '(none off t numbered nil 
+_long_options -t '*\*:toggle:(yes no)' \
+                 '*=DIRECTION:direction:(rows columns)' \
+                 '*=TYPE:type:(r n nr rn any)' \
+		 '--highlight-level*:highlight:(none normal heavy)' \
+		 '--version-control*:version control:(none off t numbered nil 
 		                        existing never simple)' \
-	         '--pretty-print*'    "[${_a2ps_cache_values[1]}]" \
-	         '--encoding*'        "(${_a2ps_cache_values[2]})" \
-	         '--medium*'          "[${_a2ps_cache_values[3]}]" \
-	         '--prologue*'        "[${_a2ps_cache_values[4]}]" \
-	         '--ppd*'             "[${_a2ps_cache_values[5]}]" \
-	         '--printer*'         "[${_a2ps_cache_values[6]}]" \
-	         '--user-option*'     "[${_a2ps_cache_values[7]}]" \
-	         '--variable*'        "[${_a2ps_cache_values[8]}]" ||
+	         "--pretty-print*:style:[${_a2ps_cache_values[1]}]" \
+	         "--encoding*:encoding:(${_a2ps_cache_values[2]})" \
+	         "--medium*:medium:[${_a2ps_cache_values[3]}]" \
+	         "--prologue*:prologue:[${_a2ps_cache_values[4]}]" \
+	         "--ppd*:printer description:[${_a2ps_cache_values[5]}]" \
+	         "--printer*:printer:[${_a2ps_cache_values[6]}]" \
+	         "--user-option*:user option:[${_a2ps_cache_values[7]}]" \
+	         "--variable*:variable:[${_a2ps_cache_values[8]}]" ||
     _files -F fignore -g '*~*.(ps|PS|eps|EPS)'
diff --git a/Completion/User/_bunzip2 b/Completion/User/_bunzip2
index f544c8c27..53f4388bc 100644
--- a/Completion/User/_bunzip2
+++ b/Completion/User/_bunzip2
@@ -1,3 +1,6 @@
 #compdef bunzip2 bzcat
 
-_files -g '*.bz2'
+local expl
+
+_description expl 'compressed file'
+_files "$expl[@]" -g '*.bz2'
diff --git a/Completion/User/_bzip2 b/Completion/User/_bzip2
index faf9f2501..15dd6f090 100644
--- a/Completion/User/_bzip2
+++ b/Completion/User/_bzip2
@@ -1,3 +1,6 @@
 #compdef bzip2
 
-_files -g '*~*.bz2'
+local expl
+
+_description expl 'file to compress'
+_files "$expl[@]" -g '*~*.bz2'
diff --git a/Completion/User/_chown b/Completion/User/_chown
index 1ec76b39e..c75dbc4b3 100644
--- a/Completion/User/_chown
+++ b/Completion/User/_chown
@@ -4,10 +4,14 @@ if [[ CURRENT -eq 2 || CURRENT -eq 3 && $words[CURRENT-1] = -* ]]; then
   if [[ $words[1] = chgrp ]] || compset -P '*[:.]'; then
     _groups
   else
+    local expl
+
+    _description expl user
+
     if [[ $OSTYPE = (solaris*|hpux*) ]]; then
-      compgen -u -S ':' -q
+      compgen "$expl[@]" -u -S ':' -q
     else
-      compgen -u -S '.' -q
+      compgen "$expl[@]" -u -S '.' -q
     fi
   fi
 else
diff --git a/Completion/User/_colors b/Completion/User/_colors
index 369a4365f..346142eea 100644
--- a/Completion/User/_colors
+++ b/Completion/User/_colors
@@ -1,5 +1,7 @@
 #autoload
 
+local expl
+
 if (( ! $+_color_cache )); then
   local file
 
@@ -17,4 +19,6 @@ if (( ! $+_color_cache )); then
   fi
 fi
 
-compadd -M 'm:{a-z}={A-Z} m:-=\  r:|[ A-Z0-9]=* r:|=*' - "$_color_cache[@]"
+_description expl 'color specification'
+compadd "$@" "$expl[@]" -M 'm:{a-z}={A-Z} m:-=\  r:|[ A-Z0-9]=* r:|=*' - \
+        "$_color_cache[@]"
diff --git a/Completion/User/_compress b/Completion/User/_compress
index 84ed42fb2..24363be07 100644
--- a/Completion/User/_compress
+++ b/Completion/User/_compress
@@ -1,3 +1,6 @@
 #compdef compress
 
-_files -g '*~*.Z'
+local expl
+
+_description expl 'file to compress'
+_files "$expl[@]" -g '*~*.Z'
diff --git a/Completion/User/_configure b/Completion/User/_configure
index 01c12dd62..5861682d0 100644
--- a/Completion/User/_configure
+++ b/Completion/User/_configure
@@ -5,5 +5,5 @@ _long_options -i '(--(disable|enable)-FEATURE* --(with|without)-PACKAGE*)' \
 	           #--enable- --disable-
 		   #--with- --without-
 		   #--without- --with-)' \
-	      '*=(E|)PREFIX*' '_files -/' \
-              '*=PROGRAM*'    '_command_names'
+	      '*=(E|)PREFIX*:prefix directory:_files -/' \
+              '*=PROGRAM*:program:_command_names'
diff --git a/Completion/User/_cursors b/Completion/User/_cursors
index 7e5cbc44e..59ecb5976 100644
--- a/Completion/User/_cursors
+++ b/Completion/User/_cursors
@@ -1,5 +1,7 @@
 #autoload
 
+local expl
+
 if (( ! $+_cursor_cache )); then
   local file
 
@@ -12,4 +14,5 @@ if (( ! $+_cursor_cache )); then
   fi
 fi
 
-compadd -M 'm:-=_ r:|_=*' - "$_cursor_cache[@]"
+_description expl 'cursor name'
+compadd "$@" "$expl[@]" -M 'm:-=_ r:|_=*' - "$_cursor_cache[@]"
diff --git a/Completion/User/_dd b/Completion/User/_dd
index e57074520..9bcdc876d 100644
--- a/Completion/User/_dd
+++ b/Completion/User/_dd
@@ -1,12 +1,21 @@
 #compdef dd
 
+local expl
+
 if compset -P 1 'conv\='; then
   # If there's a comma present, ignore up to the last one.  The
   # test alone will have that effect.
   compset -p '*,'
-  compadd -qS, -q ascii ebcdic ibm block unblock lcase ucase swab noerror sync
-elif compset -P 1 '[io]f\='; then
-  _files
+  _description expl conversion
+  compadd "$expl[@]" -qS, -q \
+          ascii ebcdic ibm block unblock lcase ucase swab noerror sync
+elif compset -P 1 'if\='; then
+  _description expl 'input file'
+  _files "$expl[@]"
+elif compset -P 1 'of\='; then
+  _description expl 'output file'
+  _files "$expl[@]"
 else
-  compadd -S '=' if of ibs obs bs cbs skip files seek count conv
+  _description expl option
+  compadd "$expl[@]" -S '=' if of ibs obs bs cbs skip files seek count conv
 fi
diff --git a/Completion/User/_find b/Completion/User/_find
index de8c3bff9..20e8f4ff7 100644
--- a/Completion/User/_find
+++ b/Completion/User/_find
@@ -1,27 +1,32 @@
 #compdef find
 
-local prev="$words[CURRENT-1]"
+local prev="$words[CURRENT-1]" expl
 
 if compset -N '-(ok|exec)' '\;'; then
   _normal
-elif compset -P 1 -; then
-  compadd daystart {max,min,}depth follow noleaf version xdev \
-    {a,c,}newer {a,c,m}{min,time} empty false {fs,x,}type gid inum links \
-    {i,}{l,}name {no,}{user,group} path perm regex size true uid used \
-    exec {f,}print{f,0,} ok prune ls
+elif [[ "$PREFIX" = -* ]]; then
+  _description expl option
+  compadd "$expl[@]" - -daystart -{max,min,}depth -follow -noleaf \
+    -version -xdev -{a,c,}newer -{a,c,m}{min,time} -empty -false \
+    -{fs,x,}type -gid -inum -links -{i,}{l,}name -{no,}{user,group} \
+    -path -perm -regex -size -true -uid -used -exec -{f,}print{f,0,} \
+    -ok -prune -ls
 elif [[ CURRENT -eq 2 ]]; then
   local ret=1
 
-  compgen -g '. ..' && ret=0
-  _files -g '*(-/)' && ret=0
+  _description expl directory
+  compgen "$expl[@]" -g '. ..' && ret=0
+  _files -/ && ret=0
 
   return ret
 elif [[ "$prev" = -((a|c|)newer|fprint(|0|f)) ]]; then
   _files
 elif [[ "$prev" = -fstype ]]; then
-  compadd ufs 4.2 4.3 nfs tmp mfs S51K S52K
+  _description expl 'file system type'
+  compadd "$expl[@]" ufs 4.2 4.3 nfs tmp mfs S51K S52K
 elif [[ "$prev" = -group ]]; then
-  compgen -k groups
+  _groups
 elif [[ "$prev" = -user ]]; then
-  compgen -u
+  _description expl user
+  compgen "$expl[@]" -u
 fi
diff --git a/Completion/User/_gdb b/Completion/User/_gdb
index ff54e6a07..1dba7819d 100644
--- a/Completion/User/_gdb
+++ b/Completion/User/_gdb
@@ -3,33 +3,38 @@
 # This uses the configuration keys `ps_args' and `ps_listargs'
 # described in the `_wait' function.
 
-local cur="$words[CURRENT]" prev w list ret=1
+local cur="$words[CURRENT]" prev w list ret=1 expl
 
-_long_options -t '*=(CORE|SYM)FILE'	'_files' \
-		 '*=EXECFILE'   	'_files *(*)' \
-		 '*=TTY'		'compadd /dev/tty*' && return 0
+_long_options -t '*=(CORE|SYM)FILE:core file:_files' \
+		 '*=EXECFILE:executable:_files *(*)' \
+		 '*=TTY:terminal device:compadd /dev/tty*' && return 0
 
 if compset -P '-(cd|directory)='; then
   _files -/
 elif compset -P '-tty='; then
-  compadd - /dev/tty*
+  _description expl 'terminal device'
+  compadd "$expl[@]" - /dev/tty*
 elif compset -P '-(exec|se)='; then
-  _files -/g '*(*)'
+  _description expl executable
+  _files "$expl[@]" -/g '*(*)'
 elif compset -P '-(symbols|core|command)='; then
   _files
-elif compset -P -; then
-  compadd -QS '' - symbols\= exec\= se\= core\= command\= directory\= \
-	           cd\= tty\=
-  compadd - help h s e c x d nx n quiet q batch fullname f b
+elif [[ "$PREFIX" = -* ]]; then
+  _description expl option
+  compadd "$expl[@]" -QS '' - symbols\= exec\= se\= core\= command\= \
+                              directory\= cd\= tty\=
+  compadd "$expl[@]" - help h s e c x d nx n quiet q batch fullname f b
 else
   prev="$words[CURRENT-1]"
 
   case "$prev" in
   (-d) _files -/ && return 0 ;;
-  (-e) _files -/g '*(*)' && return 0 ;;
   (-[csx]) _files && return 0 ;;
-  (-b) compadd -V baud 0 50 75 110 134 150 200 300 600 1200 1800 2400 4800 \
-                       9600 19200 38400 57600 115200 230400 && return 0 ;;
+  (-e) _description expl executable
+       _files "$expl[@]" -/g '*(*)' && return 0 ;;
+  (-b) _description -V expl 'baud rate'
+       compadd "$expl[@]" 0 50 75 110 134 150 200 300 600 1200 1800 2400 4800 \
+                          9600 19200 38400 57600 115200 230400 && return 0 ;;
   esac
   w=( "${(@)words[2,-1]}" )
   while [[ "$w[1]" = -* ]]; do
@@ -39,12 +44,14 @@ else
 
   if [[ $#w -gt 1 ]]; then
     _files && ret=0
+    _description expl 'process ID'
     list=("${(F)${(@Mr:COLUMNS-1:)${(f)$(ps ${compconfig[ps_listargs]:-$compconfig[ps_args]} 2>/dev/null)}[2,-1]:#[ 	]#${PREFIX}[0-9]#${SUFFIX}[ 	]*${w[1]:t}}}
 ")
-    compadd -y list - ${${${(M)${(f)"$(ps $compconfig[ps_args] 2>/dev/null)"}:#*${w[1]:t}*}## #}%% *} && ret=0
+    compadd "$expl[@]" -y list - ${${${(M)${(f)"$(ps $compconfig[ps_args] 2>/dev/null)"}:#*${w[1]:t}*}## #}%% *} && ret=0
 
     return ret
   else
+    _description expl executable
     _files -/g '*(*)'
   fi
 fi
diff --git a/Completion/User/_groups b/Completion/User/_groups
index 975189174..61f63596e 100644
--- a/Completion/User/_groups
+++ b/Completion/User/_groups
@@ -1,6 +1,9 @@
 #compdef newgrp
 
+local expl
+
 : ${(A)groups:=${${(s: :)$(</etc/group)}%%:*}}
 # : ${(A)groups:=${${(s: :)$(ypcat group.byname)}%%:*}} # If you use NIS
 
-compadd $groups
+_description expl group
+compadd "$@" "$expl[@]" - $groups
diff --git a/Completion/User/_gunzip b/Completion/User/_gunzip
index 7868e0c24..78e62c4cc 100644
--- a/Completion/User/_gunzip
+++ b/Completion/User/_gunzip
@@ -1,3 +1,6 @@
 #compdef gunzip zcat
 
-_files -g '*.[gG][z]'
+local expl
+
+_description expl 'compressed file'
+_files "$expl[@]" -g '*.[gG][z]'
diff --git a/Completion/User/_gzip b/Completion/User/_gzip
index 59e74a441..8cd4d746e 100644
--- a/Completion/User/_gzip
+++ b/Completion/User/_gzip
@@ -1,3 +1,6 @@
 #compdef gzip
 
+local expl
+
+_description expl 'file to compress'
 _files -g '*~*.[gG][zZ]'
diff --git a/Completion/User/_hosts b/Completion/User/_hosts
index d498425bc..6b2f350aa 100644
--- a/Completion/User/_hosts
+++ b/Completion/User/_hosts
@@ -1,5 +1,8 @@
 #compdef ftp ncftp ping rwho rup xping traceroute nslookup telnet
 
+local expl
+
 : ${(A)hosts:=${(s: :)${(ps:\t:)${${(f)"$(</etc/hosts)"}%%\#*}##[:blank:]#[^[:blank:]]#}}}
 
-compadd -M 'm:{a-zA-Z}={A-Za-z} r:|.=* r:|=*' "$@" - "$hosts[@]"
+_description expl host
+compadd -M 'm:{a-zA-Z}={A-Za-z} r:|.=* r:|=*' "$@" "$expl[@]" - "$hosts[@]"
diff --git a/Completion/User/_make b/Completion/User/_make
index e9ee7979f..4c6095e95 100644
--- a/Completion/User/_make
+++ b/Completion/User/_make
@@ -1,6 +1,6 @@
 #compdef make gmake pmake
 
-local prev="$words[CURRENT-1]" file ret=1
+local prev="$words[CURRENT-1]" file ret=1 expl
 
 if [[ "$prev" = -[CI] ]]; then
   _files -/
@@ -18,7 +18,8 @@ else
     file=''
   fi
 
+  _description expl 'make target'
   [[ -n "$file" ]] &&
-    compadd - $(awk '/^[a-zA-Z0-9][^\/ 	]+:/ {print $1}' FS=: $file) && ret=0
+    compadd "$expl[@]" - $(awk '/^[a-zA-Z0-9][^\/ 	]+:/ {print $1}' FS=: $file) && ret=0
   (( ret )) && { compset -P 1 '*\='; _files }
 fi
diff --git a/Completion/User/_man b/Completion/User/_man
index 1a175506c..049fa7db7 100644
--- a/Completion/User/_man
+++ b/Completion/User/_man
@@ -2,7 +2,7 @@
 
 setopt localoptions rcexpandparam
 
-local rep
+local rep expl
 
 if [[ $words[2] = (<->*|ln) ]]; then
   rep=( $manpath/(man|cat)${words[2]}/$PREFIX*$SUFFIX.<->*(N:t:r) )
@@ -10,4 +10,5 @@ else
   rep=( $manpath/(man|cat)*/$PREFIX*$SUFFIX.<->*(N:t:r) )
 fi
 
-(( $#rep )) && compadd - $rep
+_description expl 'manual page'
+(( $#rep )) && compadd "$expl[@]" - $rep
diff --git a/Completion/User/_mh b/Completion/User/_mh
index f03e3d827..3a2e53794 100644
--- a/Completion/User/_mh
+++ b/Completion/User/_mh
@@ -8,7 +8,7 @@
 local mymhdir=~/Mail
 local mhlib=/usr/lib/mh
 
-local prev="$words[CURRENT-1]"
+local prev="$words[CURRENT-1]" expl
 
 # To be on the safe side, check this exists and if not, get it anyway.
 [[ -d $mymhdir ]] || mymhdir=$(mhpath +)
@@ -17,7 +17,8 @@ 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.
-  compadd - $($words[1] -help | perl -ne 'if (/^\s*-\(?(\S+)/) {
+  _description expl option
+  compadd "$expl[@]" - $($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";
@@ -35,9 +36,11 @@ elif compset -P 1 '[+@]' || [[ "$prev" = -draftfolder ]]; then
   fi
 
   # painless, or what?
-  _path_files -W mhpath -/
+  _description expl 'MH folder'
+  _path_files "$expl[@]" -W mhpath -/
 elif [[ "$prev" = -(editor|(whatnow|rmm|show|more)proc) ]]; then
-  compgen -c
+  _description expl command
+  compgen "$expl[@]" -c
 elif [[ "$prev" = -file ]]; then
   _files
 elif [[ "$prev" = -(form|audit|filter) ]]; then
@@ -48,11 +51,14 @@ elif [[ "$prev" = -(form|audit|filter) ]]; then
   [[ -d $mhlib ]] || { mhlib=$(mhparam mhlproc); mhlib=$mhlib:h; }
   mhfpath=($mymhdir $mhlib)
 
-  compgen -W mhfpath -g '*(.)'
+  _description expl 'MH template file'
+  compgen "$expl[@]" -W mhfpath -g '*(.)'
 elif [[ "$prev" = -(no|)cc ]]; then
-  compadd all to cc me
+  _description expl 'CC address'
+  compadd "$expl[@]" all to cc me
 elif [[ "$prev" = -[rw]cache ]]; then
-  compadd public private never ask
+  _description expl cache
+  compadd "$expl[@]" public private never ask
 else
   # Generate sequences.
   local foldnam folddir f ret
@@ -69,10 +75,11 @@ else
     # leaving foldnam empty works here
   fi
 
-  compadd $(mark $foldnam 2>/dev/null | awk -F: '{ print $1 }') &&
+  _description expl sequence
+  compadd "$expl[@]" $(mark $foldnam 2>/dev/null | awk -F: '{ print $1 }') &&
       ret=0
-  compadd reply next cur prev first last all unseen && ret=0
-  compgen -W folddir -g '<->' && ret=0
+  compadd "$expl[@]" reply next cur prev first last all unseen && ret=0
+  compgen "$expl[@]" -W folddir -g '<->' && ret=0
 
   return ret
 fi
diff --git a/Completion/User/_pdf b/Completion/User/_pdf
index 076b0d111..795e8545b 100644
--- a/Completion/User/_pdf
+++ b/Completion/User/_pdf
@@ -1,8 +1,11 @@
 #compdef acroread pdf2dsc pdf2ps pdfimages pdfinfo pdftopbm pdftops pdftotext xpdf
 
+local expl
+
 # ghostscript:
 #  pdf2dsc pdf2ps
 # xpdf:
 #  pdfimages pdfinfo pdftopbm pdftops pdftotext xpdf
 
-_files -g '*.(#i)pdf'
+_description expl 'PDF file'
+_files "$expl[@]" -g '*.(#i)pdf'
diff --git a/Completion/User/_ps b/Completion/User/_ps
index b91ba8a68..086443586 100644
--- a/Completion/User/_ps
+++ b/Completion/User/_ps
@@ -1,5 +1,7 @@
 #compdef ps2epsi ps2pdf epsffit extractres fixdlsrps fixfmps fixmacps fixpsditps fixpspps fixscribeps fixtpps fixwfwps fixwpps fixwwps includeres psbook psmerge psnup psresize psselect pstops psmulti pswrap lpr lp
 
+local expl
+
 # ghostscript:
 #  ps2epsi ps2pdf
 # psutils:
@@ -7,4 +9,5 @@
 #  fixscribeps fixtpps fixwfwps fixwpps fixwwps includeres psbook psmerge
 #  psnup psresize psselect pstops
 
-_files -g '*.(#i)(ps|eps)'
+_description expl 'postscript file'
+_files "$expl[@]" -g '*.(#i)(ps|eps)'
diff --git a/Completion/User/_pspdf b/Completion/User/_pspdf
index 014d81ce3..ecc4cf82b 100644
--- a/Completion/User/_pspdf
+++ b/Completion/User/_pspdf
@@ -1,6 +1,11 @@
 #compdef gs gsbj gsdj gsdj500 gslj gslp gsnd ps2ascii ghostview gv gview mgv ggv pstoedit pstotgif
 
+local ret=1
+
 # ghostscript:
 #  gs gsbj gsdj gsdj500 gslj gslp gsnd ps2ascii
 
-_files -g '*.(#i)(ps|eps|pdf)'
+_ps && ret=0
+_pdf && ret=0
+
+return ret
diff --git a/Completion/User/_rcs b/Completion/User/_rcs
index af66739cb..272e54681 100644
--- a/Completion/User/_rcs
+++ b/Completion/User/_rcs
@@ -5,8 +5,9 @@ local nm=$compstate[nmatches]
 [[ $words[1] = ci || $words[1] = rcs ]] && _files
 
 if [[ $compstate[nmatches] -eq nm && -d RCS && $words[1] != ci ]]; then
-  local rep
+  local rep expl
 
   rep=(RCS/$PREFIX*$SUFFIX,v(:t:s/\,v//))
-  (( $#rep )) && compadd - $rep
+  _description expl 'RCS file'
+  (( $#rep )) && compadd "$expl[@]" - $rep
 fi
diff --git a/Completion/User/_rlogin b/Completion/User/_rlogin
index 03af65382..8756ec42d 100644
--- a/Completion/User/_rlogin
+++ b/Completion/User/_rlogin
@@ -1,15 +1,19 @@
 #compdef rlogin rsh ssh
 
+local expl
+
+_description expl user
+
 if [[ CURRENT -eq 2 ]];
   if compset -P 1 '*@'; then
    _hosts
   else
     local nm=${compstate[nmatches]}
     _hosts
-    [[ nm -eq compstate[nmatches] ]] && compgen -S @ -u
+    [[ nm -eq compstate[nmatches] ]] && compgen "$expl[@]" -S @ -u
   fi
 elif [[ CURRENT -eq 3 ]]; then
   compadd - -l
 else
-  compgen -S @ -u
+  compgen "$expl[@]" -S @ -u
 fi
diff --git a/Completion/User/_strip b/Completion/User/_strip
index d9f44cc5e..529176fdd 100644
--- a/Completion/User/_strip
+++ b/Completion/User/_strip
@@ -1,3 +1,6 @@
 #compdef strip
 
-_files -g '*(*)'
+local expl
+
+_description expl executable
+_files "$expl[@]" -g '*(*)'
diff --git a/Completion/User/_stty b/Completion/User/_stty
index 6e2afcde8..45408fbc1 100644
--- a/Completion/User/_stty
+++ b/Completion/User/_stty
@@ -1,12 +1,16 @@
 #compdef stty
 
+local expl
+
 if [[ "$words[CURRENT-1]" = \
   (*erase|discard|status|dsusp|intr|kill|lnext|quit|reprint|start|s*p) ]]
 then
-     compadd '^-' '^h' '^?' '^c' '^u'
+  _description expl 'control character'
+  compadd "$expl[@]" '^-' '^h' '^?' '^c' '^u'
 else
+  _description expl setting
   compset -P '[-+]'
-  compadd rows columns intr quit erase kill eof eol \
+  compadd "$expl[@]" rows columns intr quit erase kill eof eol \
     eol2 start stop susp dsusp reprint discard werase lnext \
     parenb parodd cs8 cstopb hupcl cread clocal parext \
     ignbrk brkint ignpar parmrk inpck istrip inlcr igncr icrnl iuclc \
diff --git a/Completion/User/_su b/Completion/User/_su
index e5bf09d80..7b9744cd9 100644
--- a/Completion/User/_su
+++ b/Completion/User/_su
@@ -1,12 +1,13 @@
 #compdef su
 
-local shell comp name usr base
+local shell comp name usr base expl
 
 [[ $words[2] != - ]]
 (( base=$?+2 ))
 
 if [[ CURRENT -eq base ]]; then
-  compgen -u && return
+  _description expl user
+  compgen "$expl[@]" -u && return
   usr=root
 elif [[ CURRENT -ge base+1 ]]; then
   usr=$words[base]
@@ -14,9 +15,9 @@ else
   return
 fi
 
-shell=${"$(egrep "^$usr:" </etc/passwd)"##*:}
+shell="${${(M@)${(@f)$(</etc/passwd)}:#root*}##*:}"
 compset -n $base
 for name in $shell $shell:t -default-; do
   comp="$_comps[$name]"
-  [[ ! -z "$comp" ]] && "$comp" && return
+  [[ -n "$comp" ]] && "$comp" && return
 done  
diff --git a/Completion/User/_tar b/Completion/User/_tar
index 5fcce5c67..02551759a 100644
--- a/Completion/User/_tar
+++ b/Completion/User/_tar
@@ -72,11 +72,11 @@ if [[ "$PREFIX" = --* ]]; then
 
   # ...long options after `--'.
 
-  _long_options '--owner*'          "_tilde" \
-                '*=(PROG|COMMAND)*' "_command_names" \
-		'*=ARCHIVE*'        "_tar_archive" \
-		'*=NAME*'           "_files" \
-		'*=CONTROL*'        "[t numbered nil existing never simple]"
+  _long_options '--owner*:user:_tilde' \
+                '*=(PROG|COMMAND)*:program:_command_names' \
+		'*=ARCHIVE*:archive: _tar_archive' \
+		'*=NAME*:file:_files' \
+		'*=CONTROL*:version control:[t numbered nil existing never simple]'
 
 elif [[ ( CURRENT -gt 2 && "$words[CURRENT-1]" = -*f* &&
           "$words[CURRENT-1]" != --* ) ||
@@ -93,7 +93,7 @@ elif [[ ( "$_tar_cmd" = *[xt]* || -n $del ) && -n "$tf" ]]; then
   # filenames cached, plus the name of the tarfile so we know if it
   # changes.
 
-  local largs=-tf
+  local largs=-tf expl
 
   if [[ $_tar_cmd = *z* ]]; then
     largs=-tzf
@@ -110,7 +110,8 @@ elif [[ ( "$_tar_cmd" = *[xt]* || -n $del ) && -n "$tf" ]]; then
     _tar_cache_name=$tf
   fi
 
-  _multi_parts / _tar_cache_list
+  _description expl 'file from archive'
+  _multi_parts "$expl[@]" / _tar_cache_list
 else
   
   # See if we should use a path prefix.  We have to use eval as the dir can
diff --git a/Completion/User/_tar_archive b/Completion/User/_tar_archive
index 58e436c4d..9ddf434f5 100644
--- a/Completion/User/_tar_archive
+++ b/Completion/User/_tar_archive
@@ -7,14 +7,18 @@
 # If your version of `tar' supports this you may want to complete
 # things like `host:file' or `user@host:file' here.
 
+local expl
+
 [[ $# -eq 0 && $+_tar_cmd -ne 0 ]] && set "$_tar_cmd"
 
+_description expl 'archive file'
+
 if [[ "$1" = *[tx]* ]]; then
   if [[ "$1" = *[zZ]* ]]; then
-    _files -g '*.((tar|TAR).(gz|GZ|Z)|.tgz)'
+    _files "$expl[@]" -g '*.((tar|TAR).(gz|GZ|Z)|.tgz)'
   else
-    _files -g '*.(tar|TAR)'
+    _files "$expl[@]" -g '*.(tar|TAR)'
   fi
 else
-  _files
+  _files "$expl[@]"
 fi
diff --git a/Completion/User/_tex b/Completion/User/_tex
index ac926cfbe..d270c785a 100644
--- a/Completion/User/_tex
+++ b/Completion/User/_tex
@@ -1,3 +1,6 @@
 #compdef tex latex slitex
 
-_files -g '*.(tex|TEX|texinfo|texi)'
+local expl
+
+_description expl 'TeX or LaTeX file'
+_files "$expl[@]" -g '*.(tex|TEX|texinfo|texi)'
diff --git a/Completion/User/_uncompress b/Completion/User/_uncompress
index 0aa1e073f..5392d8fe9 100644
--- a/Completion/User/_uncompress
+++ b/Completion/User/_uncompress
@@ -1,3 +1,6 @@
 #compdef uncompress zmore
 
+local expl
+
+_description expl 'compressed file'
 _files -g '*.Z'
diff --git a/Completion/User/_use_lo b/Completion/User/_use_lo
index e469154ea..a22a5fdb2 100644
--- a/Completion/User/_use_lo
+++ b/Completion/User/_use_lo
@@ -3,8 +3,4 @@
 # This is for GNU-like commands which understand the --help option,
 # but which do not otherwise require special completion handling.
 
-if [[ $PREFIX = --* ]]; then
-  _long_options
-else
-  _default
-fi
+_long_options -t || _default
diff --git a/Completion/User/_x_options b/Completion/User/_x_options
index 9c3a303bb..4e6b6ba80 100644
--- a/Completion/User/_x_options
+++ b/Completion/User/_x_options
@@ -1,10 +1,13 @@
 #compdef -p */X11/*
 
+local expl
+
 # A simple pattern completion, just as an example.
 
 if [ "$words[CURRENT-1]" = "-display" ]; then
   _compskip=all
   _hosts -S ':0 ' -r :
 else
-  compadd -J options - -display -name -xrm
+  _description expl option  
+  compadd "$expl[@]" - -display -name -xrm
 fi
diff --git a/Completion/User/_xfig b/Completion/User/_xfig
index a3b30bb81..f1c2ca6f5 100644
--- a/Completion/User/_xfig
+++ b/Completion/User/_xfig
@@ -1,3 +1,6 @@
 #compdef xfig
 
-_files -g '*.fig'
+local expl
+
+_description expl 'xfig file'
+_files "$expl[@]" -g '*.fig'
diff --git a/Completion/User/_xsetroot b/Completion/User/_xsetroot
index 74a0b6180..adce06d08 100644
--- a/Completion/User/_xsetroot
+++ b/Completion/User/_xsetroot
@@ -1,15 +1,22 @@
 #compdef xsetroot
 
+local expl
+
 case "$words[CURRENT-1]" in
--cursor) _files -/g '*.(#i)(xbm|curs(|or))'; return;;
 -cursor_name) _cursors; return;;
--bitmap) _files -/g '*.(#i)xbm'; return;;
 -([fb]g|solid)) _colors; return;;
+-cursor) _description expl 'cursor file'
+         _files "$expl[@]" -/g '*.(#i)(xbm|curs(|or))'; return;;
+-bitmap) _description expl 'bitmap file'
+         _files "$expl[@]" -/g '*.(#i)xbm'; return;;
 esac
 
 if [[ CURRENT -gt 2 && "$words[CURRENT-2]" = -cursor ]]; then
-  _files -/g '*.(#i)(xbm|curs(|or)|mask)'
+  _description expl 'cursor mask file'
+  _files "$expl[@]" -/g '*.(#i)(xbm|curs(|or)|mask)'
 else
-  compadd -M 'm:-=_ r:|_=*' - -help -def -cursor -cursor_name -bitmap -mod -gray -grey \
-                       -fg -bg -rv -solid -name
+  _description expl option
+  compadd "$expl[@]" -M 'm:-=_ r:|_=*' - \
+          -help -def -cursor -cursor_name -bitmap -mod -gray -grey \
+          -fg -bg -rv -solid -name
 fi
diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo
index 025003675..4f1b70c6e 100644
--- a/Doc/Zsh/compsys.yo
+++ b/Doc/Zsh/compsys.yo
@@ -151,6 +151,10 @@ called when completing for a command whose name matches the given
 var(pattern) (a standard globbing pattern).  Note that only one
 var(pattern) may be given.
 )
+item(tt(#compdef -P) var(pattern))(
+Like the previous one, but the function will be called only if no
+completion function for the command on the line could be found.
+)
 item(tt(#compdef -k) var(style key-sequences...))(
 This can be used to bind special completion functions to the
 var(key-sequences).  It creates a widget behaving like the builtin widget
@@ -195,6 +199,7 @@ startitem()
 xitem(tt(compdef) [ tt(-an) ] var(function names...))
 xitem(tt(compdef -d) var(names...))
 xitem(tt(compdef -p) [ tt(-a) ] var(function pattern))
+xitem(tt(compdef -P) [ tt(-a) ] var(function pattern))
 item(tt(compdef -k) [ tt(-a) ] var(function style key-sequences...))(
 The first form tells the completion system to call the given
 var(function) when completing for the contexts or commands
@@ -207,7 +212,12 @@ The third form is similar to the first, but var(function) will be called
 for all commands whose name matches the var(pattern); this is like the
 tt(#compdef -p) function tag.
 
-The fourth form defines a widget with the same name as the var(function)
+The fourth form is like the third, but the var(function) will be
+called only if no function for the command itself was found or if one
+was found and it set the tt(_compskip) parameter to a value em(not)
+containing the sub-string `tt(patterns)'.
+
+The fifth form defines a widget with the same name as the var(function)
 which will be called for each of the var(key-sequences); this is like the
 tt(#compdef -k) tag.  The function should generate the completions needed
 and will otherwise behave like the builtin widget whose name is given as
@@ -694,6 +704,37 @@ tt(-first-) context. With this
 one can write a pattern completion function that keeps other functions 
 from being tried simply by setting this parameter to any value.
 )
+item(tt(_description))(
+This function gets two arguments: the name of an array and a
+string. It tests if the configuration key tt(description_format) is
+set and if it is, it stores some options in the array that can then be 
+given to the tt(compadd) and tt(compgen) builtin commands to make the
+value of the tt(description_format) key (with the sequence `tt(%d)'
+replaced by the string given as the second argument) be displayed
+above the matches added. These options also will make sure that the
+matches are placed in a separate group (the second argument is used as 
+the name of the group) if the configuration key tt(group_matches) is
+set to a non-empty string. Normally a sorted group will be used for this
+(with the `tt(-J)' option), but if the option `tt(-V)' is given, a
+unsorted group will be used instead.
+
+In most cases, this function will be used like this:
+
+example(local expl
+_description expl file
+compadd "$expl[@]" - "$files[@]")
+)
+item(tt(_message))(
+This function takes one argument which is used like the second
+argument to the tt(_description) function. However, the resulting
+string will always be shown, not only if some matches were
+generated. This is useful to display help texts in places where no
+completions can be generated automatically.
+
+This function also uses the configuration key tt(message_format) in
+preference to tt(description_format). The latter is used only if the
+former is unset or set to the empty string.
+)
 item(tt(_multi_parts))(
 This function gets two arguments: a separator character and an
 array.  As usual, the array may be either the
@@ -791,19 +832,21 @@ names. Note that this means that you should be careful to make sure
 that this function is not called for a command that does not support
 this option.
 
-For options that get an argument after a `tt(=)', the function also
-automatically tries to find out what should be completed as the argument.
+For options that get an argument after a `tt(=)', the function also tries
+to automatically find out what should be completed as the argument.
 The possible completions for option-arguments can be described with
-the arguments to this function. This is done by giving pairs of
-patterns and actions as consecutive arguments. The actions specify
-what should be done to complete arguments of those options whose
-description match the pattern. The action may be a list of words in
-brackets or in parentheses, separated by spaces. A list in square brackets
-denotes possible values for an optional argument, a list in parentheses
+the arguments to this function. Each argument contains one description
+of the form <pattern>:<message>:<action>. The message will be printed 
+above the possible completion if the `description_format' configuration
+key is set (see above). The actions specify what
+should be done to complete arguments of those options that match 
+the pattern. The action may be a list of words in brackets or in
+parentheses, separated by spaces. A list in brackets denotes
+possible values for an optional argument, a list in parentheses
 gives words to complete for mandatory arguments. If the action does
-not start with a square bracket or parenthesis, it should be the name of a
+not start with a bracket or parentheses, it should be the name of a
 command (probably with arguments) that should be invoked to complete 
-after the equal sign. Example:
+after the equal sign. E.g.:
 
 example(_long_options '*\*'     '(yes no)' \ 
               '*=FILE*' '_files' \ 
@@ -818,8 +861,7 @@ for option descriptions containing `tt(=FILE)' and paths for option
 descriptions that contain `tt(=DIR)' or `tt(=PATH)'. These builtin
 patterns can be overridden by patterns given as arguments, however.
 
-This function also accepts the `tt(-X)', `tt(-J)', and `tt(-V)'
-options which are passed unchanged to `tt(compadd)'. If the
+If the
 option `tt(-t)' is given, completion is only done on words starting
 with two hyphens. The option `tt(-i) var(patterns)' can be used to
 give patterns for options which should not be completed. The patterns
@@ -833,6 +875,102 @@ replacement. E.g. some tt(configure)-scripts describe options only as
 completion of the second form, one would use
 `tt(-s "(#--enable- --disable-)")'.
 )
+item(tt(_arguments))(
+Like tt(_long_options), this function is in the tt(Base) subdirectory.
+
+This function can be used to complete words on the line by simply
+describing the arguments the command on the line gets. The description 
+is given as arguments to this function, with each argument describing
+one option or normal argument of the command. The descriptions
+understood are:
+
+startitem()
+item(var(n)tt(:)var(message)tt(:)var(action))(
+This describes the var(n)'th normal argument. The var(message) will be 
+printed above the matches generated and the var(action) says what can
+be completed in this position (see below).
+)
+item(tt(:)var(message)tt(:)var(action))(
+Like the previous one, but describing the em(next) argument. I.e. if
+you want to describe all arguments a command can get, you can leave
+out the numbers in the description and just use this form to describe
+them one after another in the order they have to appear on the line.
+)
+item(tt(*:)var(message)tt(:)var(action))(
+This describes how arguments are to be completed for which no
+description with one of the first two forms was given. This also means 
+that any number of arguments can be completed.
+)
+item(var(opt-spec)[var(description) ...])(
+This describes an option and (if at least one var(description) is
+given) the arguments that have to come after the option. If no
+var(description) is given, this will only be used to offer the option
+name as a possible completion in the right places. Each
+var(description) has to be of the form
+`tt(:)var(message)tt(:)var(action)' or
+`tt(::)var(message)tt(:)var(action)', where the second form describes
+an optional argument and the first one describes a mandatory argument.
+
+In the simplest form the var(opt-spec) is just the option name
+beginning with a minus or a plus sign, such as `tt(-foo)'. In this
+case, the first argument for the option (if any) has to come as a
+separate word directly after the option and the option may appear only 
+once on the line (and if it is already on the line, the option name
+will not be offered as a possible completion again). If the first
+argument for the option has to come directly after the option name
+em(in the same word), a minus sign should be added to the end of the
+var(opt-spec), as in `tt(-foo-)'. If the first argument may be given
+in one string with the option name, but may also be given as a
+separate argument after the option, a plus sign should be used
+instead. Finally, if the option may be given more than once, a star
+(`tt(*)') should be added in front of the var(opt-spec).
+enditem()
+
+In each of the cases above, the var(action) says how the possible
+completions should be generated. In cases where only one of a fixed
+set of strings can be completed, these string can directly be given as 
+a list in parentheses, as in `tt(:foo:(foo bar baz))'. If the
+var(action) does not begin with an opening parentheses, it will be
+split into separate words and executed. If the var(action) starts with 
+a space, this list of words will be invoked unchanged, otherwise it
+will be invoked with some extra string placed after the first word
+which can be given as arguments to the tt(compadd) and tt(compgen)
+builtins and which make sure that the var(message) given in the
+description will be shown above the matches.
+
+Finally, this function can be made to automatically call the
+tt(_long_options) function where appropriate by giving it the string
+`tt(--)' as an argument. All arguments after this will be given
+unchanged to the tt(_long_options) function.
+
+Example:
+
+example(_arguments '-l+:left border:' \
+           '-format:paper size:(letter A4)' \
+	   '*-copy:output file:_files::resolution:(300 600)' \
+	   ':postscript file:_files -g *.(ps|eps)' \
+	   '*:page number:')
+
+This describes three options `tt(-l)', `tt(-format)', and
+`tt(-copy)'. The first one gets one argument described as `var(left
+border)' for which no completion will be offered because of the empty
+action. The argument may come directly after the `tt(-l)' or it may be 
+given as the next word on the line. The `tt(-format)' option gets one
+argument (in the next word) described as `var(paper size)' for which
+only the strings `tt(letter)' and `tt(A4)' will be completed. The
+`tt(-copy)' option differs from the first two in that it may appear
+more than once on the command line and in that it accepts two
+arguments. The first one is mandatory and will be completed as a
+filename. The second one is optional (because of the second colon
+before the description `var(resolution)') and will be completed from
+the strings `tt(300)' and `tt(600)'.
+
+The last two descriptions say what should be completed as
+arguments. The first one describes the first argument as a
+`var(postscript file)' and makes files ending in `tt(ps)' or `tt(eps)' 
+be completed. The last description says that all other arguments are
+`var(page numbers)' but does not give possible completions.
+)
 enditem()
 
 texinode(Completion Directories)(Bindable Commands)(Completion Functions)(Completion System)
diff --git a/Doc/Zsh/mod_parameter.yo b/Doc/Zsh/mod_parameter.yo
index 4fe537c6d..3640e39d8 100644
--- a/Doc/Zsh/mod_parameter.yo
+++ b/Doc/Zsh/mod_parameter.yo
@@ -16,7 +16,7 @@ the option, respectively. Unsetting a key in this array is like
 setting it to the value tt(off).
 )
 vindex(commands)
-item(tt(command))(
+item(tt(commands))(
 This array gives access to the command hash table. The keys are the
 names of external commands, the values are the pathnames of the files
 that would be executed when the command would be invoked. Setting a