Subject: Re: bug: suffix alias and tabcompletion
From: Peter Stephenson <[email-masked]>
To: Zsh hackers list <[email-masked]>
Date: Wed, 22 Jun 2016 12:53:24 +0100
List-Id: Zsh Workers List <zsh-workers.zsh.org>

On Wed, 22 Jun 2016 10:01:59 +0100
Peter Stephenson <[email-masked]> wrote:
> On Tue, 21 Jun 2016 13:18:21 -0700
> Bart Schaefer <[email-masked]> wrote:
> > On Tue, Jun 21, 2016 at 12:39 PM, Michael Gebhard
> > <[email-masked]> wrote:
> > >
> > > running the following commands and trying to complete the last line
> > > by pressing tab produces a zsh taking up 100% cpu.
> > >
> > > zsh -f
> > > touch foo.bar
> > > alias -s bar='echo a &'
> > 
> > It's not (just) completion; attempting to run the command "foo.bar"
> > produces a similar infinite loop.

You get it with ";", too, which is easier to test.

> I suppose we'd need some way of marking something as having had a suffix
> alias expanded before it, and then we'd need to reset that flag if we
> encountered something not at the start of that input that was in command
> position so we could expand a new suffix alias.

After enough failed attempts, the right way presented itself.  We can
make this near enough to the normal alias case by attaching the alias to
be expanded (where we record the fact it's in use) to the argument, not
to the alias expansion itself.  The input stack that's recording this
doesn't care, and this makes it look pretty much exactly like the normal
case.

Obviously, this now gives "command not found" on the re-executed suffix
argument, which is the only sensible alternative to recursion.

pws

diff --git a/Src/lex.c b/Src/lex.c
index e36a01e..5ad3474 100644
--- a/Src/lex.c
+++ b/Src/lex.c
@@ -1842,10 +1842,11 @@ checkalias(void)
 	if ((suf = strrchr(zshlextext, '.')) && suf[1] &&
 	    suf > zshlextext && suf[-1] != Meta &&
 	    (an = (Alias)sufaliastab->getnode(sufaliastab, suf+1)) &&
-	    !an->inuse && incmdpos) {
-	    inpush(dupstring(zshlextext), INP_ALIAS, NULL);
+	    !an->inuse && incmdpos &&
+	    !(inbufflags & INP_ALSUFF)) {
+	    inpush(dupstring(zshlextext), INP_ALIAS, an);
 	    inpush(" ", INP_ALIAS, NULL);
-	    inpush(an->text, INP_ALIAS, an);
+	    inpush(an->text, INP_ALIAS, NULL);
 	    lexstop = 0;
 	    return 1;
 	}
diff --git a/Test/A02alias.ztst b/Test/A02alias.ztst
index 49e4756..1e09cd3 100644
--- a/Test/A02alias.ztst
+++ b/Test/A02alias.ztst
@@ -104,3 +104,9 @@
 >0
 ?(eval):2: invalid alias 'x=y' encountered while printing aliases
 # Currently, 'alias -L' returns 0 in this case.  Perhaps it should return 1.
+
+  alias -s mysuff='print -r "You said it.";'
+  eval 'thingummy.mysuff'
+127:No endless loop with suffix alias in command position
+>You said it.
+?(eval):1: command not found: thingummy.mysuff