about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSven Wischnowsky <wischnow@users.sourceforge.net>2001-01-15 09:11:31 +0000
committerSven Wischnowsky <wischnow@users.sourceforge.net>2001-01-15 09:11:31 +0000
commitca585f812b02071cc261fb9dbe463bab6f8be602 (patch)
treee90c1af1169132098b62207ced35fdf83607e910
parenta11115ecee1b5fc02b4b714561ffdbc2d2a3e622 (diff)
downloadzsh-ca585f812b02071cc261fb9dbe463bab6f8be602.tar.gz
zsh-ca585f812b02071cc261fb9dbe463bab6f8be602.tar.xz
zsh-ca585f812b02071cc261fb9dbe463bab6f8be602.zip
add `services', allowing easier re-use of (parts of) completion functions (13346)
-rw-r--r--ChangeLog20
-rw-r--r--Completion/Bsd/_bsd_pkg2
-rw-r--r--Completion/Bsd/_kld2
-rw-r--r--Completion/Core/_compalso6
-rw-r--r--Completion/Core/_complete7
-rw-r--r--Completion/Core/_normal12
-rw-r--r--Completion/Core/compdump11
-rw-r--r--Completion/Core/compinit62
-rw-r--r--Completion/Debian/_apt4
-rw-r--r--Completion/Debian/_bug2
-rw-r--r--Completion/Debian/_dpkg2
-rw-r--r--Completion/User/_bzip26
-rw-r--r--Completion/User/_chown2
-rw-r--r--Completion/User/_compress2
-rw-r--r--Completion/User/_dvi2
-rw-r--r--Completion/User/_gzip6
-rw-r--r--Completion/User/_imagemagick2
-rw-r--r--Completion/User/_ispell2
-rw-r--r--Completion/User/_java2
-rw-r--r--Completion/User/_lp2
-rw-r--r--Completion/User/_make2
-rw-r--r--Completion/User/_mount2
-rw-r--r--Completion/User/_mysql_utils2
-rw-r--r--Completion/User/_pack6
-rw-r--r--Completion/User/_pbm12
-rw-r--r--Completion/User/_psutils2
-rw-r--r--Completion/User/_rcs6
-rw-r--r--Completion/User/_rlogin4
-rw-r--r--Completion/User/_ssh12
-rw-r--r--Completion/User/_tiff8
-rw-r--r--Completion/User/_yp2
-rw-r--r--Completion/X/_xutils2
-rw-r--r--Doc/Zsh/compsys.yo18
33 files changed, 161 insertions, 73 deletions
diff --git a/ChangeLog b/ChangeLog
index a8cbc064f..936ccbd3a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2001-01-15  Sven Wischnowsky  <wischnow@zsh.org>
+
+	* 13346: Completion/Bsd/_bsd_pkg, Completion/Bsd/_kld,
+ 	Completion/Core/_compalso, Completion/Core/_complete,
+ 	Completion/Core/_normal, Completion/Core/compdump,
+ 	Completion/Core/compinit, Completion/Debian/_apt,
+ 	Completion/Debian/_bug, Completion/Debian/_dpkg,
+ 	Completion/User/_bzip2, Completion/User/_chown,
+ 	Completion/User/_compress, Completion/User/_dvi,
+ 	Completion/User/_gzip, Completion/User/_imagemagick,
+ 	Completion/User/_ispell, Completion/User/_java,
+ 	Completion/User/_lp, Completion/User/_make,
+ 	Completion/User/_mount, Completion/User/_mysql_utils,
+ 	Completion/User/_pack, Completion/User/_pbm,
+ 	Completion/User/_psutils, Completion/User/_rcs,
+ 	Completion/User/_rlogin, Completion/User/_ssh,
+ 	Completion/User/_tiff, Completion/User/_yp, Completion/X/_xutils,
+ 	Doc/Zsh/compsys.yo: add `services', allowing easier re-use of
+ 	(parts of) completion functions (see also: 12977)
+	
 2001-01-12  Sven Wischnowsky  <wischnow@zsh.org>
 
 	* 13343: Src/Zle/compmatch.c, Src/Zle/compresult.c: fix for 13339
