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

Re: completion grouping (yes, again)



Bart Schaefer wrote:

> } First, the completion function side:
> } 
> } `_tags' has been simplified. [...]
> } I also added a bit of parameter magic, so that functions using `_tags' 
> } don't need to define the `tags' parameter locally.
> 
> This is pretty cute, but I wonder if it's going to work correctly with
> (say) KSH_ARRAYS set?  There aren't very many "emulate -L zsh" calls in
> the Completion tree at the moment ...

KSH_ARRAYS is unset in _main_complete. And I hope there are no calls
to `emulate -L zsh' at all -- I hate it ever since it once reset
NUMERIC_GLOB_SORT for me when I was testing the patch that made that
option be used in completion listings. There was a call to `emulate'
in the function call chain (from i-c-w, I think) and that made it look 
as if it didn't work -- I had to search quite a while until I found
out what was happening.
Also, `emulate -L zsh' resets some other options which are tested or
used in the completion code, e.g.: extended_glob, magic_equal_subst,
and pushd_minus.

> } The I added the functions `_requested' which gets names of tags and
> } returns zero if at least one of these tags was requested.
> } 
> } So, to use tags one can now simply do something like:
> } 
> }   local ret=1
> } 
> }   _tags job process   # say which types of matches we can add
> } 
> }   while _tags; do     # get the next set of tags to try
> } 
> }     _requested job     && _jobs && ret=0
> }     _requested process && _pids && ret=0
> } 
> }     (( ret )) || return 0
> }   done
> } 
> }   return 1
> 
> This looks reasonable; I could only wish for a more direct correlation
> between the tag name and the completion function that's called to get
> the corresponding matches.  However, I can't decide whether to rename
> the tags or the functions -- and I can imagine there might be cases in
> which the same tag might map to more than one function.

I'm already almost decided to turn the names into their plural forms
-- makes it better readable in the config stuff. Otherwise, I think we 
shouldn't worry too much if function names are a bit weird. I'm hoping 
for a big renaming (and moving around, e.g. the Linux-dirs may be
superfluous) shortly before the next official release (well, there
isn't *that* much to do anymore).

> } But there is also the new function `_alternative' (please someone who
> } actually can speak English tell me a better name)
> 
> The only better words that occur to me are ones like "switch" and "case"
> that are used in other languages for select-among-alternates behavior.
> It'd probably be bad to actually use one of those because of confusion
> with similar shell reserved words.  I suppose you could use "_alternate"
> just for a little brevity, or maybe something like "_inspect".

Yes, I was thinking about `_alternate', too. Just wasn't sure if that
doesn't sound weird for antive-English speakers.

> } which basically
> } implements such a loop. Its arguments are of the form
> } `<tag>:<descr>:<action>', which should look familiar. The tags are
> } given to `_tags' and then a loop executes the actions of the requested 
> } tags.
> 
> Looks like there's an obvious optimization here:  Replicate the loop
> that's in _requested and put the body of _alternative inside it.  Am I
> missing something?

Yes. `_alternative' consecutively gets new sets of tags that should
be used and tries to generate matches for all tags in the set
currently used until one of these sets generates matches matching
what's on the line. `_requested' loops over its arguments to see if one
of the tags thus given is requested. Actually, I almost made
`_requested' accept only one tag as argument, because I wasn't sure if 
we want to test if all tags given should be requested or one of
them. Currently, `_requested' is used only with one argument.

> } This also means that there is a small difference to `_arguments' 
> } and friends: the `->state' style for actions is not supported (because 
> } `_alternative' may have to execute more than one action).
> 
> I'm afraid I don't immediately understand the ramifications of this.

`_arguments' and `_values' always only need to execute one action (or
none at all). `_alternative' on the other hand may execute more than
one action (until one generates matches). So it can't really do its
job if an action for one requested tag would have to be executed in
the calling function. If that doesn't generate any matches,
`_alternative' would have to try other tags but if the action is
executed by the calling function it obviously can't do that because it 
isn't running any more.

> } With this functions like `_wait' only have to do:
> } 
> }   _alternative 'job:: _jobs' 'process:: _pids'
> } 
> } (Empty descriptions because they are not used -- the actions start
> } with spaces and we use the descriptions added by `_jobs' and `_pids'.)
> 
> Why do the actions start with space?

An action starting with a space is executed as-is. Without the space
functions like `_alternative' and `_arguments' stuff some `compadd'
options (the ones they get from `_description') after the first
word. With an empty description that would give us no descriptions
above the matches in the lists. And we don't need the description
`_alternative' would build here because `_jobs' and `_pids' build
their own descriptions which are appropriate in this context.

> } Then I added some more support for styles. [...]
> } 
> } What I was thinking about is this: if we integrate the config stuff
> } into the tags mechanism I see two ways we can go:
> } 
> } 1) Add `pseudo'-tags, named after the config keys they replace
> } 2) Add new tags [...] which also group config keys.
> } 
> } I quite like the grouping done by 2), but for some config keys this
> } looks like overkill.
> 
> It seems to me that (2) is a superset of (1).  That is, you could use a
> special case (the empty style name?) to represent (1) within (2), and
> thus get the best of both worlds without the "overkill".

Hadn't thought of making the style-name empty. Yes, maybe...

> ...
> 
> I think the right answer is to use the contexts always, combined with
> the change described above.
> 
> If the default behavior were to treat a command-name without a slash as
> affecting all contexts, then the existing completion functions could be
> left as is without significantly changing their behavior, could they not?
> And if it were appropriate to specialize them more, contexts could be
> selectively added.

