zsh-workers
 help / color / mirror / code / Atom feed
* Re: multiple-commands-functions
@ 2000-10-11 14:56 Sven Wischnowsky
  0 siblings, 0 replies; 4+ messages in thread
From: Sven Wischnowsky @ 2000-10-11 14:56 UTC (permalink / raw)
  To: zsh-workers


Bart Schaefer wrote:

> On Oct 11,  9:32am, Sven Wischnowsky wrote:
> } 
> } Then Bart and I more-or-less suggested to use those `services' as an
> } abstraction so that functions could use `#compdef rsh remsh=rsh...'.
> } The service name would then be given as an argument to the function
> } and it could decide what to do with it.
> } 
> } But that has an ugly side-effect: some of the functions already use
> } the arguments, for options.
> 
> Hrm.  That's easily fixable, though.  E.g. in _pbm, you'd just have to add
> an extra argument as $1 when making the recursive call, to identify it as
> "the recursive call service".

And then one would have to remember that the utility functions don't
need that, but the multi-functions-used-as-utilities do.

> ...
>  
> } That made me think about ways to simplify it, or to report the service 
> } somewhere else, in a (completion-system-)global parameter. From there
> } it was only a small step to the patch below. It allows to define
> } `completion aliases' (there it is again, `aliases' -- well, we could
> } change that name, of course). For example, in an autoloaded function,
> } `#compdef rsh remsh=rsh' defines the alias `remsh=rsh'. The code
> } calling completion functions checks if $words[1] is equal to `remsh'
> } and if it is, it will call the completion function for `rsh', but
> } before that, it sets $words[1] to `rsh'. I.e. the function only has to 
> } check for $words[1] = rsh. Put the other way, `rsh' is the `service'.
> 
> Hmm.  What happens if the completion is attempted like:
> 
> zsh% /usr/local/bin/krsh <TAB>
> 
> ??  It doesn't look as though that will work properly.

I only remembered that after I sent it (but have put it into my list
as a if-..-then). It could be solved by changing how _normal looks up
these aliases.

> Are there any other cases where the format of $words[1] could mess up a 
> simple aliasing scheme?  The advantage of the previous proposals was
> that they changed the call to the completion function, not the way it
> was looked up, so there wasn't any chance for this kind of confusion.

Hm, ... I was mostly wondering if changing $words[1] could affect
other places that is used.

> If we do go with this sort of aliasing, one other thing I'd suggest is
> that it be possible to combine this with -p so that the left-hand-side
> could be a pattern, e.g.
> 
> 	compadd -p -A '*r(em|)sh=rsh'
> 
> but perhaps that's not useful enough to be worth the effort.

Dunno, easy to implement, though.

> } The only thing we would have to worry about is functions that call the 
> } command we are completing for. Since this is needed less often than
> } finding the `service', it would probably make sense to put the
> } original command name into a (completion-system-)global parameter and
> } use that everywhere we need to call the command.
> 
> In spite of the "needed less often" argument, I'd still recommend putting
> the service in a different parameter and leaving $words alone.  If the
> positionals won't work, then invent another parameter (local to _normal
> but "global" to the called functions) to store the service.  Most of the
> time there'll be a one-to-one mapping between functions and services and
> neither the service parameter nor $words[1] will be looked at.

Yes, that's the other way I was thinking about, too...

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


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

* Re: multiple-commands-functions
@ 2000-10-12  9:12 Sven Wischnowsky
  0 siblings, 0 replies; 4+ messages in thread
From: Sven Wischnowsky @ 2000-10-12  9:12 UTC (permalink / raw)
  To: zsh-workers


I think Bart will like this one better. And I probably do, too.

What I was really only after was to avoid that argument-thing we
discussed and to make live for the users easier, so that they don't
have to care about which function provides a known service.

So this patch uses the completion-system-global parameter $service to
report the service to use to the completion functions. These functions 
should then almost always use that instead of $words[1]. Definition of 
services is still done with `#compdef foo bar=foo'. But there is an
extra bit of cleverness in compdef. If the first argument is of the
form `cmd=service', i.e. it does not name a function, this really
defines what I called completion aliases in my last attempt (I haven't
called them like that this time). This works by making compdef find
out which function implements the service and making that function
(with that service) be used when completing for command `cmd'. Since
in most cases `services' will really only be commands, one can do:

  compdef krsh=rsh ...

to say that arguments for krsh should be completed as for rsh. One
doesn't need to know that it's _rlogin that implements the service
`rsh'. But of course:

  compdef _rlogin krsh=rsh