diff --git a/Completion/Bsd/_bsd_pkg b/Completion/Bsd/_bsd_pkg
index f302f8216..5089bc1a3 100644
--- a/Completion/Bsd/_bsd_pkg
+++ b/Completion/Bsd/_bsd_pkg
@@ -13,7 +13,7 @@ _bsd_pkg_packages() {
 }
 
 _bsd_pkg() {
-  case "${words[1]:t}" in
+  case "$service" in
   pkg_add)
     _arguments -s \
         '-v[be verbose]' \
diff --git a/Completion/Bsd/_kld b/Completion/Bsd/_kld
index 8fc719ccb..eefc8bf61 100644
--- a/Completion/Bsd/_kld
+++ b/Completion/Bsd/_kld
@@ -21,7 +21,7 @@ _kld_unload_id() {
 }
 
 _kld() {
-  case "${words[1]:t}" in
+  case "$service" in
   kldload)
     _arguments -s \
         '-v[be verbose]' \
diff --git a/Completion/Core/_compalso b/Completion/Core/_compalso
index 8df6b4a6f..5307bf30c 100644
--- a/Completion/Core/_compalso
+++ b/Completion/Core/_compalso
@@ -7,11 +7,11 @@
 # `_compalso -math-' to get the completions that would be generated for a
 # mathematical context.
 
-local i tmp ret=1
+local i tmp ret=1 service
 
 for i; do
-  tmp="$_comps[$1]"
-  [[ -z "$tmp" ]] || "$tmp" && ret=0
+  tmp="$_comps[$i]"
+  [[ -z "$tmp" ]] || service="${_services[$i]:-$i}" && "$tmp" && ret=0
 done
 
 return ret
diff --git a/Completion/Core/_complete b/Completion/Core/_complete
index 809df1fa9..28bb008ca 100644
--- a/Completion/Core/_complete
+++ b/Completion/Core/_complete
@@ -4,7 +4,7 @@
 # a normal completion function, but as one possible value for the
 # completer style.
 
-local comp name oldcontext ret=1
+local comp name oldcontext ret=1 service
 typeset -T curcontext="$curcontext" ccarray
 
 oldcontext="$curcontext"
@@ -95,6 +95,7 @@ fi
 
 comp="$_comps[-first-]"
 if [[ ! -z "$comp" ]]; then
+  service="${_services[-first-]:--first-}"
   ccarray[3]=-first-
   "$comp" && ret=0
   if [[ "$_compskip" = all ]]; then
@@ -123,6 +124,7 @@ else
   ccarray[3]="$cname"
 
   comp="$_comps[$cname]"
+  service="${_services[$cname]:-$cname}"
 
   # If not, we use default completion, if any.
 
@@ -133,7 +135,8 @@ else
     fi
     comp="$_comps[-default-]"
   fi
-  [[ -z "$comp" ]] || "$comp" && ret=0
+  [[ -z "$comp" ]] ||
+      service="${_services[-default-]:--default-}" && "$comp" && ret=0
 fi
 
 _compskip=
diff --git a/Completion/Core/_normal b/Completion/Core/_normal
index 54767f2f6..02229835a 100644
--- a/Completion/Core/_normal
+++ b/Completion/Core/_normal
@@ -1,7 +1,7 @@
 #compdef -command-line-
 
 local comp command cmd1 cmd2 pat val name i ret=1 _compskip="$_compskip"
-local curcontext="$curcontext"
+local curcontext="$curcontext" service
 
 # 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,
@@ -44,6 +44,7 @@ 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
@@ -54,6 +55,7 @@ if [[ "$_compskip" != (all|*patterns*) ]]; then
     fi
   done
   if [[ -n "$cmd2" ]]; then
