about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSven Wischnowsky <wischnow@users.sourceforge.net>2002-03-04 08:53:41 +0000
committerSven Wischnowsky <wischnow@users.sourceforge.net>2002-03-04 08:53:41 +0000
commitf56ba813bb92b1d61be91cb39df620b37a5a0588 (patch)
tree6b7432b8e437bfbd92b7859e0c9e38dd11277f1d
parent10490ec499fff7b932f92a0b19c7e5343a24761d (diff)
downloadzsh-f56ba813bb92b1d61be91cb39df620b37a5a0588.tar.gz
zsh-f56ba813bb92b1d61be91cb39df620b37a5a0588.tar.xz
zsh-f56ba813bb92b1d61be91cb39df620b37a5a0588.zip
allow different sets of completion definitions selected with option -T to compdef; use this for parameter values and redirections (16755)
-rw-r--r--ChangeLog19
-rw-r--r--Completion/Base/Completer/_complete8
-rw-r--r--Completion/Base/Core/_dispatch98
-rw-r--r--Completion/Base/Core/_normal123
-rw-r--r--Completion/Base/Utility/_contexts23
-rw-r--r--Completion/Base/Utility/_set_command31
-rw-r--r--Completion/Unix/Command/_gcc24
-rw-r--r--Completion/Unix/Command/_su2
-rw-r--r--Completion/Unix/Type/_files2
-rw-r--r--Completion/Unix/Type/_printers2
-rw-r--r--Completion/Unix/Type/_terminals2
-rw-r--r--Completion/Unix/Type/_time_zone2
-rw-r--r--Completion/X/Type/_x_display2
-rw-r--r--Completion/Zsh/Command/_compdef1
-rw-r--r--Completion/Zsh/Context/_default2
-rw-r--r--Completion/Zsh/Context/_in_vared2
-rw-r--r--Completion/Zsh/Context/_redirect16
-rw-r--r--Completion/Zsh/Context/_subscript2
-rw-r--r--Completion/Zsh/Context/_value83
-rw-r--r--Completion/compdump61
-rw-r--r--Completion/compinit189
-rw-r--r--Doc/Zsh/compsys.yo77
22 files changed, 471 insertions, 300 deletions
diff --git a/ChangeLog b/ChangeLog
index e10fccc38..86ad59746 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2002-03-04  Sven Wischnowsky  <wischnow@zsh.org>
+
+	* 16755: Completion/compdump, Completion/compinit,
+	Completion/Base/Completer/_complete,
+	Completion/Base/Core/_dispatch, Completion/Base/Core/_normal,
+	Completion/Base/Utility/_contexts,
+	Completion/Base/Utility/_set_command,
+	Completion/Unix/Command/_gcc, Completion/Unix/Command/_su,
+	Completion/Unix/Type/_files, Completion/Unix/Type/_printers,
+	Completion/Unix/Type/_terminals, Completion/Unix/Type/_time_zone,
+	Completion/X/Type/_x_display, Completion/Zsh/Command/_compdef,
+	Completion/Zsh/Context/_default,
+	Completion/Zsh/Context/_in_vared,
+	Completion/Zsh/Context/_redirect,
+	Completion/Zsh/Context/_subscript, Completion/Zsh/Context/_value,
+	Doc/Zsh/compsys.yo: allow different sets of completion
+	definitions selected with option -T to compdef; use this for
+	parameter values and redirections
+
 2002-03-01  Sven Wischnowsky  <wischnow@zsh.org>
 
 	* 16751: Src/Zle/comp.h, Src/Zle/compcore.c, Src/Zle/complete.c,
diff --git a/Completion/Base/Completer/_complete b/Completion/Base/Completer/_complete
index 16e0f5e9f..23670f7c0 100644
--- a/Completion/Base/Completer/_complete
+++ b/Completion/Base/Completer/_complete
@@ -95,7 +95,7 @@ fi
 
 comp="$_comps[-first-]"
 if [[ -n "$comp" ]]; then
-  service="${_services[-first-]:--first-}"
+  service="${_servicecomps[-first-]:--first-}"
   ccarray[3]=-first-
   eval "$comp" && ret=0
   if [[ "$_compskip" = all ]]; then
@@ -124,7 +124,7 @@ else
   ccarray[3]="$cname"
 
   comp="$_comps[$cname]"
-  service="${_services[$cname]:-$cname}"
+  service="${_servicecomps[$cname]:-$cname}"
 
   # If not, we use default completion, if any.
 
@@ -134,9 +134,9 @@ else
       return 1
     fi
     comp="$_comps[-default-]"
+    service="${_servicecomps[-default-]:--default-}"
   fi
-  [[ -n "$comp" ]] &&
-      service="${_services[-default-]:--default-}" && eval "$comp" && ret=0
+  [[ -n "$comp" ]] && eval "$comp" && ret=0
 fi
 
 _compskip=
