* while alias @ 2022-11-08 1:56 Pier Paolo Grassi 2022-11-08 6:13 ` Bart Schaefer 0 siblings, 1 reply; 4+ messages in thread From: Pier Paolo Grassi @ 2022-11-08 1:56 UTC (permalink / raw) To: Zsh-Users List [-- Attachment #1: Type: text/plain, Size: 504 bytes --] Hello, I have the following alias defined: WI='while {read -r it; ! [[ $? -ne 0 && -z $it ]]}' that works fine except in command substitution: a=$( echo 1 | WI { echo $it } ) zsh: parse error near `}' zsh: parse error in command substitution if I substitute the alias with the aliased code all works fine: a=$( echo 1 | while {read -r it; ! [[ $? -ne 0 && -z $it ]]} { echo $it } ); echo $a 1 alias are normally correctly substituted inside command substitution, what can it be? Pier Paolo Grassi [-- Attachment #2: Type: text/html, Size: 928 bytes --] ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: while alias 2022-11-08 1:56 while alias Pier Paolo Grassi @ 2022-11-08 6:13 ` Bart Schaefer 2022-11-08 12:39 ` Peter Stephenson 0 siblings, 1 reply; 4+ messages in thread From: Bart Schaefer @ 2022-11-08 6:13 UTC (permalink / raw) To: Pier Paolo Grassi; +Cc: Zsh-Users List On Mon, Nov 7, 2022 at 5:57 PM Pier Paolo Grassi <pierpaolog@gmail.com> wrote: > > Hello, I have the following alias defined: > > WI='while {read -r it; ! [[ $? -ne 0 && -z $it ]]}' > > that works fine except in command substitution: Put spaces around your braces. alias WI='while { read -r it; ! [[ $? -ne 0 && -z $it ]] }' Aliases in command substitutions are parsed by a complicated dance requiring that they be expanded and then backtracked over and then re-parsed. The character count for the "{" and/or "}" tokens is off by one for the backtracking step when they don't have surrounding whitespace. (Leaving it to PWS, who choreographed this dance number, to fix the footwork if possible.) ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: while alias 2022-11-08 6:13 ` Bart Schaefer @ 2022-11-08 12:39 ` Peter Stephenson 2022-11-09 11:11 ` Pier Paolo Grassi 0 siblings, 1 reply; 4+ messages in thread From: Peter Stephenson @ 2022-11-08 12:39 UTC (permalink / raw) To: Zsh-Users List (This is really for zsh-workers but in case anyone wants to see the result...) > On 08/11/2022 06:13 Bart Schaefer <schaefer@brasslantern.com> wrote: > On Mon, Nov 7, 2022 at 5:57 PM Pier Paolo Grassi <pierpaolog@gmail.com> wrote: > > > > Hello, I have the following alias defined: > > > > WI='while {read -r it; ! [[ $? -ne 0 && -z $it ]]}' > > > > that works fine except in command substitution: > > Put spaces around your braces. > > alias WI='while { read -r it; ! [[ $? -ne 0 && -z $it ]] }' > > Aliases in command substitutions are parsed by a complicated dance > requiring that they be expanded and then backtracked over and then > re-parsed. The character count for the "{" and/or "}" tokens is off > by one for the backtracking step when they don't have surrounding > whitespace. (Leaving it to PWS, who choreographed this dance number, > to fix the footwork if possible.) Yes, it's that full combination of a command substitution, an alias, and expansion text with a lexically significant closing brace with no preceding space that's doing it, so it's very specific. This will come as a shock, but there's a hack in the lexical analyser! (Counselling will be available by the usual channels.) It seems that the lexer really doesn't like closing braces without a space before them and sometimes we have to fix up the text after the event. It seems the extra special code for command substitution needs a slightly modified version of the hack. The new test in D08 checks the case Pier Paolo hit; it turns out the existing test just above checks the case where we do after all need to unget an extra closing brace, i.e. lex_add_raw ends up 1 in the code added by the first hunk. I am not going to attempt to get my mind round this any further and will be going out for some fresh air. pws diff --git a/Src/lex.c b/Src/lex.c index ece02659e..e2f8bcfb1 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -1429,10 +1429,18 @@ gettokstr(int c, int sub) peek == STRING && lexbuf.ptr[-1] == '}' && lexbuf.ptr[-2] != Bnull) { /* hack to get {foo} command syntax work */ + /* + * Alias expansion when parsing command substitution means that + * the case for raw lexical analysis may not be the same. + * (Just go with it, OK?) + */ + int lar = lex_add_raw; + lex_add_raw = lexbuf_raw.len > 0 && lexbuf_raw.ptr[-1] == '}'; lexbuf.ptr--; lexbuf.len--; lexstop = 0; hungetc('}'); + lex_add_raw = lar; } *lexbuf.ptr = '\0'; DPUTS(cmdsp != ocmdsp, "BUG: gettok: cmdstack changed."); diff --git a/Test/D08cmdsubst.ztst b/Test/D08cmdsubst.ztst index 04bf698aa..8b6bcb469 100644 --- a/Test/D08cmdsubst.ztst +++ b/Test/D08cmdsubst.ztst @@ -177,3 +177,11 @@ 0:Alias expansion needed in parsing substitutions >hi >bye + +# This should silently print a blank line; the original problem was +# a parse error as the last character of the unexpanded alias +# was erased, symptom: "command not found: W" + alias WI='while {false}' + eval 'echo $(WI blah)' +0:Aliases with braces in command substitution can cause havoc +> ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: while alias 2022-11-08 12:39 ` Peter Stephenson @ 2022-11-09 11:11 ` Pier Paolo Grassi 0 siblings, 0 replies; 4+ messages in thread From: Pier Paolo Grassi @ 2022-11-09 11:11 UTC (permalink / raw) To: Peter Stephenson; +Cc: Zsh-Users List [-- Attachment #1: Type: text/plain, Size: 3500 bytes --] thanks the space before the brace indeed solved it. good to know! Pier Paolo Grassi Il giorno mar 8 nov 2022 alle ore 13:40 Peter Stephenson < p.w.stephenson@ntlworld.com> ha scritto: > (This is really for zsh-workers but in case anyone wants to see the > result...) > > > On 08/11/2022 06:13 Bart Schaefer <schaefer@brasslantern.com> wrote: > > On Mon, Nov 7, 2022 at 5:57 PM Pier Paolo Grassi <pierpaolog@gmail.com> > wrote: > > > > > > Hello, I have the following alias defined: > > > > > > WI='while {read -r it; ! [[ $? -ne 0 && -z $it ]]}' > > > > > > that works fine except in command substitution: > > > > Put spaces around your braces. > > > > alias WI='while { read -r it; ! [[ $? -ne 0 && -z $it ]] }' > > > > Aliases in command substitutions are parsed by a complicated dance > > requiring that they be expanded and then backtracked over and then > > re-parsed. The character count for the "{" and/or "}" tokens is off > > by one for the backtracking step when they don't have surrounding > > whitespace. (Leaving it to PWS, who choreographed this dance number, > > to fix the footwork if possible.) > > Yes, it's that full combination of a command substitution, an > alias, and expansion text with a lexically significant closing brace > with no preceding space that's doing it, so it's very specific. > > This will come as a shock, but there's a hack in the lexical analyser! > (Counselling will be available by the usual channels.) It seems > that the lexer really doesn't like closing braces without a space > before them and sometimes we have to fix up the text after the event. > > It seems the extra special code for command substitution needs a > slightly modified version of the hack. The new test in D08 checks > the case Pier Paolo hit; it turns out the existing test just above > checks the case where we do after all need to unget an extra closing > brace, i.e. lex_add_raw ends up 1 in the code added by the first hunk. > > I am not going to attempt to get my mind round this any further > and will be going out for some fresh air. > > pws > > diff --git a/Src/lex.c b/Src/lex.c > index ece02659e..e2f8bcfb1 100644 > --- a/Src/lex.c > +++ b/Src/lex.c > @@ -1429,10 +1429,18 @@ gettokstr(int c, int sub) > peek == STRING && lexbuf.ptr[-1] == '}' && > lexbuf.ptr[-2] != Bnull) { > /* hack to get {foo} command syntax work */ > + /* > + * Alias expansion when parsing command substitution means that > + * the case for raw lexical analysis may not be the same. > + * (Just go with it, OK?) > + */ > + int lar = lex_add_raw; > + lex_add_raw = lexbuf_raw.len > 0 && lexbuf_raw.ptr[-1] == '}'; > lexbuf.ptr--; > lexbuf.len--; > lexstop = 0; > hungetc('}'); > + lex_add_raw = lar; > } > *lexbuf.ptr = '\0'; > DPUTS(cmdsp != ocmdsp, "BUG: gettok: cmdstack changed."); > diff --git a/Test/D08cmdsubst.ztst b/Test/D08cmdsubst.ztst > index 04bf698aa..8b6bcb469 100644 > --- a/Test/D08cmdsubst.ztst > +++ b/Test/D08cmdsubst.ztst > @@ -177,3 +177,11 @@ > 0:Alias expansion needed in parsing substitutions > >hi > >bye > + > +# This should silently print a blank line; the original problem was > +# a parse error as the last character of the unexpanded alias > +# was erased, symptom: "command not found: W" > + alias WI='while {false}' > + eval 'echo $(WI blah)' > +0:Aliases with braces in command substitution can cause havoc > +> > > [-- Attachment #2: Type: text/html, Size: 4716 bytes --] ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2022-11-09 11:13 UTC | newest] Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-11-08 1:56 while alias Pier Paolo Grassi 2022-11-08 6:13 ` Bart Schaefer 2022-11-08 12:39 ` Peter Stephenson 2022-11-09 11:11 ` Pier Paolo Grassi
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).