works, too.

I hope everyone agrees that this shortcut is interesting to have.


Most of the patch changes completion functions to use $service instead 
of $words[1]. Before committing this we'll probably have to go through 
it once more to see if there are places where external commands are
invoked that should use $service instead of $words[1] (probably
testing if there is a function/builtin/command named $service).

And before I forget, I'll put it down here: that compadd in
_remote_files() in _ssh should use _wanted.

Bye
 Sven

diff -u -r ../oz/Completion/Bsd/_bsd_pkg ./Completion/Bsd/_bsd_pkg
--- ../oz/Completion/Bsd/_bsd_pkg	Wed Oct 11 16:23:18 2000
+++ ./Completion/Bsd/_bsd_pkg	Wed Oct 11 21:54:41 2000
@@ -13,7 +13,7 @@
 }
 
 _bsd_pkg() {
-  case "${words[1]:t}" in
+  case "$service" in
   pkg_add)
     _arguments -s \
         '-v[be verbose]' \
diff -u -r ../oz/Completion/Bsd/_kld ./Completion/Bsd/_kld
--- ../oz/Completion/Bsd/_kld	Wed Oct 11 16:23:18 2000
+++ ./Completion/Bsd/_kld	Wed Oct 11 21:56:48 2000
@@ -21,7 +21,7 @@
 }
 
 _kld() {
-  case "${words[1]:t}" in
+  case "$service" in
   kldload)
     _arguments -s \
         '-v[be verbose]' \
diff -u -r ../oz/Completion/Core/_compalso ./Completion/Core/_compalso
--- ../oz/Completion/Core/_compalso	Wed Oct 11 16:23:14 2000
+++ ./Completion/Core/_compalso	Wed Oct 11 21:47:04 2000
@@ -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 -u -r ../oz/Completion/Core/_complete ./Completion/Core/_complete
--- ../oz/Completion/Core/_complete	Wed Oct 11 16:23:14 2000
+++ ./Completion/Core/_complete	Wed Oct 11 21:42:14 2000
@@ -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 @@
 
 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 @@
   ccarray[3]="$cname"
 
   comp="$_comps[$cname]"
+  service="${_services[$cname]:-$cname}"
 
   # If not, we use default completion, if any.
 
@@ -133,7 +135,8 @@
     fi
     comp="$_comps[-default-]"
   fi
-  [[ -z "$comp" ]] || "$comp" && ret=0
+  [[ -z "$comp" ]] ||
+      service="${_services[-default-]:--default-}" && "$comp" && ret=0
 fi
 
 _compskip=
diff -u -r ../oz/Completion/Core/_normal ./Completion/Core/_normal
--- ../oz/Completion/Core/_normal	Wed Oct 11 16:23:15 2000
+++ ./Completion/Core/_normal	Wed Oct 11 21:39:56 2000
@@ -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 @@
 # 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 @@
     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 @@
 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 @@
 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 @@
     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 @@
 fi
 
 [[ "$name" = -default- && -n "$comp" && "$_compskip" != (all|*default*) ]] &&
-  "$comp" && ret=0
+  service="${_services[-default-]:--default-}" && "$comp" && ret=0
 
 _compskip=''
 
diff -u -r ../oz/Completion/Core/compdump ./Completion/Core/compdump
--- ../oz/Completion/Core/compdump	Wed Oct 11 16:23:16 2000
+++ ./Completion/Core/compdump	Wed Oct 11 22:16:30 2000
@@ -35,12 +35,19 @@
 
 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
     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
 