diff --git a/Completion/Base/Core/_dispatch b/Completion/Base/Core/_dispatch
new file mode 100644
index 000000000..124aea112
--- /dev/null
+++ b/Completion/Base/Core/_dispatch
@@ -0,0 +1,98 @@
+#autoload
+
+local comp pat val name i ret=1 _compskip="$_compskip"
+local curcontext="$curcontext" service str comptype noskip def
+local __comps __patcomps __postpatcomps __services
+
+# If we get the option `-s', we don't reset `_compskip'.
+
+while [[ "$1" = -[sd] ]]; do
+  if [[ "$1" = -s ]]; then
+    noskip=yes
+  else
+    def=yes
+  fi
+  shift
+done
+
+[[ -z "$noskip" ]] && _compskip=
+
+comptype=$1
+
+__comps=_$1
+
+(( ${(P)+__comps} )) || return 1
+
+__patcomps=_pat$1
+__postpatcomps=_postpat$1
+__services=_service$1
+
+shift
+
+# See if there are any matching pattern completions.
+
+if [[ "$_compskip" != (all|*patterns*) ]]; then
+
+  for str in "$@"; do
+    [[ -n "$str" ]] || continue
+    service="${${(e):-\$${__services}[\$str]}:-$str}"
+    for i in "${(@e):-\$${__patcomps}[(K)\$str]}"; do
+      "$i" && ret=0
+      if [[ "$_compskip" = *patterns* ]]; then
+        break
+      elif [[ "$_compskip" = all ]]; then
+        _compskip=''
+        return ret
+      fi
+    done
+  done
+fi
+
+# Now look up the names in the normal completion array.
+
+ret=1
+for str in "$@"; do
+  [[ -n "$str" ]] || continue
+  name="$str"
+  comp="${(e):-\$${__comps}[\$str]}"
+  service="${${(e):-\$${__services}[\$str]}:-$str}"
+
+  [[ -z "$comp" ]] || break
+done
+
+# And generate the matches, probably using default completion.
+
+if [[ -n "$comp" ]]; then
+  _compskip=patterns
+  eval "$comp" && ret=0
+  [[ "$_compskip" = (all|*patterns*) ]] && return ret
+elif [[ "$_compskip" != *default* ]]; then
+  name=-default-
+  comp="${(e):-\$${__comps}[-default-]}"
+fi
+
+if [[ "$_compskip" != (all|*patterns*) ]]; then
+  for str; do
+    [[ -n "$str" ]] || continue
+    service="${${(e):-\$${__services}[\$str]}:-$str}"
+    for i in "${(@e):-\$${__postpatcomps}[(K)\$str]}"; do
+      _compskip=default
+      "$i" && ret=0
+      if [[ "$_compskip" = *patterns* ]]; then
+        break
+      elif [[ "$_compskip" = all ]]; then
+        _compskip=''
+        return ret
+      fi
+    done
+  done
+fi
+
+[[ "$name" = -default- && -n "$comp" &&
+   "$_compskip" != (all|*default*) ]] &&
+  service="${${(e):-\$${__services}[-default-]}:--default-}" &&
+   eval "$comp" && ret=0
+
+_compskip=''
+
+return ret
diff --git a/Completion/Base/Core/_normal b/Completion/Base/Core/_normal
index 9ddfab1cd..028687fd1 100644
--- a/Completion/Base/Core/_normal
+++ b/Completion/Base/Core/_normal
@@ -1,20 +1,16 @@
 #compdef -command-line-
 
-local comp command cmd1 cmd2 pat val name i ret=1 _compskip="$_compskip"
-local curcontext="$curcontext" service
+local _comp_command1 _comp_command2 skip
 
-# If we get the option `-s', we don't reset `_compskip'. This ensures
-# that a value set in the function for the `-first-' context is kept,
-# but that we still use pattern functions when we were called form
-# another completion function.
-
-[[ "$1" = -s ]] || _compskip=''
+if [[ "$1" = -s ]]; then
+  skip=(-s)
+else
+  skip=()
+  _compskip=''
+fi
 
-# Completing in command position? If not we set up `cmd1' and `cmd2' as
-# two strings we have to search in the completion definition arrays (e.g.
-# a path and the last path name component).
+# Completing in command position?
 
-command="$words[1]"
 if [[ CURRENT -eq 1 ]]; then
   curcontext="${curcontext%:*:*}:-command-:"
 
@@ -22,107 +18,8 @@ if [[ CURRENT -eq 1 ]]; then
   [[ -n "$comp" ]] && eval "$comp" && ret=0
 
   return ret