+    service="${_services[$cmd2]:-$cmd2}"
     for i in "${(@)_patcomps[(K)$cmd2]}"; do
       "$i" && ret=0
       if [[ "$_compskip" = *patterns* ]]; then
@@ -71,8 +73,10 @@ fi
 ret=1
 name="$cmd1"
 comp="$_comps[$cmd1]"
+service="${_services[$cmd1]:-$cmd1}"
 
-[[ -z "$comp" ]] && name="$cmd2" comp="$_comps[$cmd2]"
+[[ -z "$comp" ]] &&
+    name="$cmd2" comp="$_comps[$cmd2]" service="${_services[$cmd2]:-$cmd2}"
 
 # And generate the matches, probably using default completion.
 
@@ -86,6 +90,7 @@ elif [[ "$_compskip" != *default* ]]; then
 fi
 
 if [[ "$_compskip" != (all|*patterns*) ]]; then
+  service="${_services[$cmd1]:-$cmd1}"
   for i in "${(@)_postpatcomps[(K)$cmd1]}"; do
     _compskip=default
     "$i" && ret=0
@@ -97,6 +102,7 @@ if [[ "$_compskip" != (all|*patterns*) ]]; then
     fi
   done
   if [[ -n "$cmd2" ]]; then
+    service="${_services[$cmd2]:-$cmd2}"
     for i in "${(@)_postpatcomps[(K)$cmd2]}"; do
       _compskip=default
       "$i" && ret=0
@@ -111,7 +117,7 @@ if [[ "$_compskip" != (all|*patterns*) ]]; then
 fi
 
 [[ "$name" = -default- && -n "$comp" && "$_compskip" != (all|*default*) ]] &&
-  "$comp" && ret=0
+  service="${_services[-default-]:--default-}" && "$comp" && ret=0
 
 _compskip=''
 
diff --git a/Completion/Core/compdump b/Completion/Core/compdump
index 25df17fbf..a94a41df6 100644
--- a/Completion/Core/compdump
+++ b/Completion/Core/compdump
@@ -35,8 +35,9 @@ fi
 
 print "#files: $#_d_files" > $_d_file
 
-# First dump the arrays _comps and _patcomps.  The quoting hieroglyphyics
-# ensure that a single quote inside a variable is itself correctly quoted.
+# First dump the arrays _comps, _services and _patcomps.  The quoting
+# hieroglyphyics ensure that a single quote inside a variable is itself
+# correctly quoted.
 
 print "_comps=(" >> $_d_file
 for _d_f in ${(ok)_comps}; do
@@ -44,6 +45,12 @@ for _d_f in ${(ok)_comps}; do
 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]}"
