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

Re: Bug in completion with curly braces?

On Sat, Nov 21, 2020 at 1:09 PM Felipe Contreras
<felipe.contreras@xxxxxxxxx> wrote:
> On Sat, Nov 21, 2020 at 9:29 AM Daniel Shahaf <d.s@xxxxxxxxxxxxxxxxxx> wrote:
> > Consequently, brace expansion is presumably attempted for the same
> > reason it s attempted when the words don't contain braces.
> But zle knows { is part of the completions

Actually, it does not.  Every TAB starts over from scratch with
figuring out how to divide the command line into complete-able
"words".  It doesn't know what is going to be supplied to compadd as
the set of matches until much later.

Consequently the line is split before the unquoted "{" on the
assumption that a brace expansion is going to follow it.

It might be easier to understand/debug this by observing the effect of
the following example:

_foo() { compadd -Q 'stash@{0}' 'stash@{1}'; compstate[list]=keep }
compdef _foo foo

Looking at that with _complete_debug, the prefix is being set to
"stash@" rather than to "stash@{", and you get repeated TABs cycling
through "stash@{{0}" and "stash@{{1}".  It's waiting for you to close
the presumed brace expansion yourself.

This is similar to the situation in Daniel's thread where "{" in
command position is assumed to be the start of a "{ subcommand }".
There's only so much completion can do to guess what a heavily
overloaded token means.

This appears to work around it:

_foo() {
  local -a stashes=( 'stash@{0}' 'stash@{1}')
  if [[ $words[CURRENT] = *@\{ ]];
  then compadd -Q -p ${words[CURRENT]%\{} ${stashes#$words[CURRENT]}
  else compadd -Q $stashes

However, that gets confused if $stashes contains e.g. 'stash@{10}' and
you're trying to complete after the digit "1", so there's more
refinement required.  Any time there's an unquoted "{" on the line
you're eventually going to run into something that wants to treat it
as a brace expansion.

I even tried forcing "ignorebraces" to be on during completion, but
the best that does (in combo with other changes to the compadd) is to
convert the word on the line to be "stash@\{" which you don't want.

I've got one other idea about this but I'll send this email and think
more about the other option.

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