-else
-  if (( $+builtins[$command] + $+functions[$command] )); then
-    cmd1="$command"
-    curcontext="${curcontext%:*:*}:${cmd1}:"
-  elif [[ "$command[1]" = '=' ]]; then
-    eval cmd1\=$command
-    cmd2="$command[2,-1]"
-    curcontext="${curcontext%:*:*}:${cmd2}:"
-  elif [[ "$command" = ..#/* ]]; then
-    cmd1="${PWD}/$command"
-    cmd2="${command:t}"
-    curcontext="${curcontext%:*:*}:${cmd2}:"
-  elif [[ "$command" = */* ]]; then
-    cmd1="$command"
-    cmd2="${command:t}"
-    curcontext="${curcontext%:*:*}:${cmd2}:"
-  else
-    cmd1="$command"
-    cmd2="$commands[$command]"
-    curcontext="${curcontext%:*:*}:${cmd1}:"
-  fi
-fi
-
-# See if there are any matching pattern completions.
-
-if [[ "$_compskip" != (all|*patterns*) ]]; then
-  service="${_services[$cmd1]:-$cmd1}"
-  for i in "${(@)_patcomps[(K)$cmd1]}"; do
-    "$i" && ret=0
-    if [[ "$_compskip" = *patterns* ]]; then
-      break
-    elif [[ "$_compskip" = all ]]; then
-      _compskip=''
-      return ret
-    fi
-  done
-  if [[ -n "$cmd2" ]]; then
-    service="${_services[$cmd2]:-$cmd2}"
-    for i in "${(@)_patcomps[(K)$cmd2]}"; do
-      "$i" && ret=0
-      if [[ "$_compskip" = *patterns* ]]; then
-        break
-      elif [[ "$_compskip" = all ]]; then
-        _compskip=''
-        return ret
-      fi
-    done
-  fi
-fi
-
-# Now look up the two names in the normal completion array.
-
-ret=1
-name="$cmd1"
-comp="$_comps[$cmd1]"
-service="${_services[$cmd1]:-$cmd1}"
-
-[[ -z "$comp" ]] &&
-    name="$cmd2" comp="$_comps[$cmd2]" service="${_services[$cmd2]:-$cmd2}"
-
-# And generate the matches, probably using default completion.
-
-if [[ -n "$comp" ]]; then
-  _compskip=patterns
-  eval "$comp" && ret=0
-  [[ "$_compskip" = (all|*patterns*) ]] && return ret
-elif [[ "$_compskip" != *default* ]]; then
-  name=-default-
-  comp="$_comps[-default-]"
-fi
-
-if [[ "$_compskip" != (all|*patterns*) ]]; then
-  service="${_services[$cmd1]:-$cmd1}"
-  for i in "${(@)_postpatcomps[(K)$cmd1]}"; do
-    _compskip=default
-    "$i" && ret=0
-    if [[ "$_compskip" = *patterns* ]]; then
-      break
-    elif [[ "$_compskip" = all ]]; then
-      _compskip=''
-      return ret
-    fi
-  done
-  if [[ -n "$cmd2" ]]; then
-    service="${_services[$cmd2]:-$cmd2}"
-    for i in "${(@)_postpatcomps[(K)$cmd2]}"; do
-      _compskip=default
-      "$i" && ret=0
-      if [[ "$_compskip" = *patterns* ]]; then
-        break
-      elif [[ "$_compskip" = all ]]; then
-        _compskip=''
-        return ret
-      fi
-    done
-  fi
 fi
 
-[[ "$name" = -default- && -n "$comp" && "$_compskip" != (all|*default*) ]] &&
-  service="${_services[-default-]:--default-}" && eval "$comp" && ret=0
-
-_compskip=''
+_set_command
 
-return ret
+_dispatch -d "$skip[@]" comps "$_comp_command1" "$_comp_command2"
diff --git a/Completion/Base/Utility/_contexts b/Completion/Base/Utility/_contexts
deleted file mode 100644
index f0e5ba874..000000000
--- a/Completion/Base/Utility/_contexts
+++ /dev/null
@@ -1,23 +0,0 @@
-#autoload
-
-# This searches $* in the array for normal completions and calls the result.
-# It is used to include completions for another command or special context
-# into the list generated by the calling function.
-# For example the function for `-subscript-' could call this as in
-# `_contexts -math-' to get the completions that would be generated for a
-# mathematical context.
-
-local i tmp ret=1 service or
-
-if [[ $1 = -o ]]; then
-  or=yes
-  shift
-fi
-
-for i; do
-  tmp="$_comps[$i]"
-  [[ -n "$tmp" ]] && service="${_services[$i]:-$i}" && eval "$tmp" && ret=0
-  [[ -n "$or" && ret -eq 0 ]] && return 0
-done
-
-return ret
diff --git a/Completion/Base/Utility/_set_command b/Completion/Base/Utility/_set_command
new file mode 100644
index 000000000..daf532686
--- /dev/null
+++ b/Completion/Base/Utility/_set_command
@@ -0,0 +1,31 @@
+#autoload
+
+# This sets the parameters _comp_command1 and _comp_command2 in the
+# calling function.
+
+local command
+
+command="$words[1]"
+
+[[ -z "$command" ]] && return
+
+if (( $+builtins[$command] + $+functions[$command] )); then
+  _comp_command1="$command"
+  curcontext="${curcontext%:*:*}:${_comp_command1}:"
+elif [[ "$command[1]" = '=' ]]; then
+  eval _comp_command2\=$command
+  _comp_command1="$command[2,-1]"
+  curcontext="${curcontext%:*:*}:${_comp_command2}:"
+elif [[ "$command" = ..#/* ]]; then
+  _comp_command1="${PWD}/$command"
+  _comp_command2="${command:t}"
+  curcontext="${curcontext%:*:*}:${_comp_command2}:"
+elif [[ "$command" = */* ]]; then
+  _comp_command1="$command"
+  _comp_command2="${command:t}"
+  curcontext="${curcontext%:*:*}:${_comp_command2}:"
+else
+  _comp_command1="$command"
+  _comp_command2="$commands[$command]"
+  curcontext="${curcontext%:*:*}:${_comp_command1}:"
+fi
diff --git a/Completion/Unix/Command/_gcc b/Completion/Unix/Command/_gcc
index e6c81e408..f297126d1 100644
--- a/Completion/Unix/Command/_gcc
+++ b/Completion/Unix/Command/_gcc
@@ -1,8 +1,21 @@
-#compdef gcc
+#compdef gcc g++ -T values LDFLAGS CFLAGS CPPFLAGS
 
-local curcontext="$curcontext" state line ret=1 expl args
+local curcontext="$curcontext" state line ret=1 expl args args2
 typeset -A opt_args
 
+if [[ "$comptype" = values ]]; then
+  compset -q
+  words=( fake "$words[@]" )
+  (( CURRENT++ ))
+  if ("$service" = LDFLAGS ]]; then
+    args2=( '-R:runtime path:->rundir' )
+  else
+    args2=()
+  fi
+else
+  args2=( '*:input file:_files -g \*.\(\[cCmisSoak\]\|cc\|cxx\|ii\|k\[ih\]\)' )
+fi
+
 args=()
 case $MACHTYPE in
 m68*)
@@ -243,7 +256,7 @@ _arguments -C -M 'L:|-{fW}no-=-{fW} r:|[_-]=* r:|=*' \
   -freg-struct-return -fshared-data -fshort-enums \
   -fshort-double -fvolatile -fvolatile-global \
   -fverbose-asm -fpack-struct \
-  '*:input file:_files -g \*.\(\[cCmisSoak\]\|cc\|cxx\|ii\|k\[ih\]\)' && ret=0
+  "$args2[@]" && ret=0
 
 
 case "$state" in