diff -u -r ../oz/Completion/Core/compinit ./Completion/Core/compinit
--- ../oz/Completion/Core/compinit	Wed Oct 11 16:23:16 2000
+++ ./Completion/Core/compinit	Wed Oct 11 22:48:24 2000
@@ -100,12 +100,13 @@
   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.
@@ -181,12 +182,12 @@
 #   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
   
@@ -216,11 +217,38 @@
   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.
 
@@ -290,15 +318,19 @@
     *)
       # 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
@@ -314,7 +346,7 @@
       # Oops, cannot do that yet.
 
       echo "$0: cannot restore key bindings"
-      return 1
+      return 1v
       ;;
     *)
       unset "_comps[$^@]"
diff -u -r ../oz/Completion/Debian/_apt ./Completion/Debian/_apt
--- ../oz/Completion/Debian/_apt	Wed Oct 11 16:23:19 2000
+++ ./Completion/Debian/_apt	Wed Oct 11 21:57:25 2000
@@ -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 -u -r ../oz/Completion/Debian/_bug ./Completion/Debian/_bug
--- ../oz/Completion/Debian/_bug	Wed Oct 11 16:23:19 2000
+++ ./Completion/Debian/_bug	Wed Oct 11 21:57:41 2000
@@ -8,7 +8,7 @@
            '-v[version]' \
            '*:package:_deb_packages installed')
 
-case "${words[1]:t}" in
+case "$service" in
 bug)
 _arguments '-c[exclude configs from report]' \
            '-f[argument is a file, not a package]' \
diff -u -r ../oz/Completion/Debian/_dpkg ./Completion/Debian/_dpkg
--- ../oz/Completion/Debian/_dpkg	Wed Oct 11 16:23:19 2000
+++ ./Completion/Debian/_dpkg	Wed Oct 11 21:57:58 2000
@@ -86,7 +86,7 @@
 #  _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 -u -r ../oz/Completion/User/_bzip2 ./Completion/User/_bzip2
--- ../oz/Completion/User/_bzip2	Wed Oct 11 16:23:21 2000
+++ ./Completion/User/_bzip2	Wed Oct 11 21:58:50 2000
@@ -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 -u -r ../oz/Completion/User/_chown ./Completion/User/_chown
--- ../oz/Completion/User/_chown	Wed Oct 11 16:23:21 2000
+++ ./Completion/User/_chown	Wed Oct 11 21:59:10 2000
@@ -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 -u -r ../oz/Completion/User/_compress ./Completion/User/_compress
--- ../oz/Completion/User/_compress	Wed Oct 11 16:23:21 2000
+++ ./Completion/User/_compress	Wed Oct 11 21:59:38 2000
@@ -17,7 +17,7 @@
   '(-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 -u -r ../oz/Completion/User/_dvi ./Completion/User/_dvi
--- ../oz/Completion/User/_dvi	Wed Oct 11 16:23:21 2000
+++ ./Completion/User/_dvi	Wed Oct 11 22:00:21 2000
@@ -9,7 +9,7 @@
   ':output DVI file:_files -g \*.\(dvi\|DVI\)'
 )
 
-case "${words[1]:t}" in
+case "$service" in
 dvips)
   _arguments -s \
     '-a[make three passes]' \
diff -u -r ../oz/Completion/User/_gzip ./Completion/User/_gzip
--- ../oz/Completion/User/_gzip	Wed Oct 11 16:23:22 2000
+++ ./Completion/User/_gzip	Wed Oct 11 22:01:07 2000
@@ -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 -u -r ../oz/Completion/User/_imagemagick ./Completion/User/_imagemagick
--- ../oz/Completion/User/_imagemagick	Wed Oct 11 16:23:20 2000
+++ ./Completion/User/_imagemagick	Wed Oct 11 21:56:14 2000
@@ -18,7 +18,7 @@
   return
 fi
 
-case "${words[1]:t}" in
+case "$service" in
 display)
   _arguments -M 'm:{a-z}={A-Z}' \
       '*-backdrop[use full screen]' \