diff --git a/Completion/Core/compinit b/Completion/Core/compinit
index 86e4204f0..4203bcbc7 100644
--- a/Completion/Core/compinit
+++ b/Completion/Core/compinit
@@ -100,12 +100,13 @@ while [[ $# -gt 0 && $1 = -[dDiuC] ]]; do
   esac
 done
 
-# The associative array containing the definitions for the commands.
+# The associative array 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.
 
-typeset -gA _comps _patcomps _postpatcomps _compautos
+typeset -gA _comps _services _patcomps _postpatcomps _compautos
 
 # The associative array use to report information about the last
 # cmpletion to the outside.
@@ -198,12 +199,12 @@ comppostfuncs=()
 #   delete the definitions for the command names `bar' and `baz'
 
 compdef() {
-  local opt autol type func delete new i
+  local opt autol type func delete new i ret=0 cmd svc
 
   # Get the options.
 
   if [[ $#* -eq 0 ]]; then
-    echo "compdef needs parameters"
+    echo "$0: I needs arguments"
     return 1
   fi
   
@@ -233,11 +234,38 @@ compdef() {
   shift OPTIND-1
 
   if [[ $#* -eq 0 ]]; then
-    echo "compdef needs parameters"
+    echo "$0: I needs arguments"
     return 1
   fi
   
   if [[ -z "$delete" ]]; then
+    # If the first word contains an equal sign, all words must contain one
+    # 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}]"
+	  [[ -z "$func" ]] &&
+	    func="${_patcomps[(K)$svc][1]:-${_postpatcomps[(K)$svc][1]}}"
+          if [[ -n "$func" ]]; then
+	    _comps[$cmd]="$func"
+	    _services[$cmd]="$svc"
+	  else
+	    echo "$0: unknown command or service: $svc"
+	    ret=1
+	  fi
+	else
+	  echo "$0: invalid argument: $i"
+	  ret=1
+	fi
+      done
+
+      return ret
+    fi
+
     # Adding definitions, first get the name of the function name
     # and probably do autoloading.
 
@@ -307,15 +335,19 @@ compdef() {
     *)
       # For commands store the function name in the `_comps'
       # associative array, command names as keys.
-      if [[ -z "$new" ]]; then
-	for i; do
-	  _comps[$i]="$func"
-	done
-      else
-        for i; do
-          [[ "${+_comps[$i]}" -eq 0 ]] && _comps[$i]="$func"
-        done
-      fi
+      for i; do
+        if [[ "$i" = *\=* ]]; then
+	  cmd="${i%%\=*}"
+	  svc=yes
+        else
+	  cmd="$i"
+	  svc=
+        fi
+        if [[ -z "$new" || "${+_comps[$i]}" -eq 0 ]]; then
+          _comps[$cmd]="$func"
+	  [[ -n "$svc" ]] && _services[$cmd]="${i#*\=}"
+	fi
+      done
       ;;
     esac
   else
@@ -331,7 +363,7 @@ compdef() {
       # Oops, cannot do that yet.
 
       echo "$0: cannot restore key bindings"
-      return 1
+      return 1v
       ;;
     *)
       unset "_comps[$^@]"
diff --git a/Completion/Debian/_apt b/Completion/Debian/_apt
index 74d2dceca..62a38c0a3 100644
--- a/Completion/Debian/_apt
+++ b/Completion/Debian/_apt
@@ -1,12 +1,12 @@
 #compdef apt-get apt-cache apt-cdrom apt-config
 
 _apt () {
-  case "${words[1]:t}" in
+  case "$service" in
     apt-get) _apt-get "$@";;
     apt-cache) _apt-cache "$@";;
     apt-cdrom) _apt-cdrom "$@";;
     apt-config) _apt-config "$@";;
-    *) _message "unknown command $words[1]";;
+    *) _message "unknown command $service";;
   esac
 }
 
diff --git a/Completion/Debian/_bug b/Completion/Debian/_bug
index 1c67103e0..30993203f 100644
--- a/Completion/Debian/_bug
+++ b/Completion/Debian/_bug
@@ -18,7 +18,7 @@ _rb_commonargs=('(--bts)-B[use alternate BTS]:system:(debian gnome kde tdyc kde-
 	   '(--http_proxy)--proxy=:proxyhost:_hosts' \
 	   '(--proxy)--http_proxy=:proxyhost:_hosts')
 
-case "${words[1]:t}" in
+case "$service" in
 bug)
 _arguments '-c[exclude configs from report]' \
            '-f[argument is a file, not a package]' \
diff --git a/Completion/Debian/_dpkg b/Completion/Debian/_dpkg
index 90313b39a..ca6fdf783 100644
--- a/Completion/Debian/_dpkg
+++ b/Completion/Debian/_dpkg
@@ -86,7 +86,7 @@ _dpkg_options_recursive=('(--recursive)-R[recursive]' '(-R)--recursive')
 #  _dpkg_actions_install=('(--install)-i[install]' '(-i)--install')
 #  _dpkg_actions_record_avail=('(--record-avail)-A[record available]' '(-A)--record-avail')
 
-case "${words[1]:t}" in
+case "$service" in
 dpkg)
 _arguments -C -s "$_dpkg_actions[@]" \
            "$_dpkg_deb_actions[@]" \