@@ -276,6 +289,11 @@ library)
   _wanted libraries expl library \
       compadd - ${^=LD_LIBRARY_PATH:-/usr/lib /usr/local/lib}/lib*.(a|so*)(:t:fr:s/lib//) && ret=0
   ;;
+rundir)
+  compset -P '*:'
+  compset -S ':*'
+  _files -/ -S/ -r '\n\t\- /:' "$@"
+  ;;
 esac
 
 return ret
diff --git a/Completion/Unix/Command/_su b/Completion/Unix/Command/_su
index d8ed17183..a1dd69db8 100644
--- a/Completion/Unix/Command/_su
+++ b/Completion/Unix/Command/_su
@@ -17,4 +17,4 @@ fi
 shell="${${(M@)${(@f)$(</etc/passwd)}:#$usr*}##*:}"
 compset -n $base
 
-_contexts -o $shell $shell:t -default-
+_dispatch comps $shell $shell:t -default-
diff --git a/Completion/Unix/Type/_files b/Completion/Unix/Type/_files
index fa98ce574..4a57cdbc7 100644
--- a/Completion/Unix/Type/_files
+++ b/Completion/Unix/Type/_files
@@ -1,4 +1,4 @@
-#autoload
+#compdef -T redirs -default-
 
 local opts tmp glob pat pats expl tag i def descr end ign ret=1 match tried
 local type sdef
diff --git a/Completion/Unix/Type/_printers b/Completion/Unix/Type/_printers
index 03f950c9c..7229c1dc6 100644
--- a/Completion/Unix/Type/_printers
+++ b/Completion/Unix/Type/_printers
@@ -1,4 +1,4 @@
-#autoload
+#compdef -T values PRINTER LPDEST
 
 local expl ret=1 list disp sep
 
diff --git a/Completion/Unix/Type/_terminals b/Completion/Unix/Type/_terminals
index 7dbfeeba5..039430ad5 100644
--- a/Completion/Unix/Type/_terminals
+++ b/Completion/Unix/Type/_terminals
@@ -1,4 +1,4 @@
-#compdef infocmp
+#compdef infocmp -T values TERM
 
 local desc expl
 
diff --git a/Completion/Unix/Type/_time_zone b/Completion/Unix/Type/_time_zone
index 1ae921b61..215d8bd4a 100644
--- a/Completion/Unix/Type/_time_zone
+++ b/Completion/Unix/Type/_time_zone
@@ -1,4 +1,4 @@
-#compdef
+#compdef -T values TZ
 
 local expl
 
diff --git a/Completion/X/Type/_x_display b/Completion/X/Type/_x_display
index f547a64fa..647ff1f5a 100644
--- a/Completion/X/Type/_x_display
+++ b/Completion/X/Type/_x_display
@@ -1,3 +1,3 @@
-#autoload
+#compdef -T values DISPLAY
 
 _tags displays && _hosts -S ':0 ' -r :
diff --git a/Completion/Zsh/Command/_compdef b/Completion/Zsh/Command/_compdef
index eb1a2ebb6..db4309642 100644
--- a/Completion/Zsh/Command/_compdef
+++ b/Completion/Zsh/Command/_compdef
@@ -6,6 +6,7 @@ typeset -A opt_args
 _arguments -C -s -A "-*" -S \
   '(-d)-a[make function autoloadable]' \
   '(-d -p -P)-n[leave existing definitions intact]' \
+  "*-T[select type of completion function]:completion function type:($_comp_assocs)" \
   ':completion function:->cfun' \
   '*:commands: _command_names' \
  - d \
diff --git a/Completion/Zsh/Context/_default b/Completion/Zsh/Context/_default
index 8176f392c..81744cdef 100644
--- a/Completion/Zsh/Context/_default
+++ b/Completion/Zsh/Context/_default
@@ -19,7 +19,7 @@ _files "$@" && return 0
 # allow completion to handle file names after any equals sign.
 
 if [[ -o magicequalsubst && "$PREFIX" = *\=* ]]; then
-  compstate[parameter]="${words[1]:t}-${PREFIX%%\=*}"
+  compstate[parameter]="${PREFIX%%\=*}"
   compset -P 1 '*='
   _value "$@"
 else
diff --git a/Completion/Zsh/Context/_in_vared b/Completion/Zsh/Context/_in_vared
index abd24dd95..03f6d404e 100644
--- a/Completion/Zsh/Context/_in_vared
+++ b/Completion/Zsh/Context/_in_vared
@@ -32,4 +32,4 @@ fi
 
 compstate[insert]="${compstate[insert]//tab /}"
 
-_contexts "$also"
+_dispatch comps "$also"
diff --git a/Completion/Zsh/Context/_redirect b/Completion/Zsh/Context/_redirect
index 6e02636da..5e454014b 100644
--- a/Completion/Zsh/Context/_redirect
+++ b/Completion/Zsh/Context/_redirect
@@ -1,3 +1,17 @@
 #compdef -redirect-
 
-_files
+# This searches for `<command-name>:<redir-op>' and `<redir-op>', where
+# `<redir-op>' is something like `<' or `2>'.
+
+local strs _comp_command1 _comp_command2
+
+_set_command
+
+strs=( "$compstate[redirect]" )
+
+if [[ -n "$_comp_command1" ]]; then
+  strs=( "${_comp_command1}:$strs[-1]" "$strs[@]" )
+  [[ -n "$_comp_command2" ]] && strs=( "${_comp_command2}:$strs[1]" "$strs[@]" )
+fi
+
+_dispatch -d redirs "$strs[@]"
diff --git a/Completion/Zsh/Context/_subscript b/Completion/Zsh/Context/_subscript
index 9ea628fdb..0f1138e1a 100644
--- a/Completion/Zsh/Context/_subscript
+++ b/Completion/Zsh/Context/_subscript
@@ -113,5 +113,5 @@ elif [[ ${(Pt)${compstate[parameter]}} = array* ]]; then
 
   return 1
 else