diff -u -r ../oz/Completion/User/_ispell ./Completion/User/_ispell
--- ../oz/Completion/User/_ispell	Wed Oct 11 16:23:22 2000
+++ ./Completion/User/_ispell	Wed Oct 11 22:01:32 2000
@@ -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 -u -r ../oz/Completion/User/_java ./Completion/User/_java
--- ../oz/Completion/User/_java	Wed Oct 11 16:23:24 2000
+++ ./Completion/User/_java	Wed Oct 11 22:02:29 2000
@@ -6,7 +6,7 @@
 
 jdb_args=()
 
-case "${words[1]:t}" in
+case "$service" in
 javac)
   _arguments \
     '-g-[generate debugging information]:debug:->debug' \
diff -u -r ../oz/Completion/User/_lp ./Completion/User/_lp
--- ../oz/Completion/User/_lp	Wed Oct 11 16:23:22 2000
+++ ./Completion/User/_lp	Wed Oct 11 22:03:49 2000
@@ -5,7 +5,7 @@
 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 -u -r ../oz/Completion/User/_mount ./Completion/User/_mount
--- ../oz/Completion/User/_mount	Wed Oct 11 16:23:22 2000
+++ ./Completion/User/_mount	Wed Oct 11 22:05:32 2000
@@ -368,7 +368,7 @@
   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 -u -r ../oz/Completion/User/_mysql_utils ./Completion/User/_mysql_utils
--- ../oz/Completion/User/_mysql_utils	Wed Oct 11 16:23:23 2000
+++ ./Completion/User/_mysql_utils	Wed Oct 11 22:06:23 2000
@@ -224,7 +224,7 @@
 }
 
 _mysql_utils () {
-  case "${words[1]:t}" in
+  case "$service" in
     mysql)
       _mysql "$@"
     ;;
diff -u -r ../oz/Completion/User/_pack ./Completion/User/_pack
--- ../oz/Completion/User/_pack	Wed Oct 11 16:23:23 2000
+++ ./Completion/User/_pack	Wed Oct 11 22:06:55 2000
@@ -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 -u -r ../oz/Completion/User/_pbm ./Completion/User/_pbm
--- ../oz/Completion/User/_pbm	Wed Oct 11 16:23:23 2000
+++ ./Completion/User/_pbm	Wed Oct 11 21:55:27 2000
@@ -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 @@
 
 local _in_pbm=yes
 
-case "$cmd" in
+case "$service" in
 asciitop[gn]m)
   _arguments \
     '-d[specify divisor]:divisor:' \
diff -u -r ../oz/Completion/User/_psutils ./Completion/User/_psutils
--- ../oz/Completion/User/_psutils	Wed Oct 11 16:23:24 2000
+++ ./Completion/User/_psutils	Wed Oct 11 22:11:29 2000
@@ -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 -u -r ../oz/Completion/User/_rcs ./Completion/User/_rcs
--- ../oz/Completion/User/_rcs	Wed Oct 11 16:23:24 2000
+++ ./Completion/User/_rcs	Wed Oct 11 22:12:11 2000
@@ -1,10 +1,10 @@
 #compdef co ci rcs
 
-local nm=$compstate[nmatches] cmd="${words[1]:t}"
+local nm=$compstate[nmatches]
 
-[[ $cmd = ci || $cmd = rcs ]] && _files
+[[ $service = ci || $service = rcs ]] && _files
 
