zsh-workers
 help / color / mirror / code / Atom feed
* Re: Per command _redirect completion
@ 2002-03-02 16:28 Felix Rosencrantz
  0 siblings, 0 replies; 15+ messages in thread
From: Felix Rosencrantz @ 2002-03-02 16:28 UTC (permalink / raw)
  To: zsh-workers

Still having problem with the latest uncommitted patch:  When trying to
complete TZ I get:
_do_type:31: ':' without '?'

Which only happens from a shell where .zcompdump didn't pre-exist.  Subsequent
shells seem to work.

Also, completion for command flags/args doesn't work.  The command's completion
function is not being called.
I try:
 gzip -<TAB> 

in an empty directory and get "no match for: `file'".

I like the new changes a lot (assuming they work).  It wasn't clear to me how
completion for different redirection operators will work.  It seems that you
can only specify one redirection completer.  Which will have to do the
remaining work of figuring what completion function to use, if you want one for
input and one for output.  (And another for stderr, etc.)  It seems like that
information should be part of the compdef call.  All my command specific
redirection completers  currently are for commands that provide output, the
input comes from command line args, so it didn't matter.  But I can easily see
there being commands where input and output files from redirection are
completely different.  So the user will want to use different functions.

-FR


__________________________________________________
Do You Yahoo!?
Yahoo! Sports - sign up for Fantasy Baseball
http://sports.yahoo.com


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Per command _redirect completion
  2002-03-01  5:47             ` Bart Schaefer
@ 2002-03-04  8:50               ` Sven Wischnowsky
  0 siblings, 0 replies; 15+ messages in thread
From: Sven Wischnowsky @ 2002-03-04  8:50 UTC (permalink / raw)
  To: zsh-workers


Bart Schaefer wrote:

> ...
> 
> I like this idea a lot, now that I've had a chance to digest it fully.

Yes, me too.  Thanks to Oliver for bringing this up.

> } - I wished there were an easier way than to use `${(e):-...}' in so
> }   many places. Sigh.
> 
> We'd need namerefs; ${(P)...} doesn't cut it for hashes.  You could use
> `eval' in a few places, I think, but not all of them.

Which isn't much nicer anyway...


Felix Rosencrantz wrote:

> Still having problem with the latest uncommitted patch:  When trying to
> complete TZ I get:
> _do_type:31: ':' without '?'
> 
> Which only happens from a shell where .zcompdump didn't pre-exist.  Subsequent
> shells seem to work.

Yep, I had introduced that in another way. I found and fixed this, so
it should be working now with the patch below.

> Also, completion for command flags/args doesn't work.  The command's completion
> function is not being called.
> I try:
>  gzip -<TAB> 
> 
> in an empty directory and get "no match for: `file'".

I have no problems with this.

> I like the new changes a lot (assuming they work).  It wasn't clear to me how
> completion for different redirection operators will work.  It seems that you
> can only specify one redirection completer.  Which will have to do the
> remaining work of figuring what completion function to use, if you want one for
> input and one for output.  (And another for stderr, etc.)  It seems like that
> information should be part of the compdef call.  All my command specific
> redirection completers  currently are for commands that provide output, the
> input comes from command line args, so it didn't matter.  But I can easily see
> there being commands where input and output files from redirection are
> completely different.  So the user will want to use different functions.

See the comments in _redirection and _value. Of course the redirection
operator is part of the string searched.  E.g.:

  % compdef 'compadd a b c' 'foo:>'
  % foo > <TAB>
  a  b  c


I'm now going to commit this change so that everyone can easily try
it.  I've renamed _do_type to _dispatch and removed _contexts (it's
functionality is now in _dispatch).  I'd be thankful if someone could
have a look at the changes in the docs.  I'm almost sure that this
should be described better, somewhere else and that the strings looked
up for each type of completion should be described somewhere (we never
had this for normal commands either).  And whoever wrote the functions
for completing the values of CPPFLAGS and LDFLAGS might want to look
at _gcc to see if that's ok (I followed Oliver's suggestion to put
completion for these paramter-values there).


Bye
  Sven

Index: Completion/compdump
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/compdump,v
retrieving revision 1.2
diff -u -r1.2 compdump
--- Completion/compdump	29 May 2001 17:54:08 -0000	1.2
+++ Completion/compdump	4 Mar 2002 08:50:44 -0000
@@ -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 @@
 
 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
+for _d_name in $_comp_assocs; do
 
-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\ntypeset -gA _$_d_name _service$_d_name _pat$_d_name _postpat$_d_name"
 
-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
+  _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
@@ -128,6 +138,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.$$}
 
Index: Completion/compinit
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/compinit,v
retrieving revision 1.6
diff -u -r1.6 compinit
--- Completion/compinit	21 Jun 2001 09:24:39 -0000	1.6
+++ Completion/compinit	4 Mar 2002 08:50:44 -0000
@@ -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 @@
   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 @@
 # 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 @@
 # 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 @@
 #   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 @@
   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 @@
     # 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 @@
 
     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 @@
 	fi
 	shift 3
       done
-      ;;	 
+      ;;
     key)
       if [[ $# -lt 2 ]]; then
         echo "$0: missing keys"
@@ -348,40 +403,66 @@
       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
 }
Index: Completion/Base/Completer/_complete
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Base/Completer/_complete,v
retrieving revision 1.3
diff -u -r1.3 _complete
--- Completion/Base/Completer/_complete	22 Jan 2002 10:22:48 -0000	1.3
+++ Completion/Base/Completer/_complete	4 Mar 2002 08:50:44 -0000
@@ -95,7 +95,7 @@
 
 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 @@
   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 @@
       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=
Index: Completion/Base/Core/_dispatch
===================================================================
RCS file: Completion/Base/Core/_dispatch
diff -N Completion/Base/Core/_dispatch
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Completion/Base/Core/_dispatch	4 Mar 2002 08:50:44 -0000
@@ -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
Index: Completion/Base/Core/_normal
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Base/Core/_normal,v
retrieving revision 1.2
diff -u -r1.2 _normal
--- Completion/Base/Core/_normal	21 Jan 2002 16:13:18 -0000	1.2
+++ Completion/Base/Core/_normal	4 Mar 2002 08:50:44 -0000
@@ -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 @@
   [[ -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"
Index: Completion/Base/Utility/_contexts
===================================================================
RCS file: Completion/Base/Utility/_contexts
diff -N Completion/Base/Utility/_contexts
--- Completion/Base/Utility/_contexts	21 Jan 2002 16:13:18 -0000	1.2
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -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
Index: Completion/Base/Utility/_set_command
===================================================================
RCS file: Completion/Base/Utility/_set_command
diff -N Completion/Base/Utility/_set_command
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Completion/Base/Utility/_set_command	4 Mar 2002 08:50:44 -0000
@@ -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
Index: Completion/Unix/Command/_gcc
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Unix/Command/_gcc,v
retrieving revision 1.2
diff -u -r1.2 _gcc
--- Completion/Unix/Command/_gcc	7 Dec 2001 12:43:33 -0000	1.2
+++ Completion/Unix/Command/_gcc	4 Mar 2002 08:50:44 -0000
@@ -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 @@
   -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
@@ -275,6 +288,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
 
Index: Completion/Unix/Command/_su
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Unix/Command/_su,v
retrieving revision 1.2
diff -u -r1.2 _su
--- Completion/Unix/Command/_su	21 Jan 2002 16:13:18 -0000	1.2
+++ Completion/Unix/Command/_su	4 Mar 2002 08:50:44 -0000
@@ -17,4 +17,4 @@
 shell="${${(M@)${(@f)$(</etc/passwd)}:#$usr*}##*:}"
 compset -n $base
 
-_contexts -o $shell $shell:t -default-
+_dispatch comps $shell $shell:t -default-
Index: Completion/Unix/Type/_files
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Unix/Type/_files,v
retrieving revision 1.5
diff -u -r1.5 _files
--- Completion/Unix/Type/_files	9 Oct 2001 12:56:03 -0000	1.5
+++ Completion/Unix/Type/_files	4 Mar 2002 08:50:44 -0000
@@ -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
Index: Completion/Unix/Type/_printers
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Unix/Type/_printers,v
retrieving revision 1.2
diff -u -r1.2 _printers
--- Completion/Unix/Type/_printers	25 Jul 2001 12:18:24 -0000	1.2
+++ Completion/Unix/Type/_printers	4 Mar 2002 08:50:44 -0000
@@ -1,4 +1,4 @@
-#autoload
+#compdef -T values PRINTER LPDEST
 
 local expl ret=1 list disp sep
 
Index: Completion/Unix/Type/_terminals
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Unix/Type/_terminals,v
retrieving revision 1.1
diff -u -r1.1 _terminals
--- Completion/Unix/Type/_terminals	16 Jan 2002 16:29:52 -0000	1.1
+++ Completion/Unix/Type/_terminals	4 Mar 2002 08:50:44 -0000
@@ -1,4 +1,4 @@
-#compdef infocmp
+#compdef infocmp -T values TERM
 
 local desc expl
 
Index: Completion/Unix/Type/_time_zone
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Unix/Type/_time_zone,v
retrieving revision 1.3
diff -u -r1.3 _time_zone
--- Completion/Unix/Type/_time_zone	4 Jan 2002 12:09:30 -0000	1.3
+++ Completion/Unix/Type/_time_zone	4 Mar 2002 08:50:44 -0000
@@ -1,4 +1,4 @@
-#compdef
+#compdef -T values TZ
 
 local expl
 
Index: Completion/X/Type/_x_display
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/X/Type/_x_display,v
retrieving revision 1.1
diff -u -r1.1 _x_display
--- Completion/X/Type/_x_display	2 Apr 2001 12:09:25 -0000	1.1
+++ Completion/X/Type/_x_display	4 Mar 2002 08:50:44 -0000
@@ -1,3 +1,3 @@
-#autoload
+#compdef -T values DISPLAY
 
 _tags displays && _hosts -S ':0 ' -r :
Index: Completion/Zsh/Command/_compdef
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Zsh/Command/_compdef,v
retrieving revision 1.1
diff -u -r1.1 _compdef
--- Completion/Zsh/Command/_compdef	2 Apr 2001 11:27:07 -0000	1.1
+++ Completion/Zsh/Command/_compdef	4 Mar 2002 08:50:44 -0000
@@ -6,6 +6,7 @@
 _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 \
Index: Completion/Zsh/Context/_default
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Zsh/Context/_default,v
retrieving revision 1.1
diff -u -r1.1 _default
--- Completion/Zsh/Context/_default	2 Apr 2001 11:22:38 -0000	1.1
+++ Completion/Zsh/Context/_default	4 Mar 2002 08:50:44 -0000
@@ -19,7 +19,7 @@
 # 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
Index: Completion/Zsh/Context/_in_vared
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Zsh/Context/_in_vared,v
retrieving revision 1.1
diff -u -r1.1 _in_vared
--- Completion/Zsh/Context/_in_vared	2 Apr 2001 11:23:29 -0000	1.1
+++ Completion/Zsh/Context/_in_vared	4 Mar 2002 08:50:44 -0000
@@ -32,4 +32,4 @@
 
 compstate[insert]="${compstate[insert]//tab /}"
 
-_contexts "$also"
+_dispatch comps "$also"
Index: Completion/Zsh/Context/_redirect
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Zsh/Context/_redirect,v
retrieving revision 1.1
diff -u -r1.1 _redirect
--- Completion/Zsh/Context/_redirect	2 Apr 2001 11:24:17 -0000	1.1
+++ Completion/Zsh/Context/_redirect	4 Mar 2002 08:50:44 -0000
@@ -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[@]"
Index: Completion/Zsh/Context/_subscript
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Zsh/Context/_subscript,v
retrieving revision 1.8
diff -u -r1.8 _subscript
--- Completion/Zsh/Context/_subscript	11 Sep 2001 09:35:55 -0000	1.8
+++ Completion/Zsh/Context/_subscript	4 Mar 2002 08:50:44 -0000
@@ -113,5 +113,5 @@
 
   return 1
 else
-  _contexts -math-
+  _dispatch comps -math-
 fi
Index: Completion/Zsh/Context/_value
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Zsh/Context/_value,v
retrieving revision 1.4
diff -u -r1.4 _value
--- Completion/Zsh/Context/_value	16 Jan 2002 16:29:52 -0000	1.4
+++ Completion/Zsh/Context/_value	4 Mar 2002 08:50:44 -0000
@@ -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.
-
-  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
+# 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 [[ "$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 @@
       _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
Index: Doc/Zsh/compsys.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/compsys.yo,v
retrieving revision 1.146
diff -u -r1.146 compsys.yo
--- Doc/Zsh/compsys.yo	25 Feb 2002 09:09:36 -0000	1.146
+++ Doc/Zsh/compsys.yo	4 Mar 2002 08:50:45 -0000
@@ -173,14 +173,32 @@
 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 @@
 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 @@
 
 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 @@
 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 @@
 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 @@
 )
 )
 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 @@
 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))(

-- 
Sven Wischnowsky                          wischnow@berkom.de


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Per command _redirect completion
  2002-03-01  9:24             ` Oliver Kiddle
@ 2002-03-01 10:49               ` Sven Wischnowsky
  0 siblings, 0 replies; 15+ messages in thread
From: Sven Wischnowsky @ 2002-03-01 10:49 UTC (permalink / raw)
  To: zsh-workers


Patch below is probably the last not-to-be-committed version of this.


Oliver Kiddle wrote:

> ...
> 
> Contexts. They've always been mixed in with the commands but I think
> it'd be logical to now separate them off (with the possible exception
> of -default-). There wouldn't be much use for service and patterns with
> them though so the value of separating them is questionable.

