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

Re: compset -q oddities

Bart Schaefer wrote on Tue, Sep 13, 2016 at 22:20:29 -0700:
> On Sep 14,  3:22am, Daniel Shahaf wrote:
> } Subject: Re: compset -q oddities
> }
> } Bart Schaefer wrote on Mon, Sep 12, 2016 at 23:28:53 -0700:
> } > You didn't start from ~~~.  You started from an empty word and typed
> } > TAB twice.  ~~~ was never on the line.  I concur that the result of
> } > the second attempt is weird, I would have expected it just to fail.
> } 
> } I would have expected the second <TAB> press to do nothing
> If the first tab had correctly produced one of ~~~ or \~\~\~ then I
> would have expected the second tab to do nothing, but given what the
> first tab incorrectly burped out, it should have failed.

Why should «f \\\~\\\~\\\~<TAB>» fail?

«ssh \git.code<TAB>» completes to "ssh git.code.sf.net" despite the
redundant backslash.

By analogy, when 'compset -q' is _not_ involved, if "~~~" is a match
then «\~\~\~<TAB>» should complete to it.  (Although it might in fact
complete to \~\~\~ because of the quotestring() issue discussed below.)

Since a \~\~\~ word matches a '~~~' completion when 'compset -q' is not
involved, therefore a \\\~\\\~\\\~ word should match a '~~~' completion
when 'compset -q' _is_ in effect.

Essentially, 'compset -q' "looks through" one level of quoting, and
whatever is happening in the «ssh \git.code<TAB>» case looks through the
second level of quoting.

Makes sense?

> Also now that I think of it, there's only one match with that compadd,
> so it should have appended a trailing space and the second tab should
> have been in an entirely new (also empty) word.

That's a bit tricky.  I think it should append an escaped space, e.g.,
«sh -c touc<TAB>» should append <h> <Backslash> <Space>.

Then there are use-cases such as «su -c script-without-arguments.<TAB>»
where one wants to run «su -c script-without-arguments.foobar» (without
further arguments), which make me think that backslash-escaped should be

Perhaps something like this, for «sh -c ech<TAB>»:

1) <h> <Backslash> <Space> is inserted.

2) If the user types an alphanumeric, the backslash-space is kept (stops
being autoremovable) and the alphanumeric is inserted as the start of
the second argument to 'echo'.

3) If the user types a space, the backslash-space changed to
space (to close the argument to the top-level -c option).

All this assumes the "compset -q"'d argument is backslash-quoted.  It'd
be slightly different if it uses single or double quotes («sh -c

> } This makes sense as far as quotestring() is concerned, but when called
> } from completion, this causes the tilde to be quoted even though
> } ${_comp_caller_options[extendedglob]} is unset.
> Indeed.  It might make sense for the internals to save the top-level
> option state on entry and implicitly re-assert it during compadd.

Not only compadd, but all the other comp* builtins too, no?

> } Perhaps making quotestring() not add that redundant first
> } backslash would workaround the issue
> The problem isn't really with the backslash being added there, it's
> somewhere later on when the prefix is being compared to the candidate
> match and one side of gets too much (? different?) quoting before the
> comparison is made.  I haven't figured out where that is, yet (and am
> not going to try too hard, honestly).

Fair enough :-)



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