-if [[ $compstate[nmatches] -eq nm && -d RCS && $cmd != ci ]]; then
+if [[ $compstate[nmatches] -eq nm && -d RCS && $service != ci ]]; then
   local rep expl
 
   rep=(RCS/$PREFIX*$SUFFIX,v(:t:s/\,v//))
diff -u -r ../oz/Completion/User/_rlogin ./Completion/User/_rlogin
--- ../oz/Completion/User/_rlogin	Wed Oct 11 16:23:24 2000
+++ ./Completion/User/_rlogin	Wed Oct 11 21:52:09 2000
@@ -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 -u -r ../oz/Completion/User/_ssh ./Completion/User/_ssh
--- ../oz/Completion/User/_ssh	Wed Oct 11 16:23:24 2000
+++ ./Completion/User/_ssh	Wed Oct 11 21:51:32 2000
@@ -1,4 +1,4 @@
-#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
@@ -14,8 +14,8 @@
 
   # 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 +179,7 @@
       compset -q
       words=(ssh-opt "$words[@]" )
       (( CURRENT++ ))
+      service=ssh-opt
       _ssh
       return
     elif [[ -n "$state" ]]; then
diff -u -r ../oz/Completion/User/_tiff ./Completion/User/_tiff
--- ../oz/Completion/User/_tiff	Wed Oct 11 16:23:25 2000
+++ ./Completion/User/_tiff	Wed Oct 11 21:55:48 2000
@@ -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 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 -u -r ../oz/Completion/User/_yp ./Completion/User/_yp
--- ../oz/Completion/User/_yp	Wed Oct 11 16:23:26 2000
+++ ./Completion/User/_yp	Wed Oct 11 22:12:33 2000
@@ -14,7 +14,7 @@
   )
 fi
 
-case "${words[1]:t}" in
+case "$service" in
 ypcat)
   _arguments -C -s "$_yp_args[@]" ':map name:->map' && ret=0
   ;;
diff -u -r ../oz/Completion/X/_xutils ./Completion/X/_xutils
--- ../oz/Completion/X/_xutils	Wed Oct 11 16:23:29 2000
+++ ./Completion/X/_xutils	Wed Oct 11 22:12:49 2000
@@ -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 -u -r ../oz/Doc/Zsh/compsys.yo ./Doc/Zsh/compsys.yo
--- ../oz/Doc/Zsh/compsys.yo	Wed Oct 11 16:23:42 2000
+++ ./Doc/Zsh/compsys.yo	Wed Oct 11 23:04:27 2000
@@ -164,6 +164,14 @@
 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 @@
 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.

--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


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

* Re: multiple-commands-functions
  2000-10-11  7:32 multiple-commands-functions Sven Wischnowsky
@ 2000-10-11 14:46 ` Bart Schaefer
  0 siblings, 0 replies; 4+ messages in thread
From: Bart Schaefer @ 2000-10-11 14:46 UTC (permalink / raw)
  To: Sven Wischnowsky, zsh-workers

On Oct 11,  9:32am, Sven Wischnowsky wrote:
} 
} Then Bart and I more-or-less suggested to use those `services' as an
} abstraction so that functions could use `#compdef rsh remsh=rsh...'.
} The service name would then be given as an argument to the function
} and it could decide what to do with it.
} 
} But that has an ugly side-effect: some of the functions already use
} the arguments, for options.

Hrm.  That's easily fixable, though.  E.g. in _pbm, you'd just have to add
an extra argument as $1 when making the recursive call, to identify it as
"the recursive call service".

But it would be just as easy to put the service name in a non-positional.

} Another problem of some of the solutions suggested is that they 
} modify $_comps which may make re-loading impossible.

That was only necessary to implement one of the suggestions in terms of
the other one, but nevertheless ...
 
} That made me think about ways to simplify it, or to report the service 
} somewhere else, in a (completion-system-)global parameter. From there
} it was only a small step to the patch below. It allows to define
} `completion aliases' (there it is again, `aliases' -- well, we could
} change that name, of course). For example, in an autoloaded function,
} `#compdef rsh remsh=rsh' defines the alias `remsh=rsh'. The code
} calling completion functions checks if $words[1] is equal to `remsh'
} and if it is, it will call the completion function for `rsh', but
} before that, it sets $words[1] to `rsh'. I.e. the function only has to 
} check for $words[1] = rsh. Put the other way, `rsh' is the `service'.

Hmm.  What happens if the completion is attempted like:

zsh% /usr/local/bin/krsh <TAB>

??  It doesn't look as though that will work properly.

Are there any other cases where the format of $words[1] could mess up a 
simple aliasing scheme?  The advantage of the previous proposals was
that they changed the call to the completion function, not the way it
was looked up, so there wasn't any chance for this kind of confusion.