-  _contexts -math-
+  _dispatch comps -math-
 fi
diff --git a/Completion/Zsh/Context/_value b/Completion/Zsh/Context/_value
index 6ee8f4235..9d0acaa0e 100644
--- a/Completion/Zsh/Context/_value
+++ b/Completion/Zsh/Context/_value
@@ -1,19 +1,39 @@
-#compdef -value- -array-value-
+#compdef -value- -array-value- -T values -default-
 
-_value () {
-  # You can customize completion for different parameters by writing a
-  # function `_value:<name>', where <name> is the name of the parameter.
-  # When completing values of elements of associative arrays, we first
-  # search for a function `_value:<assoc>-<key>' and then for 
-  # `_value:<assoc>', so it's simple to define different functions
-  # for different keys or one function for a whole association.
+# You can customize completion for different parameters by writing
+# functions with the tag-line `#compdef -T value <name>'.
+# The function searches for the strings `<param-name>:<param-type>'
+# and `<param-name>'. If the line contains a command (as in `make foo=<TAB>')
+# the string `<command>:<param-name>:<param-type>' is also searched for.
 
-  if (( $+functions[_value:$compstate[parameter]] )); then
-    "_value:$compstate[parameter]" "$@"
-  elif (( $+functions[_value:${compstate[parameter]%%-*}] )); then
-    "_value:${compstate[parameter]%%-*}" "$@"
-  elif [[ "$compstate[parameter]" != *-* &&
-          "${(Pt)${compstate[parameter]}}" = assoc* ]]; then
+if [[ "$service" != -default- ]]; then
+  local strs type
+
+  type="${(Pt)compstate[parameter]}"
+
+  if [[ -z "$type" ]]; then
+    if [[ "$compstate[parameter]" = *-* ]]; then
+      type=association-value
+    elif [[ "$compstate[context]" = value ]]; then
+      type=scalar
+    else
+      type=array
+    fi
+  fi
+
+  strs=( "${compstate[parameter]}:$type" "$compstate[parameter]" )
+
+  if [[ "$compstate[context]" != *value && -n "$_comp_command1" ]]; then
+    strs=( "${_comp_command1}:$^strs[@]" "$strs[@]" )
+    [[ -n "$_comp_command2" ]] &&
+        strs=( "${_comp_command2}:${(@)^strs[-2,-1]}" "$strs[@]" )
+  fi
+
+  _dispatch -d values "$strs[@]"
+else
+  if [[ "$compstate[parameter]" != *-* &&
+        "$compstate[context]" = *value &&
+        "${(Pt)${compstate[parameter]}}" = assoc* ]]; then
     if (( CURRENT & 1 )); then
       _wanted association-keys expl 'association key' \
           compadd -k "$compstate[parameter]"
@@ -34,37 +54,4 @@ _value () {
       _default "$@"
     fi
   fi
-}
-
-_value:CPPFLAGS () {
-  compset -q
-  if compset -P '-I'; then
-    _files -/ "$@"
-  else
-    _default "$@"
-  fi
-}
-
-_value:LDFLAGS () {
-  compset -q
-  if compset -P '-L'; then
-    _files -/ "$@"
-  elif compset -P '-R'; then
-    compset -P '*:'
-    compset -S ':*'
-    _files -/ -S/ -r '\n\t\- /:' "$@"
-  else
-    _default "$@"
-  fi
-}
-
-_value:DISPLAY() { _x_display "$@" }
-
-_value:PRINTER() { _printers "$@" }
-_value:LPDEST() { _printers "$@" }
-
-_value:TERM() { _terminals "$@" }
-
-_value:TZ() { _time_zone "$@" }
-
-_value "$@"
+fi
diff --git a/Completion/compdump b/Completion/compdump
index 62840b9fe..194fcf07b 100644
--- a/Completion/compdump
+++ b/Completion/compdump
@@ -16,7 +16,7 @@
 emulate -L zsh
 setopt extendedglob noshglob
 
-typeset _d_file _d_f _d_bks _d_line _d_als _d_files
+typeset _d_file _d_f _d_bks _d_line _d_als _d_files _d_name _d_tmp
 
 _d_file=${_comp_dumpfile-${0:h}/compinit.dump}.$HOST.$$
 [[ $_d_file = //* ]] && _d_file=${_d_file[2,-1]}
@@ -35,33 +35,43 @@ fi
 
 print "#files: $#_d_files" > $_d_file
 
-# First dump the arrays _comps, _services and _patcomps.  The quoting
+# First dump the arrays _comps, _servicecomps and _patcomps.  The quoting
 # hieroglyphics ensure that a single quote inside a variable is itself
 # correctly quoted.
 
-print "_comps=(" >> $_d_file
-for _d_f in ${(ok)_comps}; do
-    print -r - "${(q)_d_f}" "${(q)_comps[$_d_f]}"
-done  >> $_d_file
-print ")" >> $_d_file
-
-print "_services=(" >> $_d_file
-for _d_f in ${(ok)_services}; do
-    print -r - "${(q)_d_f}" "${(q)_services[$_d_f]}"
-done  >> $_d_file
-print ")" >> $_d_file
-
-print "\n_patcomps=(" >> $_d_file
-for _d_f in "${(ok@)_patcomps}"; do
-  print -r - "${(q)_d_f}" "${(q)_patcomps[$_d_f]}"
-done >> $_d_file
-print ")" >> $_d_file
+for _d_name in $_comp_assocs; do
+
+  print "\n\ntypeset -gA _$_d_name _service$_d_name _pat$_d_name _postpat$_d_name"
+
+  _d_tmp="_${_d_name}"
+  print "\n_${_d_name}=("
+  for _d_f in ${(Pok)_d_tmp}; do
+    print -r - "${(q)_d_f}" "${(q)${(e):-\$${_d_tmp}[$_d_f]}}"
+  done
+  print ")"
+
+  _d_tmp="_service${_d_name}"
+  print "\n_service${_d_name}=("
+  for _d_f in ${(Pok)_d_tmp}; do
+    print -r - "${(q)_d_f}" "${(q)${(e):-\$${_d_tmp}[$_d_f]}}"
+  done
+  print ")"
+
+  _d_tmp="_pat${_d_name}"
+  print "\n_pat${_d_name}=("
+  for _d_f in ${(Pok)_d_tmp}; do
+    print -r - "${(q)_d_f}" "${(q)${(e):-\$${_d_tmp}[$_d_f]}}"
+  done
+  print ")"
+
+  _d_tmp="_postpat${_d_name}"
+  print "\n_postpat${_d_name}=("
+  for _d_f in ${(Pok)_d_tmp}; do
+    print -r - "${(q)_d_f}" "${(q)${(e):-\$${_d_tmp}[$_d_f]}}"
+  done
+  print ")"
 
-print "\n_postpatcomps=(" >> $_d_file
-for _d_f in "${(ok@)_postpatcomps}"; do
-  print -r - "${(q)_d_f}" "${(q)_postpatcomps[$_d_f]}"
 done >> $_d_file
-print ")" >> $_d_file
 
 print "\n_compautos=(" >> $_d_file
 for _d_f in "${(ok@)_compautos}"; do
@@ -129,6 +139,11 @@ for _i in "${(ok@)_compautos}"; do
   print "autoload -U $_compautos[$_i] $_i" >> $_d_file
 done
 
+print >> $_d_file
+
+print "typeset -gUa _comp_assocs" >> $_d_file
+print "_comp_assocs=( ${(q)_comp_assocs} )" >> $_d_file
+
 mv $_d_file ${_d_file%.$HOST.$$}
 
 unfunction compdump
diff --git a/Completion/compinit b/Completion/compinit
index bd879b11c..94f5f7091 100644
--- a/Completion/compinit
+++ b/Completion/compinit
@@ -11,8 +11,10 @@
 #     If the first line looks like this, the file is autoloaded as a
 #     function and that function will be called to generate the matches
 #     when completing for one of the commands whose <names> are given.
+#     The names may also be interspersed with `-T <assoc>' options
+#     specifying for which set of functions this should be added.
 #
-#   `#compdef -p <pattern>'
+#   `#compdef -[pP] <patterns ...>'
 #     This defines a function that should be called to generate matches
 #     for commands whose name matches <pattern>. Note that only one pattern
 #     may be given.
@@ -100,13 +102,26 @@ while [[ $# -gt 0 && $1 = -[dDiuC] ]]; do
   esac
 done
 
-# The associative array containing the definitions for the commands and
+# The name suffixes for the associative arrays containing the functions
+# to call.
+
+typeset -gUa _comp_assocs
+
+_comp_assocs=(comps)
+
+# The associative arrays containing the definitions for the commands and
 # services.
-# Definitions for patterns will be stored in the associations `_patcomps'
-# and `_postpatcomps'. `_compautos' contains the names and options
-# for autoloaded functions that get options.
+# Definitions for patterns will be stored in the associations `_pat*'
+# and `_postpat*'.
+# The assocs for the other function types are created automatically by
+# compdef.
+
+typeset -gA _comps _servicecomps _patcomps _postpatcomps
 
-typeset -gA _comps _services _patcomps _postpatcomps _compautos
+# `_compautos' contains the names and options for autoloaded functions
+# that get options.
+
+typeset -gA _compautos
 
 # The associative array use to report information about the last
 # completion to the outside.
@@ -176,6 +191,9 @@ comppostfuncs=()
 # 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.
+# In each of these cases the argument list may also contain `-T assoc'
+# options to specify the associactive arrays to which the following
+# definitions should be added.
 # With the `-k' option a function for a special completion keys is 
 # defined and immediately bound to those keys. Here, the extra arguments
 # are the name of one of the builtin completion widgets and any number
@@ -191,7 +209,8 @@ comppostfuncs=()
 # whose names are given as arguments. If combined with the `-p' option
 # it deletes the definitions for the patterns given as argument.
 # The `-d' option may not be combined with the `-k' option, i.e.
-# definitions for key function can not be removed.
+# definitions for key function can not be removed. But one `-T assoc'
+# option may follow the `-d' to say which definitions should be removed.
 #
 # Examples:
 #
@@ -213,12 +232,12 @@ comppostfuncs=()
 #   delete the definitions for the command names `bar' and `baz'
 
 compdef() {
-  local opt autol type func delete new i ret=0 cmd svc
+  local opt autol type func delete new i ret=0 cmd svc assoc=comps
 
   # Get the options.
 
-  if [[ $#* -eq 0 ]]; then
-    echo "$0: I needs arguments"
+  if (( ! $# )); then
+    echo "$0: I need arguments"
     return 1
   fi
 
@@ -247,8 +266,8 @@ compdef() {
   done
   shift OPTIND-1
 
-  if [[ $#* -eq 0 ]]; then
-    echo "$0: I needs arguments"
+  if (( ! $# )); then
+    echo "$0: I need arguments"
     return 1
   fi
 
@@ -257,25 +276,39 @@ compdef() {
     # and we define which services to use for the commands.
 
     if [[ "$1" = *\=* ]]; then
-      for i; do
-        if [[ "$i" = *\=* ]]; then
-	  cmd="${i%%\=*}"
-	  svc="${i#*\=}"
-          func="$_comps[${(k)_services[(R)$svc]:-$svc}]"
-          (( $+_services[$svc] )) && svc=$_services[$svc]
-	  [[ -z "$func" ]] &&
-	    func="${_patcomps[(K)$svc][1]:-${_postpatcomps[(K)$svc][1]}}"
-          if [[ -n "$func" ]]; then
-	    _comps[$cmd]="$func"
-	    _services[$cmd]="$svc"
+      while (( $# )); do
+        if [[ $1 = -T ]]; then
+          shift
+          if (( ! $# )); then
+            echo "$0: missing type"
+            return 1
+          fi
+          _comp_assocs=( "$_comp_assocs[@]" "$1" )
+          typeset -gA _$1 _service$1 _pat$1 _postpat$1
+          assoc="$1"
+          shift
+        else
+          if [[ "$1" = *\=* ]]; then
+	    cmd="${1%%\=*}"
+	    svc="${1#*\=}"
+            func="$_comps[${(e):-\${(k)_service${assoc}[(R)$svc]:-$svc}}]"
+            [[ -n ${(e):-\$_service${assoc}[$svc]} ]] &&
+                svc=${(e):-\$_service${assoc}[$svc]}
+	    [[ -z "$func" ]] &&
+	        func="${${(e):-\$_pat${assoc}[(K)$svc][1]}:-${(e):-\$_postpat${assoc}[(K)$svc][1]}}"
+            if [[ -n "$func" ]]; then
+	      eval "_${assoc}"'[$cmd]="$func"'
+	      eval "_service${assoc}"'[$cmd]="$svc"'
+	    else
+	      echo "$0: unknown command or service: $svc"
+	      ret=1
+	    fi
 	  else
-	    echo "$0: unknown command or service: $svc"
+	    echo "$0: invalid argument: $1"
 	    ret=1
 	  fi
-	else
-	  echo "$0: invalid argument: $i"
-	  ret=1
-	fi
+          shift
+        fi
       done
 
       return ret
@@ -290,18 +323,40 @@ compdef() {
 
     case "$type" in
     pattern)
-      if [[ $# -gt 1 ]]; then
-        echo "$0: only one pattern allowed"
-	return 1
-      fi
-      _patcomps[$1]="$func"
+      while (( $# )); do
+        if [[ $1 = -T ]]; then
+          shift
+          if (( ! $# )); then
+            echo "$0: missing type"
+            return 1
+          fi
+          _comp_assocs=( "$_comp_assocs[@]" "$1" )
+          typeset -gA _$1 _service$1 _pat$1 _postpat$1
+          assoc="$1"
+          shift
+        else
+          eval "_pat${assoc}"'[$1]="$func"'
+          shift
+        fi
+      done
       ;;
     postpattern)
-      if [[ $# -gt 1 ]]; then
-        echo "$0: only one pattern allowed"
-	return 1
-      fi
-      _postpatcomps[$1]="$func"
+      while (( $# )); do
+        if [[ $1 = -T ]]; then
+          shift
+          if (( ! $# )); then
+            echo "$0: missing type"
+            return 1
+          fi
+          _comp_assocs=( "$_comp_assocs[@]" "$1" )
+          typeset -gA _$1 _service$1 _pat$1 _postpat$1
+          assoc="$1"
+          shift
+        else
+          eval "_postpat${assoc}"'[$1]="$func"'
+          shift
+        fi
+      done
       ;;
     widgetkey)
       while [[ -n $1 ]]; do
@@ -321,7 +376,7 @@ compdef() {
 	fi
 	shift 3
       done
-      ;;	 
+      ;;
     key)
       if [[ $# -lt 2 ]]; then
         echo "$0: missing keys"
@@ -348,40 +403,66 @@ compdef() {
       done
       ;;
     *)
-      # For commands store the function name in the `_comps'
+      # For commands store the function name in the
       # associative array, command names as keys.
-      for i; do
-        if [[ "$i" = *\=* ]]; then
-	  cmd="${i%%\=*}"
-	  svc=yes
+      while (( $# )); do
+        if [[ $1 = -T ]]; then
+          shift
+          if (( ! $# )); then
+            echo "$0: missing type"
+            return 1
+          fi
+          _comp_assocs=( "$_comp_assocs[@]" "$1" )
+          typeset -gA _$1 _service$1 _pat$1 _postpat$1
+          assoc="$1"
+          shift
         else
-	  cmd="$i"
-	  svc=
+          if [[ "$1" = *\=* ]]; then
+	    cmd="${1%%\=*}"
+	    svc=yes
+          else
+	    cmd="$1"
+	    svc=
+          fi
+          if [[ -z "$new" || -z "${(e):-\$_${assoc}[$1]}" ]]; then
+            eval "_${assoc}"'[$cmd]="$func"'
+	    [[ -n "$svc" ]] && eval "_service${assoc}"'[$cmd]="${1#*\=}"'
+	  fi
+          shift
         fi
-        if [[ -z "$new" || "${+_comps[$i]}" -eq 0 ]]; then
-          _comps[$cmd]="$func"
-	  if [[ -n "$svc" ]]; then _services[$cmd]="${i#*\=}"; fi
-	fi
       done
       ;;
     esac
   else
     # Handle the `-d' option, deleting.
+
+    if [[ $1 = -T ]]; then
+      shift
+      if (( ! $# )); then
+        echo "$0: missing type"
+        return 1
+      fi
+      _comp_assocs=( "$_comp_assocs[@]" "$1" )
+      typeset -gA _$1 _service$1 _pat$1 _postpat$1
+      assoc="$1"
+      shift
+    fi
+
     case "$type" in
     pattern)
-      unset "_patcomps[$^@]"
+      unset "_pat${assoc}[$^@]"
       ;;
     postpattern)
-      unset "_postpatcomps[$^@]"
+      unset "_postpat${assoc}[$^@]"
       ;;
     key)
       # Oops, cannot do that yet.
 
       echo "$0: cannot restore key bindings"
-      return 1v
+      return 1
       ;;
     *)
-      unset "_comps[$^@]"
+      unset "_${assoc}[$^@]"
     esac
   fi
 }
diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo
index d6b464002..1fb337329 100644
--- a/Doc/Zsh/compsys.yo
+++ b/Doc/Zsh/compsys.yo
@@ -173,14 +173,32 @@ makes the completion system call the function when completing
 arguments for the command `tt(cmd)', setting the parameter tt($service) 
 to the string `tt(service)'.  The function can then use that parameter 
 to decide what to complete.
+
+Finally, the list of var(names) may contain tt(-T) options, each
+followed by a type name.  These type names describe in which set of
+completion function definitions the function is to be stored.  The
+default without a tt(-T) option is `tt(comps)', saying that the
+function is a normal completion function.  Other type names currently
+understood by the completion system are tt(redirs) and tt(values).
+The first is used to define specialised completion functions for
+use after redirection operators for certain commands and the latter is
+used to define functions used when completing values of parameters.
+For example, to define the function that should be used when
+completing after `tt(foo=<TAB>)' one would use the tag line:
+
+example(#compdef -T values foo)
+
+When the function is called, the parameter tt($comptype) will be set
+to the type name, making it easy to distinguish what should be
+completed.
 )
-item(tt(#compdef -p) var(pattern))(
+item(tt(#compdef -p) var(patterns...))(
 The file will be made autoloadable and the function defined in it will be
 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.
+var(pattern) (a standard globbing pattern).  As in the first case, the
+list of var(patterns) may contain tt(-T) options.
 )
-item(tt(#compdef -P) var(pattern))(
+item(tt(#compdef -P) var(patterns...))(
 Like the previous one, but the function will be called only if no
 completion function for the command on the line could be found.
 )
@@ -254,10 +272,10 @@ also be called directly by the user.
 findex(compdef)
 cindex(completion system, adding definitions)
 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))
+xitem(tt(compdef) [ tt(-an) ] var(function names) [ tt(-T) var(type) ] ...))
+xitem(tt(compdef -d) [ tt(-T) var(type) ] var(names...))
+xitem(tt(compdef -p) [ tt(-a) ] var(function patterns) [ tt(-T) var(type) ] ...)
+xitem(tt(compdef -P) [ tt(-a) ] var(function patterns) [ tt(-T) var(type) ] ...)
 xitem(tt(compdef -k) [ tt(-an) ] var(function style key-sequences...))
 item(tt(compdef -K) [ tt(-an) ] var(function name style key-sequences ...))(
 The first form tells the completion system to call the given
@@ -279,6 +297,14 @@ arguments to the command tt(foo), one would use:
 
 example(compdef '_files -g "*.h"' foo)
 
+The tt(-T) options in the list of var(names) define for which type of
+completions the function is to be used, i.e. in which set of
+completion functions definitions it should be added.  Currently used
+tt(type)s are tt(comps) (the default, for normal completion functions
+for command completion), tt(values) for completion of parameter values
+in assignments and tt(redirs) for completion after redirection
+operators.
+
 If the
 tt(-n) option is given, any existing completion behaviour for particular
 contexts or commands will not be altered.  These definitions can be deleted
@@ -3552,19 +3578,6 @@ All arguments after the requested field name are passed to
 tt(compadd) when generating matches from the style value, or to 
 the functions for the fields if they are called.
 )
-findex(_contexts)
-item(tt(_contexts) [ tt(-o) ] var(names) ...)(
-This function looks up the definitions for the context and command
-names given as arguments and calls the handler functions for them if
-there is a definition (given with the tt(compdef) function).  For
-example, the function completing inside subscripts might use
-`tt(_contexts -math-)' to include the completions generated for
-mathematical environments.
-
-If the tt(-o) option is given, tt(_contexts) returns after the first
-context for which completions could be generated, without trying the
-other contexts.
-)
 findex(_describe)
 item(tt(_describe) [ tt(-o) ] var(descr) var(name1) [ var(name2) ] var(opts) ... tt(-)tt(-) ...)(
 This function is useful for preparing a list of command options or
@@ -3643,6 +3656,19 @@ matches.  Almost all calls to tt(compadd) within the completion system use
 a similar format; this ensures that user-specified styles are correctly
 passed down to the builtins which implement the internals of completion.
 )
+findex(_dispatch)
+item(tt(_dispatch) [ tt(-d) ] var(type strings ...))(
+This function looks up the function defined for the first var(string)
+in the set of definitions named var(type) (these are those definitions
+defined with `tt(-T )var(type)').  If one is found, it is called to
+generate completions.  Otherwise the definition for the second
+var(string) is looked up and so on.  If none is found and the tt(-d)
+option is given, the definition for the special name tt(-default-) is
+used.
+
+This function is the one responsible for setting the parameters
+tt($service) and tt($comptype).
+)
 findex(_files)
 item(tt(_files))(
 The function tt(_files) uses the tt(file-patterns) style and calls
@@ -3789,7 +3815,7 @@ return ret
 )
 )
 findex(_normal)
-item(tt(_normal))(
+item(tt(_normal) [ var(type) ])(
 This function is used for normal command completion.  It has two tasks:
 completing the first word on the command line as the name of a command, and
 completing the arguments to this command.  In the second case, the name of
@@ -3808,6 +3834,13 @@ If the command name matches a pattern, the parameter tt(_compskip) is
 checked after the call to the corresponding completion function.  This has
 the same effect here as in the tt(-first-) context: if it is set, no more
 completion functions are called even if there are no matches so far.
+
+If the optional var(type) argument is given, tt(_normal) does not use
+the normal associative arrays for its lookup but instead uses the ones
+defined for the given var(type), which may currently be one of
+tt(comps) for normal completion, tt(redirs) for completion of
+command-specific redirections or tt(values) to complete on the right
+hand side of parameter assignments.
 )
 findex(_options)
 item(tt(_options))(