But interesting to think about, good idea.

> ...
> 
> Only I just wonder now: if we have to triplicate the list of commands
> just to handle redirections (normal, < and >) it might end up being a
> bit tedious.

I fear I don't understand this. We don't have to change anything
unless we want to be able to offer new features (and if anything
doesn't work this way it's a bug and I'd like to hear about it).

The change is that we now *can* offer different completions after
different redirection operators, for different commands and whatnot,
and that we can do that conveniently by putting it in the #compdef
lines, probably looking at $service in the implementation (as in the
_value function in the patch below, for example).

> ...
> _normal:74:service="${${(e):-\$${__services}[$_comp_command1]}:-$_comp_command1}"
> ...
> > +_do_type "$skip[@]" comps "_$comp_command1" "_$comp_command2"
> 
> This last line needs the dollars and underscores swapped otherwise all
> you get is service=_ and default completion.

Yep, I found these, too. Sorry for that.

> > Only two small value-functions left.
> 
> And those aren't so small and could arguably live inside _gcc.

Another thing I hadn't thought about... sounds sensible.

> ...
> 
> It isn't particularly easy thinking of good names even when it is my
> first language. My problem with the name _contexts is that it isn't
> just a context (i.e. -parameter-, -equal- etc) that can be given to it
> as an argument. It can be commands and now also values.

But then we are also talking a lot about `contexts' when we really
mean `completion after option -foo in command bar'. I'd actually like
to think about...

> ...
> 
> How about _dispatch?
> 
> _contexts might then be _redispatch. Could they be merged as one
> function? I can't see a reason why _contexts oughtn't to be honouring
> pattern compdefs and they do basically the same job.

...this. Something I had been thinking about, too.


Bye
  Sven

diff -ur -r ../oz/Completion/Base/Completer/_complete ./Completion/Base/Completer/_complete
--- ../oz/Completion/Base/Completer/_complete	Tue Feb 26 20:56:19 2002
+++ ./Completion/Base/Completer/_complete	Wed Feb 27 22:32:22 2002
@@ -95,7 +95,7 @@
 
 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 @@
   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 @@
       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 -ur -r ../oz/Completion/Base/Core/_do_type ./Completion/Base/Core/_do_type
--- ../oz/Completion/Base/Core/_do_type	Wed Feb 27 22:28:45 2002
+++ ./Completion/Base/Core/_do_type	Thu Feb 28 22:34:42 2002
@@ -0,0 +1,91 @@
+#autoload
+
+local comp pat val name i ret=1 _compskip="$_compskip"
+local curcontext="$curcontext" service str
+local __comps __patcomps __postpatcomps __services
+
+# If we get the option `-s', we don't reset `_compskip'.
+
+if [[ "$1" = -s ]]; then
+  shift
+else
+  _compskip=''
+fi
+
+__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 -ur -r ../oz/Completion/Base/Core/_normal ./Completion/Base/Core/_normal
--- ../oz/Completion/Base/Core/_normal	Tue Feb 26 20:56:19 2002
+++ ./Completion/Base/Core/_normal	Wed Feb 27 22:29:17 2002
@@ -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 @@
   [[ -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
+_do_type "$skip[@]" comps "_$comp_command1" "_$comp_command2"
diff -ur -r ../oz/Completion/Base/Utility/_contexts ./Completion/Base/Utility/_contexts
--- ../oz/Completion/Base/Utility/_contexts	Tue Feb 26 20:56:19 2002
+++ ./Completion/Base/Utility/_contexts	Tue Feb 26 23:44:51 2002
@@ -6,8 +6,19 @@
 # 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.
+# You may also select the assocs to use with the `-T assoc' option.
 
-local i tmp ret=1 service or
+local i tmp ret=1 service or type
+
+type=(-T comps)
+zparseopts -D o=or T:=type
+
+type="$type[2]"
+if (( $#or )); then
+  or=yes
+else
+  or=
+fi
 
 if [[ $1 = -o ]]; then
   or=yes
@@ -15,8 +26,9 @@
 fi
 
 for i; do
-  tmp="$_comps[$i]"
-  [[ -n "$tmp" ]] && service="${_services[$i]:-$i}" && eval "$tmp" && ret=0
+  tmp="${(e):-\$_${type}[$i]}"
+  [[ -n "$tmp" ]] && service="${${(e):-\$_service${type}[$i]}:-$i}" &&
+      eval "$tmp" && ret=0
   [[ -n "$or" && ret -eq 0 ]] && return 0
 done
 
diff -ur -r ../oz/Completion/Base/Utility/_set_command ./Completion/Base/Utility/_set_command
--- ../oz/Completion/Base/Utility/_set_command	Wed Feb 27 22:28:17 2002
+++ ./Completion/Base/Utility/_set_command	Thu Feb 28 22:11:13 2002
@@ -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_command2="$command"
+  _comp_command1="$commands[$command]"
+  curcontext="${curcontext%:*:*}:${_comp_command1}:"
+fi
diff -ur -r ../oz/Completion/Unix/Type/_files ./Completion/Unix/Type/_files
--- ../oz/Completion/Unix/Type/_files	Tue Feb 26 20:56:19 2002
+++ ./Completion/Unix/Type/_files	Wed Feb 27 22:35:35 2002
@@ -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 -ur -r ../oz/Completion/Unix/Type/_printers ./Completion/Unix/Type/_printers
--- ../oz/Completion/Unix/Type/_printers	Tue Feb 26 20:56:19 2002
+++ ./Completion/Unix/Type/_printers	Wed Feb 27 21:18:55 2002
@@ -1,4 +1,4 @@
-#autoload
+#compdef -T values PRINTER LPDEST
 
 local expl ret=1 list disp sep
 
diff -ur -r ../oz/Completion/Unix/Type/_terminals ./Completion/Unix/Type/_terminals
--- ../oz/Completion/Unix/Type/_terminals	Tue Feb 26 20:56:19 2002
+++ ./Completion/Unix/Type/_terminals	Wed Feb 27 21:19:33 2002
@@ -1,4 +1,4 @@
-#compdef infocmp
+#compdef infocmp -T values TERM
 
 local desc expl
 
diff -ur -r ../oz/Completion/Unix/Type/_time_zone ./Completion/Unix/Type/_time_zone
--- ../oz/Completion/Unix/Type/_time_zone	Tue Feb 26 20:56:19 2002
+++ ./Completion/Unix/Type/_time_zone	Wed Feb 27 21:20:11 2002
@@ -1,4 +1,4 @@
-#compdef
+#compdef -T values TZ
 
 local expl
 
diff -ur -r ../oz/Completion/X/Type/_x_display ./Completion/X/Type/_x_display
--- ../oz/Completion/X/Type/_x_display	Tue Feb 26 20:56:19 2002
+++ ./Completion/X/Type/_x_display	Wed Feb 27 21:18:14 2002
@@ -1,3 +1,3 @@
-#autoload
+#compdef -T values DISPLAY
 
 _tags displays && _hosts -S ':0 ' -r :
diff -ur -r ../oz/Completion/Zsh/Context/_default ./Completion/Zsh/Context/_default
--- ../oz/Completion/Zsh/Context/_default	Tue Feb 26 20:56:19 2002
+++ ./Completion/Zsh/Context/_default	Wed Feb 27 21:58:26 2002
@@ -19,7 +19,7 @@
 # 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 -ur -r ../oz/Completion/Zsh/Context/_redirect ./Completion/Zsh/Context/_redirect
--- ../oz/Completion/Zsh/Context/_redirect	Tue Feb 26 20:56:19 2002
+++ ./Completion/Zsh/Context/_redirect	Thu Feb 28 22:11:51 2002
@@ -1,3 +1,14 @@
 #compdef -redirect-
 
-_files
+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
+
+_do_type redirs "$strs[@]"
diff -ur -r ../oz/Completion/Zsh/Context/_value ./Completion/Zsh/Context/_value
--- ../oz/Completion/Zsh/Context/_value	Wed Feb 27 00:14:27 2002
+++ ./Completion/Zsh/Context/_value	Thu Feb 28 22:35:36 2002
@@ -1,19 +1,36 @@
-#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.
-
-  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
+# You can customize completion for different parameters by writing
+# functions with the tag-line `#compdef -T value <name>'.
+
+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
+
+  _do_type 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 +51,4 @@
       _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 -ur -r ../oz/Completion/Zsh/Context/_value_CPPFLAGS ./Completion/Zsh/Context/_value_CPPFLAGS
--- ../oz/Completion/Zsh/Context/_value_CPPFLAGS	Wed Feb 27 00:14:27 2002
+++ ./Completion/Zsh/Context/_value_CPPFLAGS	Wed Feb 27 00:25:03 2002
@@ -0,0 +1,8 @@
+#compdef -T values CPPFLAGS
+
+compset -q
+if compset -P '-I'; then
+  _files -/ "$@"
+else
+  _default "$@"
+fi
diff -ur -r ../oz/Completion/Zsh/Context/_value_LDFLAGS ./Completion/Zsh/Context/_value_LDFLAGS
--- ../oz/Completion/Zsh/Context/_value_LDFLAGS	Wed Feb 27 00:14:27 2002
+++ ./Completion/Zsh/Context/_value_LDFLAGS	Wed Feb 27 00:25:24 2002
@@ -0,0 +1,12 @@
+#compdef -T values 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
diff -ur -r ../oz/Completion/Zsh/Context/_value~ ./Completion/Zsh/Context/_value~
--- ../oz/Completion/Zsh/Context/_value~	Wed Feb 27 00:14:27 2002
+++ ./Completion/Zsh/Context/_value~	Wed Feb 27 22:03:03 2002
@@ -0,0 +1,52 @@
+#compdef -value- -array-value-
+
+# You can customize completion for different parameters by writing
+# functions with the tag-line `#compdef -T value <name>'.
+
+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]" "${compstate[parameter]}:$type" )
+
+if [[ "$compstate[context]" != *value && -n "$_comp_command1" ]]; then
+  strs=( "$strs[@]" "${_comp_command1}:$^strs[@]" )
+  [[ -n "$_comp_command2" ]] &&
+      strs=( "$strs[@]" "${_comp_command2}:${(@)^strs[1,2]}" )
+fi
+
+_do_type values "$strs[@]" && return 0
+
+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]"
+  else
+    compstate[parameter]="${compstate[parameter]}-${words[CURRENT-1]}"
+    _value "$@"
+  fi
+else
+  local pats
+
+  if { zstyle -a ":completion:${curcontext}:" assign-list pats &&
+       [[ "$compstate[parameter]" = (${(j:|:)~pats}) ]] } ||
+     [[ "$PREFIX$SUFFIX" = *:* ]]; then
+    compset -P '*:'
+    compset -S ':*'
+    _default -r '\-\n\t /:' "$@"
+  else
+    _default "$@"
+  fi
+fi
diff -ur -r ../oz/Completion/compdump ./Completion/compdump
--- ../oz/Completion/compdump	Tue Feb 26 20:56:19 2002
+++ ./Completion/compdump	Wed Feb 27 23:10:35 2002
@@ -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 @@
 
 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
diff -ur -r ../oz/Completion/compinit ./Completion/compinit
--- ../oz/Completion/compinit	Tue Feb 26 20:56:19 2002
+++ ./Completion/compinit	Wed Feb 27 23:08:37 2002
@@ -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 @@
   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 -Ua _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 @@
 # 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 @@
 # 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 @@
 #   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 @@
   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 @@
     # 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 @@
 
     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 @@
 	fi
 	shift 3
       done
-      ;;	 
+      ;;
     key)
       if [[ $# -lt 2 ]]; then
         echo "$0: missing keys"
@@ -348,40 +403,66 @@
       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 -ur -r ../oz/Doc/Zsh/compsys.yo ./Doc/Zsh/compsys.yo
--- ../oz/Doc/Zsh/compsys.yo	Tue Feb 26 20:56:17 2002
+++ ./Doc/Zsh/compsys.yo	Wed Feb 27 00:37:21 2002
@@ -173,14 +173,27 @@
 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 what kind of
+overall context the function is to be used.  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 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)
 )
-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 +267,10 @@
 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
@@ -3553,7 +3566,7 @@
 the functions for the fields if they are called.
 )
 findex(_contexts)
-item(tt(_contexts) [ tt(-o) ] var(names) ...)(
+item(tt(_contexts) [ tt(-o) ] [ tt(-T) var(type) ] 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
@@ -3564,6 +3577,10 @@
 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.
+
+This function basically calls the tt(_normal) function repeatedly and
+if the tt(-T) option is given the var(type) is given to tt(_normal) as
+an argument to tell it which type of completion function to use.
 )
 findex(_describe)
 item(tt(_describe) [ tt(-o) ] var(descr) var(name1) [ var(name2) ] var(opts) ... tt(-)tt(-) ...)(
@@ -3789,7 +3806,7 @@
 )
 )
 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 +3825,13 @@
 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))(

-- 
Sven Wischnowsky                          wischnow@berkom.de


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Per command _redirect completion
  2002-02-28  8:42           ` Sven Wischnowsky
  2002-03-01  5:47             ` Bart Schaefer
@ 2002-03-01  9:24             ` Oliver Kiddle
  2002-03-01 10:49               ` Sven Wischnowsky
  1 sibling, 1 reply; 15+ messages in thread
From: Oliver Kiddle @ 2002-03-01  9:24 UTC (permalink / raw)
  To: Sven Wischnowsky, zsh-workers

Sven wrote:

> - Does anyone know about other places than redirections and values
>   where this might be interesting to use? Even now it is already easy
>   to define more sets.

Contexts. They've always been mixed in with the commands but I think
it'd be logical to now separate them off (with the possible exception
of -default-). There wouldn't be much use for service and patterns with
them though so the value of separating them is questionable.