If we do go with this sort of aliasing, one other thing I'd suggest is
that it be possible to combine this with -p so that the left-hand-side
could be a pattern, e.g.

	compadd -p -A '*r(em|)sh=rsh'

but perhaps that's not useful enough to be worth the effort.

} The only thing we would have to worry about is functions that call the 
} command we are completing for. Since this is needed less often than
} finding the `service', it would probably make sense to put the
} original command name into a (completion-system-)global parameter and
} use that everywhere we need to call the command.

In spite of the "needed less often" argument, I'd still recommend putting
the service in a different parameter and leaving $words alone.  If the
positionals won't work, then invent another parameter (local to _normal
but "global" to the called functions) to store the service.  Most of the
time there'll be a one-to-one mapping between functions and services and
neither the service parameter nor $words[1] will be looked at.

-- 
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] 4+ messages in thread

* multiple-commands-functions
@ 2000-10-11  7:32 Sven Wischnowsky
  2000-10-11 14:46 ` multiple-commands-functions Bart Schaefer
  0 siblings, 1 reply; 4+ messages in thread
From: Sven Wischnowsky @ 2000-10-11  7:32 UTC (permalink / raw)
  To: zsh-workers


[I've prepared some patches yesterday, I'm not sure about any of them, 
so I'll just post them for further discussion, without committing them.]


We were discussing ways to improve functions like _rlogin. The
original request could be reduced to something like: is there a way to 
make it easier to use one of the `services' of such functions?

Then Bart and I more-or-less suggested to use those `services' as an
abstraction so that functions could use `#compdef rsh remsh=rsh...'.
The service name would then be given as an argument to the function
and it could decide what to do with it.

But that has an ugly side-effect: some of the functions already use
the arguments, for options. For example, _pbm can be used as a
top-level function and also calls itself to complete only appropriate
files. Another problem of some of the solutions suggested is that they 
modify $_comps which may make re-loading impossible.

That made me think about ways to simplify it, or to report the service 
somewhere else, in a (completion-system-)global parameter. From there
it was only a small step to the patch below. It allows to define
`completion aliases' (there it is again, `aliases' -- well, we could
change that name, of course). For example, in an autoloaded function,
`#compdef rsh remsh=rsh' defines the alias `remsh=rsh'. The code
calling completion functions checks if $words[1] is equal to `remsh'
and if it is, it will call the completion function for `rsh', but
before that, it sets $words[1] to `rsh'. I.e. the function only has to 
check for $words[1] = rsh. Put the other way, `rsh' is the `service'.

It is also possible to define completion aliases directly with
compdef, with the new option -A: `compdef -A krsh=rsh ...' says that
completion for `krsh' should be done as for `rsh'. I like this,
because it is independent of the function (and sub-function or
case-branch) used for `rsh' -- users don't have to worry about that.

The only thing we would have to worry about is functions that call the 
command we are completing for. Since this is needed less often than
finding the `service', it would probably make sense to put the
original command name into a (completion-system-)global parameter and
use that everywhere we need to call the command. I haven't implemented 
that yet, though.

Bye
 Sven

diff -u -r ../oz/Completion/Core/_compalso ./Completion/Core/_compalso
--- ../oz/Completion/Core/_compalso	Tue Oct 10 19:36:47 2000
+++ ./Completion/Core/_compalso	Tue Oct 10 20:09:55 2000
@@ -10,6 +10,7 @@
 local i tmp ret=1
 
 for i; do
+  (( $+_compaliases[$1] )) && 1="$_compaliases[$1]"
   tmp="$_comps[$1]"
   [[ -z "$tmp" ]] || "$tmp" && ret=0
 done
diff -u -r ../oz/Completion/Core/_normal ./Completion/Core/_normal
--- ../oz/Completion/Core/_normal	Tue Oct 10 19:36:47 2000
+++ ./Completion/Core/_normal	Tue Oct 10 20:06:50 2000
@@ -15,6 +15,11 @@
 # a path and the last path name component).
 
 command="$words[1]"