diff --git a/Completion/User/_bzip2 b/Completion/User/_bzip2
index 53ec36967..cbb231c4d 100644
--- a/Completion/User/_bzip2
+++ b/Completion/User/_bzip2
@@ -1,12 +1,12 @@
-#compdef bzip2 bzcat bunzip2 bzip2recover
+#compdef bzip2 bunzip2 bzcat=bunzip2 bzip2recover
 
 local decompress expl state line curcontext="$curcontext"
 typeset -A opt_args
 
-case "${words[1]:t}" in
+case "$service" in
   bzip2recover) [[ $CURRENT = 2 ]] && state=files;;
   bzip2) decompress=no;&
-  bunzip2|bzcat) _arguments -C -s \
+  bunzip2) _arguments -C -s \
     '(--help)-h[display help message]' \
     '(-h)--help[display help message]' \
     '(--decompress --compress -z --test -t)-d[decompress]' \
diff --git a/Completion/User/_chown b/Completion/User/_chown
index 0363e838c..40f38d2f4 100644
--- a/Completion/User/_chown
+++ b/Completion/User/_chown
@@ -3,7 +3,7 @@
 local suf
 
 if [[ CURRENT -eq 2 || CURRENT -eq 3 && $words[CURRENT-1] = -* ]]; then
-  if [[ ${words[1]:t} = chgrp ]] || compset -P '*[:.]'; then
+  if [[ $service = chgrp ]] || compset -P '*[:.]'; then
     _groups
   else
     if [[ $OSTYPE = (solaris*|hpux*) ]]; then
diff --git a/Completion/User/_compress b/Completion/User/_compress
index 3521dfef6..9ba8c8e15 100644
--- a/Completion/User/_compress
+++ b/Completion/User/_compress
@@ -17,7 +17,7 @@ common_args2=( \
   '(-q)-v[display compression statistics]' \
   "${common_args1[@]}" )
 
-case "${words[1]:t}" in
+case "$service" in
   compress)
     _arguments -C -s \
       "-b[specify maximum number of bits used to replace common substring]:bits:(${bits[*]})" \
diff --git a/Completion/User/_dvi b/Completion/User/_dvi
index 9d551ea07..672b4419d 100644
--- a/Completion/User/_dvi
+++ b/Completion/User/_dvi
@@ -9,7 +9,7 @@ args=(
   ':output DVI file:_files -g \*.\(dvi\|DVI\)'
 )
 
-case "${words[1]:t}" in
+case "$service" in
 dvips)
   _arguments -s \
     '-a[make three passes]' \
diff --git a/Completion/User/_gzip b/Completion/User/_gzip
index 549936a96..a915715a4 100644
--- a/Completion/User/_gzip
+++ b/Completion/User/_gzip
@@ -1,10 +1,10 @@
-#compdef gzip gunzip gzcat
+#compdef gzip gunzip gzcat=gunzip
 
 local decompress expl curcontext="$curcontext" state line
 typeset -A opt_args
 
-case "${words[1]:t}" in
-gunzip|zcat|gzcat)
+case "$service" in
+gunzip)
   decompress=yes
   ;&
 gzip)
diff --git a/Completion/User/_imagemagick b/Completion/User/_imagemagick
index cf6604e3d..b297f3498 100644
--- a/Completion/User/_imagemagick
+++ b/Completion/User/_imagemagick
@@ -18,7 +18,7 @@ if (( $# )); then
   return
 fi
 
-case "${words[1]:t}" in
+case "$service" in
 display)
   _arguments -M 'm:{a-z}={A-Z}' \
       '*-backdrop[use full screen]' \
diff --git a/Completion/User/_ispell b/Completion/User/_ispell
index 7d81952dc..3eacee87f 100644
--- a/Completion/User/_ispell
+++ b/Completion/User/_ispell
@@ -1,6 +1,6 @@
 #compdef ispell buildhash munchlist findaffix tryaffix icombine ijoin
 
-case "${words[1]:t}" in
+case "$service" in
 ispell)
   _arguments -s \
     '(-n -h)-t[input file is in TeX/LaTeX format]' \
