From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 23448 invoked from network); 17 Sep 2000 23:04:56 -0000 Received: from sunsite.auc.dk (130.225.51.30) by ns1.primenet.com.au with SMTP; 17 Sep 2000 23:04:56 -0000 Received: (qmail 6111 invoked by alias); 17 Sep 2000 23:03:10 -0000 Mailing-List: contact zsh-users-help@sunsite.auc.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 3432 Received: (qmail 6104 invoked from network); 17 Sep 2000 23:03:09 -0000 Date: Sun, 17 Sep 2000 19:03:05 -0400 Message-Id: <200009172303.TAA07756@soup.ql.org> X-Authentication-Warning: soup.ql.org: ejb set sender to ejb@ql.org using -f From: "E. Jay Berkenbilt" To: schaefer@candle.brasslantern.com CC: zsh-users@sunsite.auc.dk In-reply-to: <1000917184320.ZM19505@candle.brasslantern.com> (schaefer@candle.brasslantern.com) Subject: Re: completion with globbing, take 2 References: <200009171750.NAA05647@soup.ql.org> <1000917184320.ZM19505@candle.brasslantern.com> Mime-Version: 1.0 (generated by tm-edit 7.106) Content-Type: text/plain; charset=US-ASCII 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