From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 13571 invoked from network); 9 Oct 2000 11:24:37 -0000 Received: from sunsite.auc.dk (130.225.51.30) by ns1.primenet.com.au with SMTP; 9 Oct 2000 11:24:37 -0000 Received: (qmail 8360 invoked by alias); 9 Oct 2000 11:23:48 -0000 Mailing-List: contact zsh-workers-help@sunsite.auc.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 12928 Received: (qmail 8353 invoked from network); 9 Oct 2000 11:23:47 -0000 Date: Mon, 9 Oct 2000 13:23:45 +0200 (MET DST) Message-Id: <200010091123.NAA18212@beta.informatik.hu-berlin.de> From: Sven Wischnowsky To: zsh-workers@sunsite.auc.dk In-reply-to: "Bart Schaefer"'s message of Sun, 8 Oct 2000 17:34:47 +0000 Subject: 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. Yes. > } 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! Right. > 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 acceptable? Bye Sven -- Sven Wischnowsky wischnow@informatik.hu-berlin.de