diff --git a/Completion/User/_java b/Completion/User/_java
index d92dbca3f..f906f0ae8 100644
--- a/Completion/User/_java
+++ b/Completion/User/_java
@@ -6,7 +6,7 @@ typeset -A opt_args tmpassoc
 
 jdb_args=()
 
-case "${words[1]:t}" in
+case "$service" in
 javac)
   _arguments \
     '-g-[generate debugging information]:debug:->debug' \
diff --git a/Completion/User/_lp b/Completion/User/_lp
index a81d348bb..b556f1bf5 100644
--- a/Completion/User/_lp
+++ b/Completion/User/_lp
@@ -5,7 +5,7 @@ local expl ret=1 printer list disp strs shown
 if compset -P -P || [[ "$words[CURRENT-1]" = -P ]]; then
   _printers
 else
-  if [[ "${words[1]:t}" = (lpq|lprm) ]]; then
+  if [[ "$service" = (lpq|lprm) ]]; then
     if [[ "$words" = *-P* ]]; then
       printer=(-P "${${words##*-P( |)}%% *}")
     else
diff --git a/Completion/User/_make b/Completion/User/_make
index b13224c06..958e2a5af 100644
--- a/Completion/User/_make
+++ b/Completion/User/_make
@@ -25,7 +25,7 @@ else
     file=Makefile
   elif [[ -e makefile ]]; then
     file=makefile
-  elif [[ -e GNUmakefile ]]; then
+  elif [[ -n "$_is_gnu[$words[1]]" && -e GNUmakefile ]]; then
     file=GNUmakefile
   else
     file=''
diff --git a/Completion/User/_mount b/Completion/User/_mount
index 50fa769b2..cbd762583 100644
--- a/Completion/User/_mount
+++ b/Completion/User/_mount
@@ -368,7 +368,7 @@ if (( ! $+_fs_any )); then
   esac
 fi
 
-if [[ "${words[1]:t}" = mount ]]; then
+if [[ "$service" = mount ]]; then
 
   # Here are the tests and tables for the arguments and options for
   # the `mount' program. The `fss' array has to be set to the names
diff --git a/Completion/User/_mysql_utils b/Completion/User/_mysql_utils
index c4648c818..ae7ffe72c 100644
--- a/Completion/User/_mysql_utils
+++ b/Completion/User/_mysql_utils
@@ -224,7 +224,7 @@ _mysqladmin_commands () {
 }
 
 _mysql_utils () {
-  case "${words[1]:t}" in
+  case "$service" in
     mysql)
       _mysql "$@"
     ;;
diff --git a/Completion/User/_pack b/Completion/User/_pack
index 5ec7a160c..b0172dca8 100644
--- a/Completion/User/_pack
+++ b/Completion/User/_pack
@@ -1,15 +1,15 @@
-#compdef pack pcat unpack
+#compdef pack unpack pcat=unpack
 
 local expl state line
 
-case ${words[1]:t} in
+case $service in
   pack)
     _arguments -C \
       '-f[force packing even for files which will not benefit]' \
       '-[show statistics for files]' \
       '*:file to compress:_files -g \*\~\*.z'
   ;;
-  pcat|unpack)
+  unpack)
     _description files expl 'compressed file'
     _files "$expl[@]" -g '*.z'
   ;;
diff --git a/Completion/User/_pbm b/Completion/User/_pbm
index 4b7163dcd..7980fc2b7 100644
--- a/Completion/User/_pbm
+++ b/Completion/User/_pbm
@@ -6,14 +6,14 @@
 # defaults can be overridden by simply defining completion functions
 # for those commands whose arguments you want to complete differently.
 
-local pat expl ret=1 cmd="${words[1]:t}"
+local pat expl ret=1
 