The only other places I can think of are arguments to math functions
and condition codes but they are probably best left until we need them
(I thought about adding a file size math function to the stat module so
it might be useful someday with that sort of thing).

> > Have I also understood correctly, that the compdef changes allow
> > multiple uses of -T so that _gzip might start with:
> >     #compdef gzip gunzip gzcat=gunzip -T values GZIP
> 
> Right. Good? ;-)

Yes. Good.

Only I just wonder now: if we have to triplicate the list of commands
just to handle redirections (normal, < and >) it might end up being a
bit tedious.

> Felix Rosencrantz wrote:
> 
> > Looks good to me.  Though am seeing an error with the value
completions.  While
> > the redirs and normal completion don't seem to have a problem. 
> > 
> > host@ TZ=<TAB>
> > _normal:74: division by zero
> > host@ DISPLAY=<TAB>
> > _normal:74: ':' without '?'
> > 
> >
_normal:74:service="${${(e):-\$${__services}[$_comp_command1]}:-$_comp_command1}"
> 
> Yup, had this too, somtimes. Try the new and improved patch below...

Doesn't seem to be solved - `_do_type:31: ':' without '?'' after
TZ=<tab>

And, f < <tab> is a bad math expression: operand expected at `<'

> +++ ./Completion/Base/Core/_normal	Wed Feb 27 22:29:17 2002

> +_set_command
>  
> -return ret
> +_do_type "$skip[@]" comps "_$comp_command1" "_$comp_command2"

This last line needs the dollars and underscores swapped otherwise all
you get is service=_ and default completion.

> Only two small value-functions left.

And those aren't so small and could arguably live inside _gcc.

> > > diff -ur -r ../oz/Completion/Base/Utility/_contexts
> > > +# You may also select the assocs to use with the `-T assoc'
option.
> > 
> > I know we only renamed it a year ago but _contexts perhaps could be
> > better named.
> 
> Hm. I don't think it's too bad, but then I'm not a native English
> speaker.

It isn't particularly easy thinking of good names even when it is my
first language. My problem with the name _contexts is that it isn't
just a context (i.e. -parameter-, -equal- etc) that can be given to it
as an argument. It can be commands and now also values.

> The stuff in _normal has been put into separate function
> `_do_type', which needs a better name (for which I need help).
> 
> Between the things to do:
> 
> - Decide on a name for the concept so that we can give _do_type its
>   final name and update the docs.

How about _dispatch?

_contexts might then be _redispatch. Could they be merged as one
function? I can't see a reason why _contexts oughtn't to be honouring
pattern compdefs and they do basically the same job.

Thanks.

Oliver

__________________________________________________
Do You Yahoo!?
Everything you'll ever need on one web page
from News and Sport to Email and Music Charts
http://uk.my.yahoo.com


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Per command _redirect completion
  2002-02-28  8:42           ` Sven Wischnowsky
