zsh-workers
 help / color / mirror / code / Atom feed
From: Bart Schaefer <schaefer@brasslantern.com>
To: zsh-workers@zsh.org
Subject: Re: Inconsistent history expansion of characters adjacent to histchar
Date: Mon, 07 Oct 2013 19:56:12 -0700	[thread overview]
Message-ID: <131007195612.ZM1029@torch.brasslantern.com> (raw)
In-Reply-To: <CANWLQWuM4CBXOmLkVpFN4PO3cLj72qQYbbbGZKxoAqdBwz05kw@mail.gmail.com>

On Mon, Oct 7, 2013 at 8:55 AM, Hauke Petersen <hkptrsn@gmail.com> wrote:

> It does not immediately make sense to me why a single `!' would be
> interpreted as a double `!!' before a `;' and tried, unsuccessfully,
> to find an explanation.

Bluntly, it's because that history documentation is lying to you. The
correct bit is the first sentence here:

>     Event Designators
>     !   Start a history expansion, except when followed by a blank, new-line,
>     `=' or `('.  If followed immediately by a word designator, this forms a
>     history reference with no event designator.

Semicolon is not one of the things that prevents a "!" from starting
a history expansion, so everything from there forward behaves like a
history reference with no event.

This bug appears to have been around for longer than we've been keeping
source control copies of the shell. For some reason ';' is called out
in histsubchar() along with things that begin (or end) event or word
designators. The same is true of any kind of quotes, e.g.:

    print !`echo foo`
    print !!`echo foo`

are equivalent; "!}" also has the same problem though it usually causes
a parse error.

I think the intent is that those characters only end a history reference
after at least one other character [not in that set] has been read, but
that's not the way the loop is written, and it doesn't account for other
characters that can't be word designators, as seen here:

> there is no previous command starting with ';'.  Like otherwise
> similar `&':
>
>     % print !& print foo
>     zsh: event not found: &

Same happens with "!|" and probably a few other obscure variations.

In short, the history parser has always been very ad-hoc and deviates
from its own spec in several ways.

Here's a patch that fixes the unintended expansion, but it doesn't fix
the inconsistent behavior with !& !| et al.  There should probably be
more method to this madness instead of multiple series of individual
character comparisons.

The (c == '"') condition is probably unnecessary because '!"' has been
handled much earlier, but the loop above this also tests all three
quotes, so ...  

diff --git a/Src/hist.c b/Src/hist.c
index d1af30a..bd650e8 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -521,6 +521,12 @@ histsubchar(int c)
 		}
 		c = ingetc();
 	    }
+	    if (ptr == buf &&
+		(c == '}' ||  c == ';' || c == '\'' || c == '"' || c == '`')) {
+	      /* Neither event nor word designator, no expansion */
+	      safeinungetc(c);
+	      return bangchar;
+	    }
 	    *ptr = 0;
 	    if (!*buf) {
 		if (c != '%') {


  reply	other threads:[~2013-10-08  2:56 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-10-07 15:55 Hauke Petersen
2013-10-08  2:56 ` Bart Schaefer [this message]
2013-10-08 14:31   ` Bart Schaefer
2013-10-08 14:44     ` Peter Stephenson
2013-10-08 15:43       ` Peter Stephenson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=131007195612.ZM1029@torch.brasslantern.com \
    --to=schaefer@brasslantern.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).