Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Functions for multiple commands

Bart Schaefer wrote:

> On Oct 6,  9:18am, Sven Wischnowsky wrote:
> } 
> } I thought of several ways to restructure these completion functions for
> } multiple commands/contexts. Below are those I liked best.
> You've probably run off to play with this over the weekend and I'm too
> late to give much useful feedback, but:

No, I got a surprise visit and had almost not time at the weekend...

> ...
> } b)
> } One way to avoid that: the function that handles `#digest' only saves the
> } mappings from the autoloaded function to the sub-functions in an
> } associative array, say $_digest. Keys are the autoloaded functions, values
> } are formed like ' sub-func1 sub-func2 ...'.
> What other interesting thing do you envisage doing with the autoloaded
> function names that they need to be the keys?  Just unset the elements?

Yes, I was thinking only about the unset... (and, yes, before I was
thinking about using the names of the sub-funcs be the keys).

> ...
> Er, I don't like that `unfunction $digest' in there:  It means that the
> name of the digest can't be the name of one of the sub-functions (e.g.,
> the way _rlogin is in the patch I sent).  Let the digest function do its
> own unfunctioning, if that's appropriate.


> } I'm not exactly sure how big a problem it is that this means that sub-
> } functions are not directly callable.
> How often is any completion-system function meant to be directly called?

Well, we have these helper functions like _pids and _diff_options. But 
of course, if someone writes such a collection-in-one-file he could
always put interesting sub-functions into their own files.

> } c)
> } That could be avoided with a bit of magic, namely: the function handling
> } `#digest' creates dummy-functions for the sub-functions [...]
> } And in any case, digest-file writers would have to use:
> } 
> }   (( $+functions[_foo] )) || _foo() { ... }
> The dummy function must then unfunction *itself* before calling the
> digest function, or none of the real sub-functions will ever become
> defined!


> However:
> } so that sub-functions found earlier (in user-defined autoloaded files)
> } override those found later.
> I disagree with this (and it's use in _cvs continually annoys me, BTW,
> because it makes it difficult to load a revised version into a running
> shell).  Either those functions are all intended to be used together,
> or they are not; if so, I want them all defined, and if not, they should
> not all be contained in the same source file.
> Rather than testing $+functions[...], I'd prefer to test $_comps[...]
> in the way that was done in the _rlogin patch I sent.  If the user wants
> to override a completion function with his own autoloads, he should also
> explicitly compdef for that function.  (This of course doesn't apply to
> helper functions that are designed to be replaced, only to completion
> "callbacks" themselves.)

Hmhm. Right again.

> } 2)
> } Using only one autoloaded function, no sub-functions. The function then
> } uses a big `case', the `service' to use is given as the first argument
> Returning to Jay's original example (using _rlogin for krsh et al.), how
> is this idea qualitatively different from writing a little wrapper that
> looks like:
>     #compdef krsh krcp
>     words[1]=$words[1]:s/k//
>     _rlogin

One doesn't need to write a wrapper fuction, one only does

  compdef _rsh krsh
  compdef _rcp krcp

> } 2a)
> } Instead of `#digest', we could also use `#compdef' and allow a special
> } syntax to mean that for a certain command/context the autoloaded function
> } should be called with a `service'-argument.
> Aside: Using new compdef syntax instead of #digest would work with idea #1.

Of course.

> Let me ramble a little on this particular idea.  (As if I haven't already
> been.)  Instead of an _digest assoc, we'd have an _services assoc.  Then
> we'd change calls to the function in $_comps[$words[1]] to also pass as
> an argument $_services[$words[1]].  The #compdef line could look like:
>     #compdef -s rlogin=rlogin rsh=rsh remsh=rsh rcp=rcp
> 	The LHS of the = is the key into _comps and _services, the RHS
> 	is the value for that key in _services
> or
>     #compdef -S rlogin rsh remsh rcp
> 	Shorthand for rlogin=rlogin rsh=rsh remsh=remsh rcp=rcp
> So the result (in the first case) would be that _comps[remsh]=_rlogin
> and _services[remsh]=rsh, and so on.
> The nice thing about this is that we don't need any special magic when
> the function is called.  _normal always passes $_services[$words[1]]
> when it exists.  Also, the meaning of the service is entirely up to the
> called function; the completion system isn't forced to interpret it as
> a function name.
> I'm leaning heavily towards this approach, at the moment.

Hmhm, agreed. Actually, I was mostly concerned with getting tarred and
feathered when suggesting yet another level of indirection, which this 
is, even though that extra level isn't used in most functions.

> ...
> For example, suppose we choose (2a).  Then _rlogin could look something
> like:
>     #compdef -S rlogin rcp rsh remsh 
>     _rsh() {
> 	# guts of rsh service ...
>     }
>     _rcp() { ... }
>     _rsh() { ... }
>     case $1 in
>     remsh) 1=rsh ;&
>     rsh|rcp)
> 	_comps[$words[1]]=_$1
> 	unset _services[$words[1]]  # this is not even strictly necessary
> 	_$1 ;;
>     *)
>     	# guts of rlogin service ...
> 	;;
>     esac
> Thus turning (2a) into (1b).  I'm not sure what the ramifications of this
> sort of thing would be for efficiency of .zwc file loading.

Defining functions is cheap when using mapped .zwc files. Still, one
could change the above so that _rlogin re-defines itself with a
function containing only the `case...'. That would make it even
faster (and then we probably don't even need to modify $_comps).
We could even add a utility function (_dispatch or some such) that
implements the `case...' in a generic way.

So, is anyone against adding support for such `services'? Is that name 


Sven Wischnowsky                         wischnow@xxxxxxxxxxxxxxxxxxxxxxx

Messages sorted by: Reverse Date, Date, Thread, Author