+if (( $+_compaliases[$command] )); then
+  command="$_compaliases[$command]"
+  words[1]="$command"
+fi
+
 if [[ CURRENT -eq 1 ]]; then
   curcontext="${curcontext%:*:*}:-command-:"
 
diff -u -r ../oz/Completion/Core/compdump ./Completion/Core/compdump
--- ../oz/Completion/Core/compdump	Tue Oct 10 19:36:47 2000
+++ ./Completion/Core/compdump	Tue Oct 10 20:21:45 2000
@@ -35,12 +35,18 @@
 
 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.  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
     print -r - "${(q)_d_f}" "${(q)_comps[$_d_f]}"
+done  >> $_d_file
+print ")" >> $_d_file
+
+print "_compaliases=(" >> $_d_file
+for _d_f in ${(ok)_compaliases}; do
+    print -r - "${(q)_d_f}" "${(q)_compaliases[$_d_f]}"
 done  >> $_d_file
 print ")" >> $_d_file
 
diff -u -r ../oz/Completion/Core/compinit ./Completion/Core/compinit
--- ../oz/Completion/Core/compinit	Tue Oct 10 19:36:47 2000
+++ ./Completion/Core/compinit	Tue Oct 10 20:43:37 2000
@@ -100,12 +100,13 @@
   esac
 done
 
-# The associative array containing the definitions for the commands.
+# The associative arrays containing the definitions for the commands and
+# the completion aliases.
 # 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 _compaliases _patcomps _postpatcomps _compautos
 
 # The associative array use to report information about the last
 # cmpletion to the outside.
@@ -181,16 +182,16 @@
 #   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 ali
 
   # Get the options.
 
-  if [[ $#* -eq 0 ]]; then
-    echo "compdef needs parameters"
+  if (( ! $# )); then
+    echo "#0: I need arguments"
     return 1
   fi
   
-  while getopts "anpPkKd" opt; do
+  while getopts "anpPkKdA" opt; do
     case "$opt" in
     a)    autol=yes;;
     n)    new=yes;;
@@ -211,16 +212,44 @@
 	  fi
 	  ;;
     d) delete=yes;;
+    A) ali=yes;;
     esac
   done
   shift OPTIND-1
 
