Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: completion with globbing, take 2
- X-seq: zsh-users 3432
- From: "E. Jay Berkenbilt" <ejb@xxxxxx>
- To: schaefer@xxxxxxxxxxxxxxxxxxxxxxx
- Subject: Re: completion with globbing, take 2
- Date: Sun, 17 Sep 2000 19:03:05 -0400
- Cc: zsh-users@xxxxxxxxxxxxxx
- In-reply-to: <1000917184320.ZM19505@xxxxxxxxxxxxxxxxxxxxxxx> (schaefer@xxxxxxxxxxxxxxxxxxxxxxx)
- Mailing-list: contact zsh-users-help@xxxxxxxxxxxxxx; run by ezmlm
- References: <200009171750.NAA05647@xxxxxxxxxxx> <1000917184320.ZM19505@xxxxxxxxxxxxxxxxxxxxxxx>
Okay, with everyone's help, my problem is solved, but the solution
brings up lots of questions.
> } Several days ago, I wanted to know how I could get zsh to respond to
> }
> } something *TAB
> }
> } by replacing the * with the list everything that the completion system
> } would return instead of everything * would match in the current
> } directory. I was told to do this:
> }
> } zstyle ':completion:*' completer _oldlist _complete _match
> } bindkey "^I" complete-word
>
> More precisely, you were told that Andrej does that.
>
> Andrej probably wasn't expecting you to use it verbatim, though, because
> he didn't show you what his settings for the matcher-list style are.
Right.
> You
> didn't say whether you have any settings for matcher-list; if you don't,
> the _match completer won't do anything.
Sorry -- my original message failed to say that I was starting with
zsh -f with only the completion system loaded and no additional
customization. This is why I was much more explicit in my second
message.
Also, after reading the code, I don't believe it is true that _match
won't do anything without matcher-list set -- see analysis and
questions below.
> } I want behavior more like what expand-or-complete does except that I
> } want only what the completion system would return to be substituted.
>
> That's what the _expand completer is for. I believe you want:
>
> zstyle ':completion:*' completer _oldlist _expand _complete _match
> zstyle ':completion::expand:*' completions true
This almost worked, and it gave me enough additional information to
get the rest of the way there. I now have the following:
zstyle ':completion:*' completer _oldlist _complete _expand _match
zstyle ':completion::expand:*' completions true
bindkey "^I" complete-word
This seems to do exactly what I'm looking for. We'll see whether I've
broken anything.
Removing any of _complete, _expand, or _match or changing the order in
which they appear breaks things.
Now I've analyzed the code and think I understand why this works, but
I'm not 100% certain. Interestingly, ^X? doesn't work when I do
rmdir *^X?
but that's okay -- I just did setopt xtrace and then
rmdir *TAB
Again, I have just 1, 2, 3, a, b, and c in the currently directory
where 1, 2, and 3 are directories and a, b, and c are files.
Looking at the trace and the code, here's what I think is happening:
_main_complete is called. It looks up my completers (_oldlist,
_complete, _expand, and _match) and calls then in order. _oldlist
returns nothing, _complete returns nothing (since no files start with
'*'). Now it starts getting interesting. _expand is called. Since I
have set the completions style for expand to true, it sets
compstate[insert]=all which gives me the behavior I'm looking for with
respect to the replacement. However, since the current context is not
expand-word:*, it does not call _complete and thus just returns 1.
Finally, _match is called. I don't follow exactly what's going on at
the top of _match, but it doesn't matter. Since I don't have
match-original set, _match sets compstate[pattern_match]='*' and calls
_complete again. This time, since compstate[pattern_match] is set,
_complete actually does find matches.
So the right thing happens, but the path to the desired end seems
quite convoluted and counterintuitive to me. I would never have
figured this out without the significant hints without having to spend
a lot of time grokking this code.
So there end up being two important commands here. Without this one:
zstyle ':completion::expand:*' completions true
the call to _expand doesn't set compstate[insert]=all. Now if I look
at this:
zstyle ':completion:*' completer _oldlist _complete _expand _match
If we remove _match, then _complete never gets called again with
compstate[pattern_match]='*', so it is essential. If _expand appears
before _complete, then
rmdir TAB
by itself inserts all the matches.
So, in summary, it seems that the only thing I'm using expand for is
to get compstate[insert]=all. The only thing I'm using _match for is
to get _complete to be called with with compstate[pattern_match]='*'.
I can't do this with setopt glob_complete because if I do, then the
first call to _complete will generate matches when it is called before
the call to _expand, so I'll get the menu behavior instead of what I
wanted. If I put _expand before _complete with these settings, I
always get all matches substituted (as if I had typed the *), which
renders the completion system pretty useless.
So, is my analysis correct? Am I getting behavior that was intended
here, or have I just stumbled upon a way to do this? I feel like I'm
getting the desired behavior through a series of coincidences and that
this could change or break pretty easily in the future....
Thanks for all the help.
Jay
Messages sorted by:
Reverse Date,
Date,
Thread,
Author