@ 2002-03-01  5:47             ` Bart Schaefer
  2002-03-04  8:50               ` Sven Wischnowsky
  2002-03-01  9:24             ` Oliver Kiddle
  1 sibling, 1 reply; 15+ messages in thread
From: Bart Schaefer @ 2002-03-01  5:47 UTC (permalink / raw)
  To: zsh-workers

On Feb 27, 10:35am, Sven Wischnowsky wrote:
}
} I wrote:
} 
} > I would try to make compdef and parts of _normal (and probably
} > _complete) generic enough to use an assoc given as argument, so that
} > we get the pattern and services stuff.

I like this idea a lot, now that I've had a chance to digest it fully.

} - I wished there were an easier way than to use `${(e):-...}' in so
}   many places. Sigh.

We'd need namerefs; ${(P)...} doesn't cut it for hashes.  You could use
`eval' in a few places, I think, but not all of them.

On Feb 28,  9:42am, Sven Wischnowsky wrote:
}
} - Decide on a name for the concept so that we can give _do_type its
}   final name and update the docs.

What if we called the function `_common'?  It's use is both "commonplace"
and "shared" ...

} - Probably change the order of the strings given to _do_type (these
}   are the strings used for lookup, e.g. command names for normal
}   completion). These should be from most to least specific, I think.

That sounds sensible.

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Per command _redirect completion
  2002-02-28  6:35         ` Felix Rosencrantz
@ 2002-02-28  8:42           ` Sven Wischnowsky
  2002-03-01  5:47             ` Bart Schaefer
  2002-03-01  9:24             ` Oliver Kiddle
  0 siblings, 2 replies; 15+ messages in thread
From: Sven Wischnowsky @ 2002-02-28  8:42 UTC (permalink / raw)
  To: zsh-workers


Felix Rosencrantz wrote:

> Looks good to me.  Though am seeing an error with the value completions.  While
> the redirs and normal completion don't seem to have a problem. 
> 
> host@ TZ=<TAB>
> _normal:74: division by zero
> host@ DISPLAY=<TAB>
> _normal:74: ':' without '?'
> 
> _normal:74:service="${${(e):-\$${__services}[$_comp_command1]}:-$_comp_command1}"

Yup, had this too, somtimes. Try the new and improved patch below...

It's still not in its final form, but definitely getting better. No
more need to define new types in the _comp_assoc array by hand,
compdef() will do it automatically. Only two small value-functions
left. The stuff in _normal has been put into separate function
`_do_type', which needs a better name (for which I need help).

Between the things to do:

- Decide on a name for the concept so that we can give _do_type its
  final name and update the docs.
- Cleanup _value. Especially the call to _do_type should probably be
  moved further down so that completion for values of assocs is tried
  first. As with redirection we can use `-T values -default-' fro
  default completion. This could even be integrated into _value which
  would then decide what to do based on $service.
- Probably change the order of the strings given to _do_type (these
  are the strings used for lookup, e.g. command names for normal
  completion). These should be from most to least specific, I think.
- Improve _redirect to use more information about the redirection
  operator once we have it.
- Update _compdef.

Every help is appreciated, especially for the first point.


Bye
  Sven

diff -ur -r ../oz/Completion/Base/Completer/_complete ./Completion/Base/Completer/_complete
--- ../oz/Completion/Base/Completer/_complete	Tue Feb 26 20:56:19 2002
+++ ./Completion/Base/Completer/_complete	Wed Feb 27 22:32:22 2002
@@ -95,7 +95,7 @@
 
 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 @@
   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 @@
       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 -ur -r ../oz/Completion/Base/Core/_do_type ./Completion/Base/Core/_do_type
