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

Re: Bug#519535: history expansion: modifier completion missing

On Sun, 15 Mar 2009 06:22:53 +0000
Clint Adams <schizo@xxxxxxxxxx> wrote:
> On Fri, Mar 13, 2009 at 11:55:55AM +0100, martin f krafft wrote:
> > I tried to show off zsh to a sceptic today and had to find out the
> > hard way that it does not (yet) provide completion for history
> > expansion modifiers, e.g.
> > 
> >   echo !$:<TAB>

I thought this was going to be harder than it turned out to be; as you can
see it's really quite simple, particularly since I already wrote modifer
completion and it would appear had the foresight to make it handle the
history case.

It's in _normal which is where we handle normal command arguments.  I think
this is both the first and last place where get to massage command line
arguments generically---we don't just want this in default completion since
history expansion, if active, trumps everything else.

It probably needs to go in _value for assignments; is right at the top the
appropriate place?  Or should it actually go higher, in _complete itself,
outside the "if" that decides whether it's _normal or otherwise?  I don't
think so, because that screws up vared.  Hmmm... I think that's true of
putting it in _value, which _in_vared uses.  Maybe leaving it discretely
alone might work well.

The rum thing is the way $PREFIX acquires quoted !'s.  I thought $PREFIX
was fairly raw, so you could handle special characters?  Obviously I'm
misremembering, because I traced the quoting to some completely general
code for all special characters.  Anyway, that has two effects:  first you
have to check $words, because that does have the raw form, and secondly you
have to update $PREFIX so that you get the raw !'s inserted into the
command line.  (But you don't usually have to do that even if you're
inserting special characters, do you?  You just need to make sure compadd
has the argument -Q, which it does here, except that's not good enough.

I think -z $compstate[quote] ensures we're not already doing something
clever inside nested quotes, which would mean the expression couldn't be a
history expansion.  I think.

So it seems to work fine (possibly depending on your options and
completers---there are other things around that will do other things to
!'s), but I'm still a bit confused.

Index: Completion/Base/Core/_normal
RCS file: /cvsroot/zsh/zsh/Completion/Base/Core/_normal,v
retrieving revision 1.4
diff -u -r1.4 _normal
--- Completion/Base/Core/_normal	13 Mar 2002 09:28:05 -0000	1.4
+++ Completion/Base/Core/_normal	16 Mar 2009 18:05:48 -0000
@@ -9,6 +9,19 @@
+# Check for a history reference to complete modifiers.
+# $PREFIX has a quoted form of the !, so we can't test that
+# (it might the start of a real argument), but words has the
+# raw McCoy.
+if [[ -o BANG_HIST && $words[CURRENT] = \!*: && -z $compstate[quote] ]]; then
+  # This looks like a real history expansion; in that case
+  # we'd better put the !'s back the way pfalstad intended.
+  PREFIX=${PREFIX//\\!/!}
+  compset -P '*:'
+  _history_modifiers h
+  return
 # Completing in command position?
 if [[ CURRENT -eq 1 ]]; then

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