-if [[ "$cmd" = pnm* ]]; then
+if [[ "$service" = pnm* ]]; then
   pat='*.(#i)p[bgp]m'
-elif [[ "$cmd" = *top[bgpn]m ]]; then
-  pat="*.(#i)${cmd%%top[bgpn]m}"
+elif [[ "$service" = *top[bgpn]m ]]; then
+  pat="*.(#i)${service%%top[bgpn]m}"
 else
-  pat="*.(#i)${cmd[1,3]}"
+  pat="*.(#i)${service[1,3]}"
 fi
   
 if [[ $# -ne 0 || $+_in_pbm -ne 0 ]]; then
@@ -24,7 +24,7 @@ fi
 
 local _in_pbm=yes
 
-case "$cmd" in
+case "$service" in
 asciitop[gn]m)
   _arguments \
     '-d[specify divisor]:divisor:' \
diff --git a/Completion/User/_psutils b/Completion/User/_psutils
index 58cfff112..b2e713e6d 100644
--- a/Completion/User/_psutils
+++ b/Completion/User/_psutils
@@ -1,6 +1,6 @@
 #compdef epsffit extractres fixdlsrps fixfmps fixmacps fixpsditps fixpspps fixscribeps fixtpps fixwfwps fixwpps fixwwps includeres psbook psmerge psnup psresize psselect pstops getafm showchar
 
-case "${words[1]:t}" in
+case "$service" in
 epsffit)
   _arguments \
     '-v[print version]' \
diff --git a/Completion/User/_rcs b/Completion/User/_rcs
index 1e0fa315a..11cb7a59f 100644
--- a/Completion/User/_rcs
+++ b/Completion/User/_rcs
@@ -1,14 +1,14 @@
 #compdef co ci rcs
 
-local cmd="${words[1]:t}" ret=1
+local ret=1
 