--- ../oz/Completion/Base/Core/_do_type	Wed Feb 27 22:28:45 2002
+++ ./Completion/Base/Core/_do_type	Wed Feb 27 23:12:31 2002
@@ -0,0 +1,91 @@
+#autoload
+
+local comp pat val name i ret=1 _compskip="$_compskip"
+local curcontext="$curcontext" service str
+local __comps __patcomps __postpatcomps __services
+
+# If we get the option `-s', we don't reset `_compskip'.
+
+if [[ "$1" = -s ]]; then
+  shift
+else
+  _compskip=''
+fi
+
+__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 -ur -r ../oz/Completion/Base/Core/_normal ./Completion/Base/Core/_normal
--- ../oz/Completion/Base/Core/_normal	Tue Feb 26 20:56:19 2002
+++ ./Completion/Base/Core/_normal	Wed Feb 27 22:29:17 2002
@@ -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 @@
   [[ -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
+_do_type "$skip[@]" comps "_$comp_command1" "_$comp_command2"
diff -ur -r ../oz/Completion/Base/Utility/_contexts ./Completion/Base/Utility/_contexts
--- ../oz/Completion/Base/Utility/_contexts	Tue Feb 26 20:56:19 2002
+++ ./Completion/Base/Utility/_contexts	Tue Feb 26 23:44:51 2002
@@ -6,8 +6,19 @@
 # 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.
+# You may also select the assocs to use with the `-T assoc' option.
 
-local i tmp ret=1 service or
+local i tmp ret=1 service or type
+
+type=(-T comps)
+zparseopts -D o=or T:=type
+
+type="$type[2]"
+if (( $#or )); then
+  or=yes
+else
+  or=
+fi
 
 if [[ $1 = -o ]]; then
   or=yes
@@ -15,8 +26,9 @@
 fi
 
 for i; do
-  tmp="$_comps[$i]"
-  [[ -n "$tmp" ]] && service="${_services[$i]:-$i}" && eval "$tmp" && ret=0
+  tmp="${(e):-\$_${type}[$i]}"
+  [[ -n "$tmp" ]] && service="${${(e):-\$_service${type}[$i]}:-$i}" &&
+      eval "$tmp" && ret=0
   [[ -n "$or" && ret -eq 0 ]] && return 0
 done
 
diff -ur -r ../oz/Completion/Base/Utility/_set_command ./Completion/Base/Utility/_set_command
--- ../oz/Completion/Base/Utility/_set_command	Wed Feb 27 22:28:17 2002
+++ ./Completion/Base/Utility/_set_command	Wed Feb 27 22:27:46 2002
@@ -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_command1\=$command
+  _comp_command2="$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 -ur -r ../oz/Completion/Unix/Type/_files ./Completion/Unix/Type/_files
--- ../oz/Completion/Unix/Type/_files	Tue Feb 26 20:56:19 2002
+++ ./Completion/Unix/Type/_files	Wed Feb 27 22:35:35 2002
@@ -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 -ur -r ../oz/Completion/Unix/Type/_printers ./Completion/Unix/Type/_printers
--- ../oz/Completion/Unix/Type/_printers	Tue Feb 26 20:56:19 2002
+++ ./Completion/Unix/Type/_printers	Wed Feb 27 21:18:55 2002
@@ -1,4 +1,4 @@
-#autoload
+#compdef -T values PRINTER LPDEST
 
 local expl ret=1 list disp sep
 
diff -ur -r ../oz/Completion/Unix/Type/_terminals ./Completion/Unix/Type/_terminals
--- ../oz/Completion/Unix/Type/_terminals	Tue Feb 26 20:56:19 2002
+++ ./Completion/Unix/Type/_terminals	Wed Feb 27 21:19:33 2002
@@ -1,4 +1,4 @@
-#compdef infocmp
+#compdef infocmp -T values TERM
 
 local desc expl
 
diff -ur -r ../oz/Completion/Unix/Type/_time_zone ./Completion/Unix/Type/_time_zone
--- ../oz/Completion/Unix/Type/_time_zone	Tue Feb 26 20:56:19 2002
+++ ./Completion/Unix/Type/_time_zone	Wed Feb 27 21:20:11 2002
@@ -1,4 +1,4 @@
-#compdef
+#compdef -T values TZ
 
 local expl
 
diff -ur -r ../oz/Completion/X/Type/_x_display ./Completion/X/Type/_x_display
--- ../oz/Completion/X/Type/_x_display	Tue Feb 26 20:56:19 2002
+++ ./Completion/X/Type/_x_display	Wed Feb 27 21:18:14 2002
@@ -1,3 +1,3 @@
-#autoload
+#compdef -T values DISPLAY
 
 _tags displays && _hosts -S ':0 ' -r :
diff -ur -r ../oz/Completion/Zsh/Context/_default ./Completion/Zsh/Context/_default
--- ../oz/Completion/Zsh/Context/_default	Tue Feb 26 20:56:19 2002
+++ ./Completion/Zsh/Context/_default	Wed Feb 27 21:58:26 2002
@@ -19,7 +19,7 @@
 # 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 -ur -r ../oz/Completion/Zsh/Context/_redirect ./Completion/Zsh/Context/_redirect
--- ../oz/Completion/Zsh/Context/_redirect	Tue Feb 26 20:56:19 2002
+++ ./Completion/Zsh/Context/_redirect	Wed Feb 27 22:45:54 2002
@@ -1,3 +1,15 @@
 #compdef -redirect-
 
-_files
+local strs _comp_command1 _comp_command2
+
+_set_command
+
+strs=( "$compstate[redirect]" )
+
+if [[ -n "$_comp_command1" ]]; then
+  strs=( "$strs[@]"
+         "${_comp_command1}:$strs[1]" )
+  [[ -n "$_comp_command2" ]] && strs=( "$strs[@]" "${_comp_command2}:$strs[1]" )
+fi
+
+_do_type redirs "$strs[@]"
diff -ur -r ../oz/Completion/Zsh/Context/_value ./Completion/Zsh/Context/_value
--- ../oz/Completion/Zsh/Context/_value	Wed Feb 27 00:14:27 2002
+++ ./Completion/Zsh/Context/_value	Wed Feb 27 22:03:03 2002
@@ -1,70 +1,52 @@
 #compdef -value- -array-value-
 
-_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.
-
-  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 (( CURRENT & 1 )); then
-      _wanted association-keys expl 'association key' \
-          compadd -k "$compstate[parameter]"
-    else
-      compstate[parameter]="${compstate[parameter]}-${words[CURRENT-1]}"
-      _value "$@"
-    fi
-  else
-    local pats
+# You can customize completion for different parameters by writing
+# functions with the tag-line `#compdef -T value <name>'.
+
+local strs type
+
+type="${(Pt)compstate[parameter]}"
 
-    if { zstyle -a ":completion:${curcontext}:" assign-list pats &&
-         [[ "$compstate[parameter]" = (${(j:|:)~pats}) ]] } ||
-       [[ "$PREFIX$SUFFIX" = *:* ]]; then
-      compset -P '*:'
-      compset -S ':*'
-      _default -r '\-\n\t /:' "$@"
-    else
-      _default "$@"
-    fi
+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]" "${compstate[parameter]}:$type" )
 
-_value:CPPFLAGS () {
-  compset -q
-  if compset -P '-I'; then
-    _files -/ "$@"
+if [[ "$compstate[context]" != *value && -n "$_comp_command1" ]]; then
+  strs=( "$strs[@]" "${_comp_command1}:$^strs[@]" )
+  [[ -n "$_comp_command2" ]] &&
+      strs=( "$strs[@]" "${_comp_command2}:${(@)^strs[1,2]}" )
+fi
+
+_do_type values "$strs[@]" && return 0
+
+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]"
   else
-    _default "$@"
+    compstate[parameter]="${compstate[parameter]}-${words[CURRENT-1]}"
+    _value "$@"
   fi
-}
+else
+  local pats
 
-_value:LDFLAGS () {
-  compset -q
-  if compset -P '-L'; then
-    _files -/ "$@"
-  elif compset -P '-R'; then
+  if { zstyle -a ":completion:${curcontext}:" assign-list pats &&
+       [[ "$compstate[parameter]" = (${(j:|:)~pats}) ]] } ||
+     [[ "$PREFIX$SUFFIX" = *:* ]]; then
     compset -P '*:'
     compset -S ':*'
-    _files -/ -S/ -r '\n\t\- /:' "$@"
+    _default -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 -ur -r ../oz/Completion/Zsh/Context/_value_CPPFLAGS ./Completion/Zsh/Context/_value_CPPFLAGS
--- ../oz/Completion/Zsh/Context/_value_CPPFLAGS	Wed Feb 27 00:14:27 2002
+++ ./Completion/Zsh/Context/_value_CPPFLAGS	Wed Feb 27 00:25:03 2002
@@ -0,0 +1,8 @@
+#compdef -T values CPPFLAGS
+
+compset -q
+if compset -P '-I'; then
+  _files -/ "$@"
+else
+  _default "$@"
+fi
diff -ur -r ../oz/Completion/Zsh/Context/_value_LDFLAGS ./Completion/Zsh/Context/_value_LDFLAGS
--- ../oz/Completion/Zsh/Context/_value_LDFLAGS	Wed Feb 27 00:14:27 2002
+++ ./Completion/Zsh/Context/_value_LDFLAGS	Wed Feb 27 00:25:24 2002
@@ -0,0 +1,12 @@
+#compdef -T values 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
diff -ur -r ../oz/Completion/compdump ./Completion/compdump
--- ../oz/Completion/compdump	Tue Feb 26 20:56:19 2002
+++ ./Completion/compdump	Wed Feb 27 23:10:35 2002
@@ -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 @@
 
 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
diff -ur -r ../oz/Completion/compinit ./Completion/compinit
--- ../oz/Completion/compinit	Tue Feb 26 20:56:19 2002
+++ ./Completion/compinit	Wed Feb 27 23:08:37 2002
@@ -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 @@
   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 -Ua _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 @@
 # 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 @@
 # 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 @@
 #   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 @@
   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 @@
     # 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 @@
 
     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 @@
 	fi
 	shift 3
       done
-      ;;	 
+      ;;
     key)
       if [[ $# -lt 2 ]]; then
         echo "$0: missing keys"
@@ -348,40 +403,66 @@
       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 -ur -r ../oz/Doc/Zsh/compsys.yo ./Doc/Zsh/compsys.yo
--- ../oz/Doc/Zsh/compsys.yo	Tue Feb 26 20:56:17 2002
+++ ./Doc/Zsh/compsys.yo	Wed Feb 27 00:37:21 2002
@@ -173,14 +173,27 @@
 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 what kind of
+overall context the function is to be used.  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 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)
 )
-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 +267,10 @@
 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
@@ -3553,7 +3566,7 @@
 the functions for the fields if they are called.
 )
 findex(_contexts)
-item(tt(_contexts) [ tt(-o) ] var(names) ...)(
+item(tt(_contexts) [ tt(-o) ] [ tt(-T) var(type) ] 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
@@ -3564,6 +3577,10 @@
 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.
+
+This function basically calls the tt(_normal) function repeatedly and
+if the tt(-T) option is given the var(type) is given to tt(_normal) as
+an argument to tell it which type of completion function to use.
 )
 findex(_describe)
 item(tt(_describe) [ tt(-o) ] var(descr) var(name1) [ var(name2) ] var(opts) ... tt(-)tt(-) ...)(
@@ -3789,7 +3806,7 @@
 )
 )
 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 +3825,13 @@
 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))(

-- 
Sven Wischnowsky                          wischnow@berkom.de


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Per command _redirect completion
@ 2002-02-28  6:35         ` Felix Rosencrantz
  2002-02-28  8:42           ` Sven Wischnowsky
  0 siblings, 1 reply; 15+ messages in thread
From: Felix Rosencrantz @ 2002-02-28  6:35 UTC (permalink / raw)
  To: zsh-workers

Looks good to me.  Though am seeing an error with the value completions.  While
the redirs and normal completion don't seem to have a problem. 

host@ TZ=<TAB>
_normal:74: division by zero
host@ DISPLAY=<TAB>
_normal:74: ':' without '?'

_normal:74:service="${${(e):-\$${__services}[$_comp_command1]}:-$_comp_command1}"

-FR.

__________________________________________________
Do You Yahoo!?
Yahoo! Greetings - Send FREE e-cards for every occasion!
http://greetings.yahoo.com


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Per command _redirect completion
  2002-02-27 13:10         ` Oliver Kiddle
@ 2002-02-27 14:30           ` Sven Wischnowsky
  0 siblings, 0 replies; 15+ messages in thread
From: Sven Wischnowsky @ 2002-02-27 14:30 UTC (permalink / raw)
  To: zsh-workers


Oliver Kiddle wrote:

> 
>  --- Sven Wischnowsky <wischnow@berkom.de> wrote: > 
> 
> > And one (mostly) unrelated remark: in a private mail Oliver asked if
> > it were possible to supply the completion widgets with a list of
> > redirections on the line. Collecting this information shouldn't be
> > too
> > complicated. Any suggestions for how we should pas this information
> > to
> > the completion function? An array containing values of the form
> > `<redir-op>:<word>'?
> 
> The array sounds reasonable. What happens with something like 2>&1?
> What can the redir op be - just < and > or a variety of things. What
> about another command being piped to the one it is completing.

You can have a look at it by trying completion after various
redirection operators and then using `echo $_lastcomp[redirect]'.
They are the ones you can see in the table at lex.c:128. There are
almost certainly some interesting things missing (e.g. the descriptor
number used in `2>...'). Just some more things that would have to be
put into that array (and the lookup string in _redirect).

Pipes are generally not supported currently -- separates different
commands and that part of the code is pretty old.

> > diff -ur -r ../oz/Completion/Base/Utility/_contexts
> > +# You may also select the assocs to use with the `-T assoc' option.
> 
> I know we only renamed it a year ago but _contexts perhaps could be
> better named.

Hm. I don't think it's too bad, but then I'm not a native English
speaker.

> > diff -ur -r ../oz/Completion/Zsh/Context/_value_PRINTER
> > ./Completion/Zsh/Context/_value_PRINTER
> > @@ -0,0 +1,3 @@
> > +#compdef -T values PRINTER LPDEST
> > +
> > +_printers
> 
> Do we really want lots of tiny little functions like this one? Can't we
> just stick the compdef line in _printers itself. We have a compdef for
> commands like rmdir in _directories which is a similar situation.

Seems that I didn't make it clear enough that I only consider the core
of this patch to be near its final form (basically the code in
compinit and _normal, where the latter will be slightly modified and
moved to a separate function). I just didn't want to change too many
functions that won't have to be changed anyway.

The way it's implemented we have many different possibilities for how
to handle this. For some of the functions we have already we can, as
you correctly saw, modify already existing function-files like
_printer, for others we could group them together in a single file and
use $service to decide what exactly to complete (grouping together
parameters or redirections that belong together in the same way we
already do it for commands). And for others we can use new files as in
this example patch.

> Have I also understood correctly, that the compdef changes allow
> multiple uses of -T so that _gzip might start with:
>     #compdef gzip gunzip gzcat=gunzip -T values GZIP

Right. Good? ;-)

> Sorry, but I've only had time to glance over this. I'll try it out and
> reply more fully later.

Thanks!


Bye
  Sven

-- 
Sven Wischnowsky                          wischnow@berkom.de


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Per command _redirect completion
  2002-02-27  9:35       ` Sven Wischnowsky
@ 2002-02-27 13:10         ` Oliver Kiddle
  2002-02-27 14:30           ` Sven Wischnowsky
  2002-02-28  6:35         ` Felix Rosencrantz
  1 sibling, 1 reply; 15+ messages in thread
From: Oliver Kiddle @ 2002-02-27 13:10 UTC (permalink / raw)
  To: zsh-workers


 --- Sven Wischnowsky <wischnow@berkom.de> wrote: > 

> And one (mostly) unrelated remark: in a private mail Oliver asked if
> it were possible to supply the completion widgets with a list of
> redirections on the line. Collecting this information shouldn't be
> too
> complicated. Any suggestions for how we should pas this information
> to
> the completion function? An array containing values of the form
> `<redir-op>:<word>'?

The array sounds reasonable. What happens with something like 2>&1?
What can the redir op be - just < and > or a variety of things. What
about another command being piped to the one it is completing.

> diff -ur -r ../oz/Completion/Base/Utility/_contexts
> +# You may also select the assocs to use with the `-T assoc' option.

I know we only renamed it a year ago but _contexts perhaps could be
better named.

> diff -ur -r ../oz/Completion/Zsh/Context/_value_PRINTER
> ./Completion/Zsh/Context/_value_PRINTER
> @@ -0,0 +1,3 @@
> +#compdef -T values PRINTER LPDEST
> +
> +_printers

Do we really want lots of tiny little functions like this one? Can't we
just stick the compdef line in _printers itself. We have a compdef for
commands like rmdir in _directories which is a similar situation.

Have I also understood correctly, that the compdef changes allow
multiple uses of -T so that _gzip might start with:
    #compdef gzip gunzip gzcat=gunzip -T values GZIP

Sorry, but I've only had time to glance over this. I'll try it out and
reply more fully later.

Oliver


__________________________________________________
Do You Yahoo!?
Everything you'll ever need on one web page
from News and Sport to Email and Music Charts
http://uk.my.yahoo.com


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Per command _redirect completion
  2002-02-26  8:44     ` Sven Wischnowsky
@ 2002-02-27  9:35       ` Sven Wischnowsky
  2002-02-27 13:10         ` Oliver Kiddle
  2002-02-28  6:35         ` Felix Rosencrantz
  0 siblings, 2 replies; 15+ messages in thread
From: Sven Wischnowsky @ 2002-02-27  9:35 UTC (permalink / raw)
  To: zsh-workers


I wrote:

> ...
> 
> I would try to make compdef and parts of _normal (and probably
> _complete) generic enough to use an assoc given as argument, so that
> we get the pattern and services stuff.

Here is a first implementation, not in its final shape, so I'm not
going to commit it right now. But maybe some of you want to play with
it and give me some input.

Remarks (in no particular order):

- To try this, you should remove your dump-file.
- Most of the changes are currently in _normal. I'm planning to change
  that, putting parts of it in a separate function that will be called
  from _normal, _value and _redirect.
  That function will also handle a -defult- context so that calling
  functions don't have to implement defaults themselves (see _redirect
  for an example).
  I'm searching a good name for this function and the whole concept,
  actually. If you look at the docs, you'll see that I was struggling
  and called it `type of completion function'. It's basically a new
  intermediate level, something like multiple sets of definitions.
  Any suggestions? (Besides trying to make this clearer in the docs?)
  That `type of ...' led to the naming of the compdef-option (-T).
