From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28442 invoked by alias); 20 Jan 2016 07:47:59 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 37700 Received: (qmail 23332 invoked from network); 20 Jan 2016 07:47:57 -0000 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.0 Date: Wed, 20 Jan 2016 07:47:53 +0000 From: Daniel Shahaf To: Peter Stephenson Cc: zsh-workers@zsh.org Subject: Re: bufferwords() lexes a subshell in a shortloop repeat as a string Message-ID: <20160120074753.GA13624@tarsus.local2> References: <20160115062648.GA14019@tarsus.local2> <20160115094117.5fcde75c@pwslap01u.europe.root.pri> <20160118022558.GC3979@tarsus.local2> <20160118104548.7db26f60@pwslap01u.europe.root.pri> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20160118104548.7db26f60@pwslap01u.europe.root.pri> User-Agent: Mutt/1.5.23 (2014-03-12) Peter Stephenson wrote on Mon, Jan 18, 2016 at 10:45:48 +0000: > There is some special casing in bufferwords() for loops, though, so > maybe the case you want isn't far off working. bufferwords() received the «(x)» as a STRING token, so I looked further down, into gettok(). The attached patch seems to do the trick [see the added tests]. However, to paraphrase Knuth, I only tested this code, not proved it correct. I'd appreciate a review. Thanks for the (snipped) clarifications. Cheers, Daniel diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index bcea980..b64c76e 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -479,6 +479,8 @@ '(( 3 + 1 == 8 / 2 ))' 'for (( i = 1 ; i < 10 ; i++ ))' '((0.25542 * 60) - 15)*60' + 'repeat 3 (x)' + 'repeat 3 (echo foo; echo bar)' ) for string in $strings; do array=(${(z)string}) @@ -514,6 +516,20 @@ >8:15: >9:): >10:*60: +>1:repeat: +>2:3: +>3:(: +>4:x: +>5:): +>1:repeat: +>2:3: +>3:(: +>4:echo: +>5:foo: +>6:;: +>7:echo: +>8:bar: +>9:): line=$'A line with # someone\'s comment\nanother line # (1 more\nanother one' diff --git a/Src/lex.c b/Src/lex.c index 0f260d0..2505dd6 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -267,9 +267,13 @@ zshlex(void) { if (tok == LEXERR) return; - do + do { + if (inrepeat_) + ++inrepeat_; + if (inrepeat_ == 3 && isset(SHORTLOOPS)) + incmdpos = 1; tok = gettok(); - while (tok != ENDINPUT && exalias()); + } while (tok != ENDINPUT && exalias()); nocorrect &= 1; if (tok == NEWLIN || tok == ENDINPUT) { while (hdocs) { @@ -1870,6 +1874,7 @@ exalias(void) zshlextext[0] == '}' && !zshlextext[1])) && (rw = (Reswd) reswdtab->getnode(reswdtab, zshlextext))) { tok = rw->token; + inrepeat_ = (tok == REPEAT); if (tok == DINBRACK) incond = 1; } else if (incond && !strcmp(zshlextext, "]]")) { diff --git a/Src/parse.c b/Src/parse.c index 4829e3a..49c1ac0 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -63,6 +63,12 @@ int isnewlin; /**/ int infor; +/* != 0 if we are after a repeat keyword; if it's nonzero it's a 1-based index + * of the current token from the last-seen command position */ + +/**/ +int inrepeat_; + /* != 0 if parsing arguments of typeset etc. */ /**/ @@ -271,6 +277,7 @@ parse_context_save(struct parse_stack *ps, int toplevel) ps->incasepat = incasepat; ps->isnewlin = isnewlin; ps->infor = infor; + ps->inrepeat_ = inrepeat_; ps->intypeset = intypeset; ps->hdocs = hdocs; @@ -305,6 +312,7 @@ parse_context_restore(const struct parse_stack *ps, int toplevel) incasepat = ps->incasepat; isnewlin = ps->isnewlin; infor = ps->infor; + inrepeat_ = ps->inrepeat_; intypeset = ps->intypeset; hdocs = ps->hdocs; @@ -447,6 +455,7 @@ init_parse_status(void) * using the lexical analyser for strings as well as here. */ incasepat = incond = inredir = infor = intypeset = 0; + inrepeat_ = 0; incmdpos = 1; } @@ -1482,6 +1491,7 @@ par_while(int *cmplx) static void par_repeat(int *cmplx) { + /* ### what to do about inrepeat_ here? */ int oecused = ecused, p; p = ecadd(0); diff --git a/Src/zsh.h b/Src/zsh.h index 0302d68..a398242 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -2913,6 +2913,7 @@ struct parse_stack { int incasepat; int isnewlin; int infor; + int inrepeat_; int intypeset; int eclen, ecused, ecnpats; diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c index 86840bd..a3af234 100644 --- a/Src/Zle/zle_vi.c +++ b/Src/Zle/zle_vi.c @@ -65,7 +65,7 @@ char *vichgbuf; int viinsbegin; static struct modifier lastmod; -static int inrepeat, vichgrepeat; +static int inrepeat, vichgrepeat; /* that's why the trailing underscore */ /** * im: >= 0: is an insertmode