-if [[ -d RCS && $cmd != ci ]]; then
+if [[ -d RCS && $service != ci ]]; then
   local rep expl
 
   rep=(RCS/*,v(:t:s/\,v//))
   (( $#rep )) && _wanted files expl 'RCS file' compadd -a rep && ret=0
 fi
 
-[[ $cmd = ci || $cmd = rcs || ret -eq 1 ]] && _files && ret=0
+[[ $service = ci || $service = rcs || ret -eq 1 ]] && _files && ret=0
 
 return ret
diff --git a/Completion/User/_rlogin b/Completion/User/_rlogin
index f84939ce9..bdfe2b44c 100644
--- a/Completion/User/_rlogin
+++ b/Completion/User/_rlogin
@@ -1,7 +1,7 @@
-#compdef rlogin rsh remsh rcp
+#compdef rlogin rsh remsh=rsh rcp
 
 _rlogin () {
-  case "${words[1]:t}" in
+  case "$service" in
   rlogin)
     _arguments -s \
       '-8[allow 8-Bit data]' \
diff --git a/Completion/User/_ssh b/Completion/User/_ssh
index c6a6898f1..7e81123ef 100644
--- a/Completion/User/_ssh
+++ b/Completion/User/_ssh
@@ -1,9 +1,12 @@
-#compdef ssh slogin scp ssh-add ssh-agent ssh-keygen
+#compdef ssh slogin=ssh scp ssh-add ssh-agent ssh-keygen
 
 _remote_files () {
   # This is extremely simple-minded; could parse "ls -F" output to do
   # colorings and LIST_TYPES and so on, but I'm just not that ambitious.
-  compadd $(ssh -a -x ${words[CURRENT]%:*} echo ${words[CURRENT]#*:}\*)
+  local expl
+
+  _wanted files expl 'remote files' \
+      compadd $(ssh -a -x ${words[CURRENT]%:*} echo ${words[CURRENT]#*:}\*)
 }
 
 _ssh () {
@@ -14,8 +17,8 @@ _ssh () {
 
   # ssh-opt is a pseudo-command used to complete ssh options for `scp -o'.
 
-  case "${words[1]:t}" in
-  ssh|slogin)
+  case "$service" in
+  ssh)
     args=(
       ':remote host name:->userhost'
       '(-):command: _command_names -e'
@@ -179,6 +182,7 @@ _ssh () {
       compset -q
       words=(ssh-opt "$words[@]" )
       (( CURRENT++ ))
+      service=ssh-opt
       _ssh
       return
     elif [[ -n "$state" ]]; then
diff --git a/Completion/User/_tiff b/Completion/User/_tiff
index f780f6bca..c5c7c3c35 100644
--- a/Completion/User/_tiff
+++ b/Completion/User/_tiff
@@ -1,9 +1,9 @@
 #compdef -P (tiff*|*2tiff|pal2rgb)
 
-local pat expl ret=1 cmd="${words[1]:t}"
+local pat expl ret=1
 
-if [[ "$cmd" = *2tiff ]]; then
-  pat="*.(#i)${cmd%%2tiff}"
+if [[ "$service" = *2tiff ]]; then
+  pat="*.(#i)${service}"
 else
   pat="*.(#i)tiff"
 fi
@@ -23,7 +23,7 @@ local _in_tiff=yes
 local curcontext="$curcontext" state line ret=1
 typeset -A opt_args
 
-case "$cmd" in
+case "$service" in
 tiff2bw)
   _arguments -C \
     '-c[specify compression scheme]:compression scheme:->compress' \
diff --git a/Completion/User/_yp b/Completion/User/_yp
index d25533e35..1ca374972 100644
--- a/Completion/User/_yp
+++ b/Completion/User/_yp
@@ -14,7 +14,7 @@ if (( ! $+_yp_cache_maps )); then
   )
 fi
 
-case "${words[1]:t}" in
+case "$service" in
 ypcat)
   _arguments -C -s "$_yp_args[@]" ':map name:->map' && ret=0
   ;;
diff --git a/Completion/X/_xutils b/Completion/X/_xutils
index bba73a3ee..89e5b3bc1 100644
--- a/Completion/X/_xutils
+++ b/Completion/X/_xutils
@@ -1,6 +1,6 @@
 #compdef xdpyinfo xwininfo xkill xfontsel xfd xev xhost xon xsetroot xwd xwud xrdb
 
-case "${words[1]:t}" in
+case "$service" in
 xdpyinfo)
   _x_arguments \
     -queryExtensions \
diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo
index adfe4914e..d3f86b203 100644
--- a/Doc/Zsh/compsys.yo
+++ b/Doc/Zsh/compsys.yo
@@ -164,6 +164,14 @@ in it will be called when completing var(names), each of which is
 either the name of a command whose arguments are to be completed or one of
 a number of special contexts in the form tt(-)var(context)tt(-) described
 below for the tt(_complete) function.
+
+Each var(name) may also be of the form `var(cmd)tt(=)var(service)'.  This
+is used by functions that offer multiple services, i.e. different
+completion behaviour for multiple commands.  Such a string
+makes the completion system call the function when completing
+arguments for the command `tt(cmd)', setting the parameter tt($service) 
+to the string `tt(service)'.  The function can then use that parameter 
+to decide what to complete.
 )
 item(tt(#compdef -p) var(pattern))(
 The file will be made autoloadable and the function defined in it will be
@@ -253,7 +261,15 @@ 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
 var(function) when completing for the contexts or commands
-whose var(names) are given:  this is like the tt(#compdef) tag.  If the
+whose var(names) are given:  this is like the tt(#compdef) tag unless
+the first word contains an equal sign.  In this case all words have to 
+be of the form `var(cmd)tt(=)var(service)' where var(service) is the
+name of a command or of a service defined by an autoloaded function
+with the tt(#compdef) tag and an argument of the form
+`var(cmd)tt(=)var(service)'.  This kind of use makes the arguments of
+the var(cmd)s be completed as those for the var(services).
+
+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
 by giving the tt(-d) option as in the second form.