- That new helper function will then get the name of the completion
  function type and the strings to use to look up definitions. For
  normal completion this will be the command name(s), for redirection
  I'd prefer a combination of command name and redirection operator.
  Then we could use a pattern-definition to write a function called
  for all output redirections and so on[*]. For values we currently
  use only the parameter name. For things like `make FOO=<TAB>' we
  might want to include the command name, too. And probably the
  parameter type, if it is known.
  Any other suggestions?
- The other important part to look at are the new _value_* functions,
  showing how this is used.
- Currently there is a _comp_assocs array defined in compinit that
  contains the known names of types (comps, redirs, values). It would
  be nice if we could make this obsolete, probably making compdef()
  collect the type names and creating the associative arrays when
  needed. compdump would then have to be changed to output calls to
  `typeset -gA ...'.
- I wished there were an easier way than to use `${(e):-...}' in so
  many places. Sigh.
- Does anyone know about other places than redirections and values
  where this might be interesting to use? Even now it is already easy
  to define more sets.
- _compdef isn't changed yet.


And one (mostly) unrelated remark: in a private mail Oliver asked if
it were possible to supply the completion widgets with a list of
redirections on the line. Collecting this information shouldn't be too
complicated. Any suggestions for how we should pas this information to
the completion function? An array containing values of the form
`<redir-op>:<word>'?


Bye
  Sven

[*] Leading to a function that is to be called to complete
    non-existing files, that can also be used for mv and others.

diff -ur -r ../oz/Completion/Base/Completer/_complete ./Completion/Base/Completer/_complete
--- ../oz/Completion/Base/Completer/_complete	Tue Feb 26 20:56:19 2002
+++ ./Completion/Base/Completer/_complete	Tue Feb 26 21:31:26 2002
@@ -95,7 +95,7 @@
 
 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 @@
   ccarray[3]="$cname"
 
   comp="$_comps[$cname]"
-  service="${_services[$cname]:-$cname}"
+  service="${_servicecomps[$cname]:-$cname}"
 
   # If not, we use default completion, if any.
 
@@ -136,7 +136,7 @@
     comp="$_comps[-default-]"
   fi
   [[ -n "$comp" ]] &&
-      service="${_services[-default-]:--default-}" && eval "$comp" && ret=0
+      service="${_servicecomps[-default-]:--default-}" && eval "$comp" && ret=0
 fi
 
 _compskip=
diff -ur -r ../oz/Completion/Base/Core/_normal ./Completion/Base/Core/_normal
--- ../oz/Completion/Base/Core/_normal	Tue Feb 26 20:56:19 2002
+++ ./Completion/Base/Core/_normal	Wed Feb 27 00:13:48 2002
@@ -1,55 +1,78 @@
 #compdef -command-line-
 
-local comp command cmd1 cmd2 pat val name i ret=1 _compskip="$_compskip"
+local comp command pat val name i ret=1 _compskip="$_compskip"
 local curcontext="$curcontext" service
+local _comp_command1 _comp_command2
+local __comps __patcomps __postpatcomps __services
 
 # 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