Yep, that's what I was thinking about. Good.

> } [W]e could change `_arguments' so that [it builds] context names
> } if users don't define them. For `_arguments' this could, for example,
> } use names like `-o' and `arg-1' (for options getting multiple
> } arguments this would have to be `-foo-1'). Or maybe we use `arg/1',
> } making it look like a (sub-)sub-context. But, of course, the problem
> } with this is that in many cases the names would be ugly (`infile' is
> } certainly more user-friendly than `arg/1').
> 
> Before I address that, answer me this:
> 
> How does the system know `infile' means "the first non-option argument"?
> Or that `outfile' means "the word after `-o ' or `--output='"?  What's
> the step I haven't seen that maps these user-friendly context names to
> the corresponding (and potentially different for each command) "shape" of
> the command line?  I don't believe we can simply infer it.

Right. Maybe I forgot to say that for more descriptive names we would
have to change `_arguments' (and `_values') so that the descriptions
for command arguments also contain the context names. E.g.:

  _arguments \
    '-o<outfile>:output file:_files -g \*.\(\#i\)ps' \
    '<infile>:DVI file:_files -g \*.\(\#i\)dvi'

Here, the `<name>'s are the context names.

The need to change almost every function that uses `_arguments' (and
every argument to that function) is what made me suggest we try to
build the context names automatically. Also people would probably
often be too lazy to add such contexts even if they would make sense
(the same problem as with the options option-description).

> Unless that mapping can be established in a simple/understandable way, I
> think we're just as well off using mechanically-constructed context names
> like those suggested above.

Yep.

> } As I said above, I have implemented two suggestions. The functions
> } are `conf1' and `conf2' in `compinit'.
> 
> This is great stuff, Sven.  I don't have any real opinion at this point
> about which is better.  I would suggest a couple of changes:
> 
> ... [ conf1 ]
> 
> I'd suggest
> 
>   <context> = 'when' pattern |
>               'else'
> 
> I might even go so far as to suggest 'if' rather than 'when' -- you
> obviously aren't avoiding use of reserved words.

I was trying to make that readable: `in the context ...'. But I prefer 
conf2 anyway...

> Incidentally, can there be multiple 'in' (suggested 'when') clauses, or
> only one?

Any number of them. Slightly modeled after `case'.

> }   <prio>    = '=' 'never' |
> }               '=' number [ <style> ... ]
> }   <style>   = 'with' style
> } 
> } where `style' may be `foo=bar' (i.e. a style with a value).
> 
> } The `is'-form would be used for replacing config keys as in:
> } 
> }   conf1 completer is '_complete:_correct'
> 
> OK ...
> 
> }   conf2 <def> ...
> }   <def>      = 'for' pat 'do' <spec> |
> }                'else' 'do' <spec> |
> } 	       'always' do <spec>
>                         ^^
>                        'do' ?
> 
> Once again I'd suggest 'when' rather than 'for'.  There's a looping
> connotation to 'for' and I don't think any loop is implied here.

Here I was thinking about `for the command ...'. But it already
irritated me to (it's weird how we automatically think about a loop if 
we see the word `for' -- remember the story with the dogs and the
bells ;-).

> Also, I suggest 'use' or 'try' or maybe even 'expect' rather than 'do';
> see below.

I've been hacking some more yesterday (but that isn't in a presentable 
state yet and I don't think I'll have enough time today, maybe I'll
send it tomorrow) where I changed it to `add' (I had also thought
about `use', but not `try').

I also added the syntax `never add job' to replace `always do no job'
(I like the example with the `job' tag ;-). I'm also playing with the
`no ...' clauses (currently it's `for cmd add a or b but not c or d').

And I made `conf2' without arguments list the current settings. But
see below...

> ...
> 
> Hence my suggestion that some other word than 'do' be used here.

We will.


In another message:

> One other thing I forgot to mention:  I'd like it better if these functions
> read from stdin/file rather than taking everything as command-line args.
> Here-strings could be used for simple cases.  I wanted to do this with
> _arg_compile, but didn't get around to it.
> 
> ...
> 
> It's just that I don't like having to write what looks like semi-structured
> text with backslashes at the end of every line.

Yes, I'd like that, too. I don't have a solution yet, though.

One problem is that due to the way tags are stored internally it can
really mess things up if `conf2' is called more than once when using
the same command/tag pairs (or at least one such pair is used in
multiple invocations). Maybe we should disallow calling it mutliple
times. And maybe we don't really need to make it able to list the
settings. But if we make it read from stdin, we could easily save the
verbatim input and make it dump that to stdout as a `listing'.

Since `conf2' is also a bit slow, I currently want to keep it in shell 
code only until we agreed upon a sensible syntax and then move (the
biggest part of) it into C-code. Together with some stuff for the
other tag functions (they'll certainly be called often enough to
justify this).

Also, when reading from stdin we could use `||' and `&&' instead of
`or' and `and', but I'm not sure if I like it.

Btw, I've also been thinking about using `then' (in the chronological
sense) instead of `or' because that's what it does.

Hm...

  compconf <<THERE

  if 'kill' try
    jobs or
    processes
  else try
    jobs but 
    not processes
  always try
    arguments and values with description or
    options with description and with hidden-prefix
  always try
    glob or
    paths or
    files

  THERE

Bye
 Sven


--
Sven Wischnowsky                         wischnow@xxxxxxxxxxxxxxxxxxxxxxx



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