-  if [[ $#* -eq 0 ]]; then
-    echo "compdef needs parameters"
+  if (( ! $# )); then
+    echo "$0: I need arguments"
     return 1
   fi
-  
-  if [[ -z "$delete" ]]; then
+
+  if [[ -n "$ali" ]]; then
+    if [[ -n "$autol$type" ]]; then
+      echo "$0: -A can't be combined with other options"
+      return 1
+    fi
+    if [[ -z "$delete" ]]; then
+      ali=0
+      for i; do
+        if [[ "$i" != *\=* ]]; then
+	  echo "$0: invalid argument: \`$i'"
+	  ali=1
+        else
+          new="${i#*\=}"
+	  if (( $+_compaliases[$new] )); then
+	    _compaliases[${i%%\=*}]="$_compaliases[$new]"
+	    _comps[${i%%\=*}]="$_comps[$_compaliases[$new]]"
+	  else
+	    _compaliases[${i%%\=*}]="$new"
+	    _comps[${i%%\=*}]="$_comps[$new]"
+	  fi
+        fi
+      done
+      return ali
+    else
+      unset _compaliases\[${^*}\]
+      return
+    fi
+  elif [[ -z "$delete" ]]; then
     # Adding definitions, first get the name of the function name
     # and probably do autoloading.
 
@@ -290,15 +319,15 @@
     *)
       # 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
+	  _compaliases[${i%%\=*}]="${i#*\=}"
+	  _comps[${i%%\=*}]="$_comps[${i#*\=}]"
+	else
+          [[ -z "$new" || "${+_comps[$i]}" -eq 0 ]] && _comps[$i]="$func"
+	fi
+      done
       ;;
     esac
   else
diff -u -r ../oz/Completion/User/_rlogin ./Completion/User/_rlogin
--- ../oz/Completion/User/_rlogin	Tue Oct 10 19:36:48 2000
+++ ./Completion/User/_rlogin	Tue Oct 10 20:38:28 2000
@@ -1,4 +1,4 @@
-#compdef rlogin rsh remsh rcp
+#compdef rlogin rsh remsh=rsh rcp
 
 _rlogin () {
   case "${words[1]:t}" in
@@ -9,7 +9,7 @@
       '-l[specify login user name]:login as:_rlogin_users' \
       ':remote host name:_rlogin_hosts'
     ;;
-  rsh|remsh)
+  rsh)
     local context state line ret=1
     typeset -A opt_args
 
diff -u -r ../oz/Completion/User/_ssh ./Completion/User/_ssh
--- ../oz/Completion/User/_ssh	Tue Oct 10 19:36:48 2000
+++ ./Completion/User/_ssh	Tue Oct 10 20:20:28 2000
@@ -1,4 +1,4 @@
-#compdef ssh slogin scp ssh-add ssh-agent ssh-keygen
+#compdef ssh slogin=ssh scp ssh-add ssh-agent ssh-keygen
 
 _remote_files () {
   local expl files
@@ -18,7 +18,7 @@
   # ssh-opt is a pseudo-command used to complete ssh options for `scp -o'.
 
   case "${words[1]:t}" in
-  ssh|slogin)
+  ssh)
     args=(
       ':remote host name:->userhost'
       '(-):command: _command_names -e'
diff -u -r ../oz/Doc/Zsh/compsys.yo ./Doc/Zsh/compsys.yo
--- ../oz/Doc/Zsh/compsys.yo	Tue Oct 10 19:36:41 2000
+++ ./Doc/Zsh/compsys.yo	Tue Oct 10 21:11:20 2000
@@ -164,6 +164,10 @@
 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(name1)tt(=)var(name2)'.
+This makes the function be used to complete arguments for var(name1)
+and ensures that the function treats it as if completing for var(name2).
 )
 item(tt(#compdef -p) var(pattern))(
 The file will be made autoloadable and the function defined in it will be
@@ -250,7 +254,8 @@
 xitem(tt(compdef -p) [ tt(-a) ] var(function pattern))
 xitem(tt(compdef -P) [ tt(-a) ] var(function pattern))
 xitem(tt(compdef -k) [ tt(-an) ] var(function style key-sequences...))
-item(tt(compdef -K) [ tt(-an) ] var(function name style key-sequences ...))(
+xitem(tt(compdef -K) [ tt(-an) ] var(function name style key-sequences...))
+item(tt(compdef -A) var(aliases...))(
 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
@@ -285,6 +290,11 @@
 for tt(-k) and the first must be a unique widget name beginning with an
 underscore.
 
+The form with tt(-A) defines the completion var(aliases), each of
+which has to be of the form `var(command1)tt(=)var(command2)'.  Such an 
+alias makes the arguments of var(command1) be completed in the same
+way as those for var(command2).
+
 In each of the forms supporting it the tt(-a) option makes the
 var(function) autoloadable (exactly equivalent to
 tt(autoload -U )var(function)).
@@ -301,7 +311,15 @@
 example(compdef _pids foo)
 
 using the tt(_pids) function from the distribution to generate the
-process identifiers.  Not also the tt(_use_lo) function described
+process identifiers.  Completion aliases are intended to express that
+completion for a command has to be done in the same way as for another 
+command, e.g.:
+
+example(compdef -A foo=rsh)
+
+says that completion for tt(foo) has to be done as for tt(rsh).
+
+Note also the tt(_use_lo) function described
 below, which can be used to complete options for commands that
 understand the `tt(-)tt(-help)' option.
 

--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


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

end of thread, other threads:[~2000-10-12  9:13 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-10-11 14:56 multiple-commands-functions Sven Wischnowsky
  -- strict thread matches above, loose matches on Subject: below --
2000-10-12  9:12 multiple-commands-functions Sven Wischnowsky
2000-10-11  7:32 multiple-commands-functions Sven Wischnowsky
2000-10-11 14:46 ` multiple-commands-functions Bart Schaefer

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).