+  shift
+else
+  _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).
+if (( ! $# )); then
 
-command="$words[1]"
-if [[ CURRENT -eq 1 ]]; then
-  curcontext="${curcontext%:*:*}:-command-:"
+  # Completing in command position?
 
-  comp="$_comps[-command-]"
-  [[ -n "$comp" ]] && eval "$comp" && ret=0
+  if [[ CURRENT -eq 1 ]]; then
+    curcontext="${curcontext%:*:*}:-command-:"
 
-  return ret
-else
-  if (( $+builtins[$command] + $+functions[$command] )); then
-    cmd1="$command"
-    curcontext="${curcontext%:*:*}:${cmd1}:"
+    comp="$_comps[-command-]"
+    [[ -n "$comp" ]] && eval "$comp" && ret=0
+
+    return ret
+  fi
+
+  1=comps
+fi
+
+__comps=_$1
+__patcomps=_pat$1
+__postpatcomps=_postpat$1
+__services=_service$1
+
+# Not completing in command position. We set up `_comp_command1' and
+# `_comp_command2' as two strings we have to search in the completion
+# definition arrays (e.g. a path and the last path name component).
+
+if [[ -n $+_comp_command1 ]]; then
+  command="$words[1]"
+  if [[ "$compstate[context]" = *value ]]; then
+    _comp_command1="$compstate[parameter]"
+    curcontext="${curcontext%:*:*}:${_comp_command1}:"
+  elif (( $+builtins[$command] + $+functions[$command] )); then
+    _comp_command1="$command"
+    curcontext="${curcontext%:*:*}:${_comp_command1}:"
   elif [[ "$command[1]" = '=' ]]; then
-    eval cmd1\=$command
-    cmd2="$command[2,-1]"
-    curcontext="${curcontext%:*:*}:${cmd2}:"
+    eval _comp_command1\=$command
+    _comp_command2="$command[2,-1]"
+    curcontext="${curcontext%:*:*}:${_comp_command2}:"
   elif [[ "$command" = ..#/* ]]; then
-    cmd1="${PWD}/$command"
-    cmd2="${command:t}"
-    curcontext="${curcontext%:*:*}:${cmd2}:"
+    _comp_command1="${PWD}/$command"
+    _comp_command2="${command:t}"
+    curcontext="${curcontext%:*:*}:${_comp_command2}:"
   elif [[ "$command" = */* ]]; then
-    cmd1="$command"
-    cmd2="${command:t}"
-    curcontext="${curcontext%:*:*}:${cmd2}:"
+    _comp_command1="$command"
+    _comp_command2="${command:t}"
+    curcontext="${curcontext%:*:*}:${_comp_command2}:"
   else
-    cmd1="$command"
-    cmd2="$commands[$command]"
-    curcontext="${curcontext%:*:*}:${cmd1}:"
+    _comp_command1="$command"
+    _comp_command2="$commands[$command]"
+    curcontext="${curcontext%:*:*}:${_comp_command1}:"
   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
+  service="${${(e):-\$${__services}[$_comp_command1]}:-$_comp_command1}"
+  for i in "${(@e):-\$${__patcomps}[(K)$_comp_command1]}"; do
     "$i" && ret=0
     if [[ "$_compskip" = *patterns* ]]; then
       break
@@ -58,9 +81,9 @@
       return ret
     fi
   done
-  if [[ -n "$cmd2" ]]; then
-    service="${_services[$cmd2]:-$cmd2}"
-    for i in "${(@)_patcomps[(K)$cmd2]}"; do
+  if [[ -n "$_comp_command2" ]]; then
+    service="${${(e):-\$${__services}[$_comp_command2]}:-$_comp_command2}"
+    for i in "${(@e):-\$${__patcomps}[(K)$_comp_command2]}"; do
       "$i" && ret=0
       if [[ "$_compskip" = *patterns* ]]; then
         break
@@ -75,12 +98,13 @@
 # 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}"
+name="$_comp_command1"
+comp="${(e):-\$${__comps}[$_comp_command1]}"
+service="${${(e):-\$${__services}[$_comp_command1]}:-$_comp_command1}"
+
+[[ -z "$comp" && -n "$_comp_command2" ]] &&
+    name="$_comp_command2" comp="${(e):-\$${__comps}[$_comp_command2]}" \
+    service="${${(e):-\$${__services}[$_comp_command2]}:-$_comp_command2}"
 
 # And generate the matches, probably using default completion.
 
@@ -88,14 +112,14 @@
   _compskip=patterns
   eval "$comp" && ret=0
   [[ "$_compskip" = (all|*patterns*) ]] && return ret
-elif [[ "$_compskip" != *default* ]]; then
+elif [[ "$1" = comps && "$_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
+  service="${${(e):-\$${__services}[$_comp_command1]}:-$_comp_command1}"
+  for i in "${(@e):-\$${__postpatcomps}[(K)$_comp_command1]}"; do
     _compskip=default
     "$i" && ret=0
     if [[ "$_compskip" = *patterns* ]]; then
@@ -105,9 +129,9 @@
       return ret
     fi
   done
-  if [[ -n "$cmd2" ]]; then
-    service="${_services[$cmd2]:-$cmd2}"
-    for i in "${(@)_postpatcomps[(K)$cmd2]}"; do
+  if [[ -n "$_comp_command2" ]]; then
+    service="${${(e):-\$${__services}[$_comp_command2]}:-$_comp_command2}"
+    for i in "${(@e):-\$${__postpatcomps}[(K)$_comp_command2]}"; do
       _compskip=default
       "$i" && ret=0
       if [[ "$_compskip" = *patterns* ]]; then
@@ -120,8 +144,10 @@
   fi
 fi
 
-[[ "$name" = -default- && -n "$comp" && "$_compskip" != (all|*default*) ]] &&
-  service="${_services[-default-]:--default-}" && eval "$comp" && ret=0
+[[ "$1" = comps && "$name" = -default- && -n "$comp" &&
+   "$_compskip" != (all|*default*) ]] &&
+  service="${${(e):-${__services}[-default-]}:--default-}" &&
+   eval "$comp" && ret=0
 
 _compskip=''
 
diff -ur -r ../oz/Completion/Base/Utility/_contexts ./Completion/Base/Utility/_contexts
--- ../oz/Completion/Base/Utility/_contexts	Tue Feb 26 20:56:19 2002
+++ ./Completion/Base/Utility/_contexts	Tue Feb 26 23:44:51 2002
@@ -6,8 +6,19 @@
 # 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.
+# You may also select the assocs to use with the `-T assoc' option.
 
-local i tmp ret=1 service or
+local i tmp ret=1 service or type
+
+type=(-T comps)
+zparseopts -D o=or T:=type
+
+type="$type[2]"
+if (( $#or )); then
+  or=yes
+else
+  or=
+fi
 
 if [[ $1 = -o ]]; then
   or=yes
@@ -15,8 +26,9 @@
 fi
 
 for i; do
-  tmp="$_comps[$i]"
-  [[ -n "$tmp" ]] && service="${_services[$i]:-$i}" && eval "$tmp" && ret=0
+  tmp="${(e):-\$_${type}[$i]}"
+  [[ -n "$tmp" ]] && service="${${(e):-\$_service${type}[$i]}:-$i}" &&
+      eval "$tmp" && ret=0
   [[ -n "$or" && ret -eq 0 ]] && return 0
 done
 
diff -ur -r ../oz/Completion/Zsh/Context/_redirect ./Completion/Zsh/Context/_redirect
--- ../oz/Completion/Zsh/Context/_redirect	Tue Feb 26 20:56:19 2002
+++ ./Completion/Zsh/Context/_redirect	Tue Feb 26 22:56:48 2002
@@ -1,3 +1,3 @@
 #compdef -redirect-
 
-_files
+_normal redirs || _files
diff -ur -r ../oz/Completion/Zsh/Context/_value ./Completion/Zsh/Context/_value
--- ../oz/Completion/Zsh/Context/_value	Wed Feb 27 00:14:27 2002
+++ ./Completion/Zsh/Context/_value	Wed Feb 27 00:09:28 2002
@@ -1,70 +1,29 @@
 #compdef -value- -array-value-
 
-_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>'.
 
-  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 (( CURRENT & 1 )); then
-      _wanted association-keys expl 'association key' \
-          compadd -k "$compstate[parameter]"
-    else
-      compstate[parameter]="${compstate[parameter]}-${words[CURRENT-1]}"
-      _value "$@"
-    fi
-  else
-    local pats
-
-    if { zstyle -a ":completion:${curcontext}:" assign-list pats &&
-         [[ "$compstate[parameter]" = (${(j:|:)~pats}) ]] } ||
-       [[ "$PREFIX$SUFFIX" = *:* ]]; then
-      compset -P '*:'
-      compset -S ':*'
-      _default -r '\-\n\t /:' "$@"
-    else
-      _default "$@"
-    fi
-  fi
-}
+_normal value && return 0
 
-_value:CPPFLAGS () {
-  compset -q
-  if compset -P '-I'; then
-    _files -/ "$@"
+if [[ "$compstate[parameter]" != *-* &&
+      "${(Pt)${compstate[parameter]}}" = assoc* ]]; then
+  if (( CURRENT & 1 )); then
+    _wanted association-keys expl 'association key' \
+        compadd -k "$compstate[parameter]"
   else
-    _default "$@"
+    compstate[parameter]="${compstate[parameter]}-${words[CURRENT-1]}"
+    _value "$@"
   fi
-}
+else
+  local pats
 
-_value:LDFLAGS () {
-  compset -q
-  if compset -P '-L'; then
-    _files -/ "$@"
-  elif compset -P '-R'; then
+  if { zstyle -a ":completion:${curcontext}:" assign-list pats &&
+       [[ "$compstate[parameter]" = (${(j:|:)~pats}) ]] } ||
+     [[ "$PREFIX$SUFFIX" = *:* ]]; then
     compset -P '*:'
     compset -S ':*'
-    _files -/ -S/ -r '\n\t\- /:' "$@"
+    _default -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 -ur -r ../oz/Completion/Zsh/Context/_value_CPPFLAGS ./Completion/Zsh/Context/_value_CPPFLAGS
--- ../oz/Completion/Zsh/Context/_value_CPPFLAGS	Wed Feb 27 00:14:27 2002
+++ ./Completion/Zsh/Context/_value_CPPFLAGS	Wed Feb 27 00:25:03 2002
@@ -0,0 +1,8 @@
+#compdef -T values CPPFLAGS
+
+compset -q
+if compset -P '-I'; then
+  _files -/ "$@"
+else
+  _default "$@"
+fi
diff -ur -r ../oz/Completion/Zsh/Context/_value_DISPLAY ./Completion/Zsh/Context/_value_DISPLAY
--- ../oz/Completion/Zsh/Context/_value_DISPLAY	Wed Feb 27 00:14:27 2002
+++ ./Completion/Zsh/Context/_value_DISPLAY	Wed Feb 27 00:25:31 2002
@@ -0,0 +1,3 @@
+#compdef -T values DISPLAY
+
+_x_display
diff -ur -r ../oz/Completion/Zsh/Context/_value_LDFLAGS ./Completion/Zsh/Context/_value_LDFLAGS
--- ../oz/Completion/Zsh/Context/_value_LDFLAGS	Wed Feb 27 00:14:27 2002
+++ ./Completion/Zsh/Context/_value_LDFLAGS	Wed Feb 27 00:25:24 2002
@@ -0,0 +1,12 @@
+#compdef -T values 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
diff -ur -r ../oz/Completion/Zsh/Context/_value_PRINTER ./Completion/Zsh/Context/_value_PRINTER
--- ../oz/Completion/Zsh/Context/_value_PRINTER	Wed Feb 27 00:14:27 2002
+++ ./Completion/Zsh/Context/_value_PRINTER	Wed Feb 27 00:25:12 2002
@@ -0,0 +1,3 @@
+#compdef -T values PRINTER LPDEST
+
+_printers
diff -ur -r ../oz/Completion/Zsh/Context/_value_TERM ./Completion/Zsh/Context/_value_TERM
--- ../oz/Completion/Zsh/Context/_value_TERM	Wed Feb 27 00:14:27 2002
+++ ./Completion/Zsh/Context/_value_TERM	Wed Feb 27 00:25:42 2002
@@ -0,0 +1,3 @@
+#compdef -T values TERM
+
+_terminals
diff -ur -r ../oz/Completion/Zsh/Context/_value_TZ ./Completion/Zsh/Context/_value_TZ
--- ../oz/Completion/Zsh/Context/_value_TZ	Wed Feb 27 00:14:27 2002
+++ ./Completion/Zsh/Context/_value_TZ	Wed Feb 27 00:25:49 2002
@@ -0,0 +1,3 @@
+#compdef -T values TZ
+
+_time_zone
diff -ur -r ../oz/Completion/Zsh/Context/_value~ ./Completion/Zsh/Context/_value~
--- ../oz/Completion/Zsh/Context/_value~	Wed Feb 27 00:14:27 2002
+++ ./Completion/Zsh/Context/_value~	Fri Feb 22 14:25:41 2002
@@ -0,0 +1,70 @@
+#compdef -value- -array-value-
+
+_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.
+
+  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 (( CURRENT & 1 )); then
+      _wanted association-keys expl 'association key' \
+          compadd -k "$compstate[parameter]"
+    else
+      compstate[parameter]="${compstate[parameter]}-${words[CURRENT-1]}"
+      _value "$@"
+    fi
+  else
+    local pats
+
+    if { zstyle -a ":completion:${curcontext}:" assign-list pats &&
+         [[ "$compstate[parameter]" = (${(j:|:)~pats}) ]] } ||
+       [[ "$PREFIX$SUFFIX" = *:* ]]; then
+      compset -P '*:'
+      compset -S ':*'
+      _default -r '\-\n\t /:' "$@"
+    else
+      _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 "$@"
diff -ur -r ../oz/Completion/compdump ./Completion/compdump
--- ../oz/Completion/compdump	Tue Feb 26 20:56:19 2002
+++ ./Completion/compdump	Tue Feb 26 23:34:51 2002
@@ -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,41 @@
 
 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
+
+  _d_tmp="_${_d_name}"
+  print "_${_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
diff -ur -r ../oz/Completion/compinit ./Completion/compinit
--- ../oz/Completion/compinit	Tue Feb 26 20:56:19 2002
+++ ./Completion/compinit	Wed Feb 27 00:20:53 2002
@@ -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,27 @@
   esac
 done
 
-# The associative array containing the definitions for the commands and
+# The name suffixes for the associative arrays containing the functions
+# to call.
+#
+# NOTE: you have to update this array when defining new types of
+#       completion function sets.
+
+_comp_assocs=(comps redirs values)
+
+# 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*'.
+
+for _i_name in "${(@)_comp_assocs}"; do
+  typeset -gA _$_i_name _service$_i_name _pat$_i_name _postpat$_i_name
+done
+
+# `_compautos' contains the names and options for autoloaded functions
+# that get options.
 
-typeset -gA _comps _services _patcomps _postpatcomps _compautos
+typeset -gA _compautos
 
 # The associative array use to report information about the last
 # completion to the outside.
@@ -176,6 +192,9 @@
 # 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 +210,8 @@
 # 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 +233,12 @@
 #   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 +267,8 @@
   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 +277,41 @@
     # 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
+          if (( ! ${_comp_assocs[(I)$1]} )); then
+            echo "$0: unknown type"
+            return 1
+          fi
+          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 +326,44 @@
 
     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
+          if (( ! ${_comp_assocs[(I)$1]} )); then
+            echo "$0: unknown type"
+            return 1
+          fi
+          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
+          if (( ! ${_comp_assocs[(I)$1]} )); then
+            echo "$0: unknown type"
+            return 1
+          fi
+          assoc="$1"
+          shift
+        else
+          eval "_postpat${assoc}"'[$1]="$func"'
+          shift
+        fi
+      done
       ;;
     widgetkey)
       while [[ -n $1 ]]; do
@@ -321,7 +383,7 @@
 	fi
 	shift 3
       done
-      ;;	 
+      ;;
     key)
       if [[ $# -lt 2 ]]; then
         echo "$0: missing keys"
@@ -348,40 +410,70 @@
       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
+          if (( ! ${_comp_assocs[(I)$1]} )); then
+            echo "$0: unknown type"
+            return 1
+          fi
+          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
+      if (( ! ${_comp_assocs[(I)$1]} )); then
+        echo "$0: unknown type"
+        return 1
+      fi
+      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 -ur -r ../oz/Doc/Zsh/compsys.yo ./Doc/Zsh/compsys.yo
--- ../oz/Doc/Zsh/compsys.yo	Tue Feb 26 20:56:17 2002
+++ ./Doc/Zsh/compsys.yo	Wed Feb 27 00:37:21 2002
@@ -173,14 +173,27 @@
 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 what kind of
+overall context the function is to be used.  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 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)
 )
-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 +267,10 @@
 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
@@ -3553,7 +3566,7 @@
 the functions for the fields if they are called.
 )
 findex(_contexts)
-item(tt(_contexts) [ tt(-o) ] var(names) ...)(
+item(tt(_contexts) [ tt(-o) ] [ tt(-T) var(type) ] 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
@@ -3564,6 +3577,10 @@
 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.
+
+This function basically calls the tt(_normal) function repeatedly and
+if the tt(-T) option is given the var(type) is given to tt(_normal) as
+an argument to tell it which type of completion function to use.
 )
 findex(_describe)
 item(tt(_describe) [ tt(-o) ] var(descr) var(name1) [ var(name2) ] var(opts) ... tt(-)tt(-) ...)(
@@ -3789,7 +3806,7 @@
 )
 )
 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 +3825,13 @@
 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))(

-- 
Sven Wischnowsky                          wischnow@berkom.de


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Per command _redirect completion
  2002-02-26  6:56   ` Felix Rosencrantz
@ 2002-02-26  8:44     ` Sven Wischnowsky
  2002-02-27  9:35       ` Sven Wischnowsky
  0 siblings, 1 reply; 15+ messages in thread
From: Sven Wischnowsky @ 2002-02-26  8:44 UTC (permalink / raw)
  To: zsh-workers


Felix Rosencrantz wrote:

> --- Oliver Kiddle <okiddle@yahoo.co.uk> wrote:
> > I would prefer if - both for redirection and for values - we had
> > separate associative arrays like _comps. And then, perhaps a compdef
> > option for adding to these new associations.
> > 
> > This is for a number of reasons, one being consistency with the way we
> > handle commands. ...
> > This redirection suggestion is even more linked to the command being
> > run and again it would be more useful to use the existing command's
> > completion function and have it work out what sort of files to
> > complete.
> 
> Yep, that's exactly why I asked, there is an inconsistency.  Though, I'm not
> volunteering to graft redirection and value/parameter onto the _comps or a
> similar array.  Would have to be a job for someone else.

I would try to make compdef and parts of _normal (and probably
_complete) generic enough to use an assoc given as argument, so that
we get the pattern and services stuff.

I think I'll give it a try.

Bye
  Sven

-- 
Sven Wischnowsky                          wischnow@berkom.de


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Per command _redirect completion
  2002-02-25  9:47 ` Oliver Kiddle
@ 2002-02-26  6:56   ` Felix Rosencrantz
  2002-02-26  8:44     ` Sven Wischnowsky
  0 siblings, 1 reply; 15+ messages in thread
From: Felix Rosencrantz @ 2002-02-26  6:56 UTC (permalink / raw)
  To: Oliver Kiddle; +Cc: zsh-workers

--- Oliver Kiddle <okiddle@yahoo.co.uk> wrote:
> I would prefer if - both for redirection and for values - we had
> separate associative arrays like _comps. And then, perhaps a compdef
> option for adding to these new associations.
> 
> This is for a number of reasons, one being consistency with the way we
> handle commands. ...
> This redirection suggestion is even more linked to the command being
> run and again it would be more useful to use the existing command's
> completion function and have it work out what sort of files to
> complete.

Yep, that's exactly why I asked, there is an inconsistency.  Though, I'm not
volunteering to graft redirection and value/parameter onto the _comps or a
similar array.  Would have to be a job for someone else.

Though I would like to see better completion for redirection.  Redirection is
one of those situations where the file may not already exist, so better
guessing tricks would be useful.

-FR

__________________________________________________
Do You Yahoo!?
Yahoo! Sports - Coverage of the 2002 Olympic Games
http://sports.yahoo.com


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Per command _redirect completion
  2002-02-25  5:59 Felix Rosencrantz
  2002-02-25  8:18 ` Sven Wischnowsky
@ 2002-02-25  9:47 ` Oliver Kiddle
  2002-02-26  6:56   ` Felix Rosencrantz
  1 sibling, 1 reply; 15+ messages in thread
From: Oliver Kiddle @ 2002-02-25  9:47 UTC (permalink / raw)
  To: Felix Rosencrantz; +Cc: zsh-workers

 --- Felix Rosencrantz <f_rosencrantz@yahoo.com> wrote:
> Below is a proposed change for the _redirect completion function.  If
> there
> is a function with the name _redirect:COMMAND, that function is
> called
> to perform completion.  Otherwise, the default behavior of completing
> files
> is performed.  This is the way we do variable specific dispatch for
> _value.
> 
> If there are no objections, I'll create a real diff and checkin.

I would prefer if - both for redirection and for values - we had
separate associative arrays like _comps. And then, perhaps a compdef
option for adding to these new associations.

This is for a number of reasons, one being consistency with the way we
handle commands.

Many of the _value: functions just call one other function. It'd be
better if instead, for example we could specify in the #compdef on
_x_display to handle the $DISPLAY variable. Also, in many cases what
should be completed is already being done in another function. For
example, $GZIP should complete gzip options. It'd be more useful to
direct this into _gzip where gzip options are already completed and
_gzip would just need a compstate test. 

This redirection suggestion is even more linked to the command being
run and again it would be more useful to use the existing command's
completion function and have it work out what sort of files to
complete.

Oliver



__________________________________________________
Do You Yahoo!?
Everything you'll ever need on one web page
from News and Sport to Email and Music Charts
http://uk.my.yahoo.com


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Per command _redirect completion
  2002-02-25  5:59 Felix Rosencrantz
@ 2002-02-25  8:18 ` Sven Wischnowsky
  2002-02-25  9:47 ` Oliver Kiddle
  1 sibling, 0 replies; 15+ messages in thread
From: Sven Wischnowsky @ 2002-02-25  8:18 UTC (permalink / raw)
  To: zsh-workers


Felix Rosencrantz wrote:

> Below is a proposed change for the _redirect completion function.  If there
> is a function with the name _redirect:COMMAND, that function is called
> to perform completion.  Otherwise, the default behavior of completing files
> is performed.  This is the way we do variable specific dispatch for _value.

Makes sense, I think.


Bye
  Sven

-- 
Sven Wischnowsky                          wischnow@berkom.de


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Per command _redirect completion
@ 2002-02-25  5:59 Felix Rosencrantz
  2002-02-25  8:18 ` Sven Wischnowsky
  2002-02-25  9:47 ` Oliver Kiddle
  0 siblings, 2 replies; 15+ messages in thread
From: Felix Rosencrantz @ 2002-02-25  5:59 UTC (permalink / raw)
  To: zsh-workers

Below is a proposed change for the _redirect completion function.  If there
is a function with the name _redirect:COMMAND, that function is called
to perform completion.  Otherwise, the default behavior of completing files
is performed.  This is the way we do variable specific dispatch for _value.

If there are no objections, I'll create a real diff and checkin.

-FR.
---------------------------------------------------------------------------
#compdef -redirect-

if (( $+functions[_redirect:$words[1]] )); then
    "_redirect:$words[1]" "$@"
else
        _files
fi

__________________________________________________
Do You Yahoo!?
Yahoo! Sports - Coverage of the 2002 Olympic Games
http://sports.yahoo.com


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2002-03-04  8:52 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-03-02 16:28 Per command _redirect completion Felix Rosencrantz
  -- strict thread matches above, loose matches on Subject: below --
2002-02-25  5:59 Felix Rosencrantz
2002-02-25  8:18 ` Sven Wischnowsky
2002-02-25  9:47 ` Oliver Kiddle
2002-02-26  6:56   ` Felix Rosencrantz
2002-02-26  8:44     ` Sven Wischnowsky
2002-02-27  9:35       ` Sven Wischnowsky
2002-02-27 13:10         ` Oliver Kiddle
2002-02-27 14:30           ` Sven Wischnowsky
2002-02-28  6:35         ` Felix Rosencrantz
2002-02-28  8:42           ` Sven Wischnowsky
2002-03-01  5:47             ` Bart Schaefer
2002-03-04  8:50               ` Sven Wischnowsky
2002-03-01  9:24             ` Oliver Kiddle
2002-03-01 10:49               ` Sven Wischnowsky

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).