From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-1.1 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from primenet.com.au (ns1.primenet.com.au [203.24.36.2]) by inbox.vuxu.org (OpenSMTPD) with ESMTP id 5d0d5194 for ; Wed, 19 Jun 2019 15:02:53 +0000 (UTC) Received: (qmail 14513 invoked by alias); 19 Jun 2019 15:02:48 -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: List-Unsubscribe: X-Seq: 44435 Received: (qmail 20297 invoked by uid 1010); 19 Jun 2019 15:02:48 -0000 X-Qmail-Scanner-Diagnostics: from mailout1.w1.samsung.com by f.primenet.com.au (envelope-from , uid 7791) with qmail-scanner-2.11 (clamdscan: 0.101.2/25482. spamassassin: 3.4.2. Clear:RC:0(210.118.77.11):SA:0(-7.0/5.0):. Processed in 2.666143 secs); 19 Jun 2019 15:02:48 -0000 X-Envelope-From: p.stephenson@samsung.com X-Qmail-Scanner-Mime-Attachments: | X-Qmail-Scanner-Zip-Files: | Received-SPF: pass (ns1.primenet.com.au: SPF record at _spf.samsung.com designates 210.118.77.11 as permitted sender) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout1.w1.samsung.com 20190619150212euoutp01e2b939067f8be0b9dfddb6c83f36c6ba~pobIRRTpG0809508095euoutp01s DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1560956532; bh=yEYu7iZ9c5nWALk6v/8yr0Qt/jIW1FrCajfMpqPC3i8=; h=Subject:From:To:Date:In-Reply-To:References:From; b=dPNJGaNjfmVFxDdp6i45Y1cRcXnV/3X3xO/zrq0M3WzWEm9nuf0rUBC/5x276CPu4 ZrRQH7Yi6Bk3d6Sv8FCfePyA8OoeqOSHN9F8kdgxz6Gd+t+Z+c3YIh3bMqQrFVXukm 9eEUg7nVhWlk/Vt//RnPPfIyXr1R6VHPeOTer+q0= X-AuditID: cbfec7f4-113ff70000001119-d5-5d0a4e73e908 Message-ID: <1560956527.23478.10.camel@samsung.com> Subject: Re: PATCH: trailing components From: Peter Stephenson To: Date: Wed, 19 Jun 2019 16:02:07 +0100 In-Reply-To: <6f974c69-9c16-4e9f-b0b6-37e40083223a@www.fastmail.com> X-Mailer: Evolution 3.18.5.2-0ubuntu3.2 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrHIsWRmVeSWpSXmKPExsWy7djP87rFflyxBqcPCFscbH7I5MDoserg B6YAxigum5TUnMyy1CJ9uwSujJe901gKjrYxVsyaOIO9gXFyfhcjJ4eEgIlE66237F2MXBxC AisYJW59/MkI4fQxSeyf+Bgq08skcfvzX3aYlil3njJBJJYzSmyc/4MFJAFWNW+rPETiDKPE 07vLWCGcC4wSSw63sHUxcnDwChhLrLofDtIgLKAusWHNXjYQm03AUGLqptmMILaIgKTEtebT YDaLgKrE728PwWxOAReJT71LWSGu0JDYcPMYE4jNKyAocXLmE7AjmAXkJZq3zmaGqHnOJnGn TQbCdpG4c/IMC4QtLPHq+Baob2Qk/u+cD/aNhEA7o8SaSa/ZIZweRolNR+8wQlRZS/TdvsgI 8gCzgKbE+l36EGFHieVHd7GChCUE+CRuvBWEuIFPYtK26cwQYV6JjjYhiGo1iR1NWxkhwjIS T9coTGBUmoXkgVlIHpiFsGoBI/MqRvHU0uLc9NRio7zUcr3ixNzi0rx0veT83E2MwFRw+t/x LzsYd/1JOsQowMGoxMN7QosrVog1say4MvcQowQHs5IIL3czZ6wQb0piZVVqUX58UWlOavEh RmkOFiVx3mqGB9FCAumJJanZqakFqUUwWSYOTqkGRqbDfAemP0kR/PHg4IfFJo9iL5zeWRRq FFgiJagiGxE66ceiDe9ecostTBCN2fbzwEWtnXfU1CdsUUjWu84gM4HjIcfpwiuPbbhq9weU MzzzYbncGFDYq3glxDmK3bxDynXZ8+P5DOc+NR4Xvfn0O+OvdadXfjwpsob3ZaXtnu3Fqflt m7s4NJVYijMSDbWYi4oTAY5C1m0BAwAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFmpikeLIzCtJLcpLzFFi42I5/e/4Xd0iP65Yg74mcYuDzQ+ZHBg9Vh38 wBTAGKVnU5RfWpKqkJFfXGKrFG1oYaRnaGmhZ2RiqWdobB5rZWSqpG9nk5Kak1mWWqRvl6CX 8bJ3GkvB0TbGilkTZ7A3ME7O72Lk5JAQMJGYcucpUxcjF4eQwFJGiWfPVjNCJGQkPl35yA5h C0v8udbFBlHUzSSxpfkjC4RzhlFi7s5WRgjnAqPEjV9TgRwODl4BY4lV98NBuoUF1CU2rNnL BmKzCRhKTN00G2yDiICkxLXm02A2i4CqxO9vD8FsTgEXiU+9S1lBbCGB5UwSrce9QWxmAU2J 1u2/oS7SkNhw8xgTiM0rIChxcuYTFogaeYnmrbOZJzAKzULSMgtJ2SwkZQsYmVcxiqSWFuem 5xYb6RUn5haX5qXrJefnbmIEhv+2Yz+37GDsehd8iFGAg1GJh/eEFlesEGtiWXFl7iFGCQ5m JRFe7mbOWCHelMTKqtSi/Pii0pzU4kOMpkAPTWSWEk3OB8ZmXkm8oamhuYWlobmxubGZhZI4 b4fAwRghgfTEktTs1NSC1CKYPiYOTqkGxrNRxgLeN5dfeL3f3vHDpSvSPiqs+14uSmLtvahw RbjW+cdO+ctFjTdepCzqu+/LuNiF+8UeDeFlMZ2vDlxWjuSduV5whanmvkNxK/Q9ZlV4zJ75 rXdPuyuPldYSsaPTwkUmhkrLJiWyq20s3BFxksfrhXLbhJMiL3dP99rjyrQh6Oqak3JsOUos xRmJhlrMRcWJAAhvInSVAgAA X-CMS-MailID: 20190619150210eucas1p25fad2a2d416db30033737d97c622b89b X-Msg-Generator: CA Content-Type: text/plain; charset="utf-8" X-RootMTR: 20190618130008eucas1p176cc19c1c8b831fc30b4bf7b3294f3af X-EPHeader: CA CMS-TYPE: 201P X-CMS-RootMailID: 20190618130008eucas1p176cc19c1c8b831fc30b4bf7b3294f3af References: <1560862806.7731.11.camel@samsung.com> <523ba6f0-651a-444a-8ceb-c7c4ec186b20@www.fastmail.com> <1560866087.7731.18.camel@samsung.com> <6f974c69-9c16-4e9f-b0b6-37e40083223a@www.fastmail.com> On Tue, 2019-06-18 at 19:37 +0000, Daniel Shahaf wrote: > Peter Stephenson wrote on Tue, 18 Jun 2019 13:55 +00:00: > >  > > to be clear, what I was hoping for and lacking was something along the > > lines of: > >  > > echo /blah/blah/blah/**/*.oogabooga() > What about > . >     echo /blah/blah/blah/**/*.oogabooga(e.:t 2.) > . > after defining «function ":t" { … }» using one of the previous snippets? > You could even define curried versions, «_t2() { :t 2 "$@" }», for use > with the «(+_t2)» syntax. Yes, that's about the best I can think of, and the :t naming convention is a useful addition. Still probably worth having something this basic to do with the path built in.  Here's the change with a reasonably full set of tests. pws diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index a212d742d..61e41b9a7 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -260,9 +260,23 @@ see the definition of the filename extension in the description of the  tt(r) modifier below.  Note that according to that definition the result  will be empty if the string ends with a `tt(.)'.  ) -item(tt(h))( -Remove a trailing pathname component, leaving the head.  This works -like `tt(dirname)'. +item(tt(h) [ var(digits) ])( +Remove a trailing pathname component, shortening the path by one +directory level: this is the `head' of the pathname.  This works like +`tt(dirname)'.  If the tt(h) is followed immediately (with no spaces or +other separator) by any number of decimal digits, and the value of the +resulting number is non-zero, that number of leading components is +preserved instead of the final component being removed.  In an +absolute path the leading `tt(/)' is the first component, so, +for example, if tt(var=/my/path/to/something), then tt(${var:h3}) +substitutes tt(/my/path).  Consecutive `/'s are treated the same as +a single `/'.  In parameter substitution, digits may only be +used if the expression is in braces, so for example the short form +substitution tt($var:h2) is treated as tt(${var:h}2), not as +tt(${var:h2}).  No restriction applies to the use of digits in history +substitution or globbing qualifiers.  If more components are requested +than are present, the entire path is substituted (so this does not +trigger a `failed modifier' error in history expansion).  )  item(tt(l))(  Convert the words to all lowercase. @@ -316,9 +330,12 @@ immediately by a tt(g).  In parameter expansion the tt(&) must appear  inside braces, and in filename generation it must be quoted with a  backslash.  ) -item(tt(t))( -Remove all leading pathname components, leaving the tail.  This works -like `tt(basename)'. +item(tt(t) [ var(digits) ])( +Remove all leading pathname components, leaving the final component (tail). +This works like `tt(basename)'.  Any trailing slashes are first removed. +Decimal digits are handled as described above for (h), but in this +case that number of trailing components are preserved instead of +the default 1; 0 is treated the same as 1.  )  item(tt(u))(  Convert the words to all uppercase. diff --git a/NEWS b/NEWS index ec20b4982..4603c62a3 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,12 @@ specify the order of completion matches. This affects the display  of candidate matches and the order in which they are selected when  cycling between them using menu completion.   +The :h and :t modifiers in parameter expansion (if braces are present), +glob qualifiers and history expansion may take following decimal digit +arguments in order to keep that many leading or trailing path components +instead of the defaults of all but one (:h) and one (:t).  In an absolute +path the leading '/' counts as one component. +  Changes from 5.6.2 to 5.7.1  ---------------------------   diff --git a/README b/README index 9763e7aa6..be7929164 100644 --- a/README +++ b/README @@ -30,9 +30,28 @@ Zsh is a shell with lots of features.  For a list of some of these, see the  file FEATURES, and for the latest changes see NEWS.  For more  details, see the documentation.   -Incompatibilities since 5.6.2 +Incompatibilities since 5.7.1  -----------------------------   +The history expansion !:1:t2 used to be interpreted such that the 2 +was a separate character added after the history expansion.  Now +it is an argument to the :t modifier. + +For example + +% echo /my/interesting/path +% echo !:1:t2 + +used to echo "path2", but now echoes "interesting/path". + +The behaviour of :h has similarly changed. + +The behaviour has also changed in forms such as ${foo:t2) and *(:t2), +but in those cases the previous behaviour was not meaningful. + +Incompatibilities between 5.6.2 and 5.7.1 +----------------------------------------- +  1) vcs_info git: The gen-unapplied-string hook receives the patches in  order (next to be applied first).  This is consistent with the hg  backend and with one of two contradictory claims in the documentation diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c index f963d5712..f242e1b28 100644 --- a/Src/Zle/compctl.c +++ b/Src/Zle/compctl.c @@ -2511,7 +2511,7 @@ makecomplistcmd(char *os, int incmd, int flags)      else if (!(cmdstr &&     (((ccp = (Compctlp) compctltab->getnode(compctltab, cmdstr)) &&       (cc = ccp->cc)) || -    ((s = dupstring(cmdstr)) && remlpaths(&s) && +    ((s = dupstring(cmdstr)) && remlpaths(&s, 1) &&       (ccp = (Compctlp) compctltab->getnode(compctltab, s)) &&       (cc = ccp->cc))))) {   if (flags & CFN_DEFAULT) diff --git a/Src/glob.c b/Src/glob.c index ed2c90bd8..92fd64e7c 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -400,7 +400,7 @@ insert(char *s, int checked)   if (colonmod) {       /* Handle the remainder of the qualifier:  e.g. (:r:s/foo/bar/). */       char *mod = colonmod; -     modify(&news, &mod); +     modify(&news, &mod, 1);   }   if (!statted && (gf_sorts & GS_NORMAL)) {       statfullpath(s, &buf, 1); diff --git a/Src/hist.c b/Src/hist.c index 901cd3b1a..fd5606dc3 100644 --- a/Src/hist.c +++ b/Src/hist.c @@ -555,6 +555,27 @@ substfailed(void)      return -1;  }   +/* + * Return a count given by decimal digits after a modifier. + */ +static int +digitcount(void) +{ +    int c = ingetc(), count; + +    if (idigit(c)) { + count = 0; + do { +     count = 10 * count + (c - '0'); +     c = ingetc(); + } while (idigit(c)); +    } +    else + count = 0; +    inungetc(c); +    return count; +} +  /* Perform history substitution, returning the next character afterwards. */    /**/ @@ -835,7 +856,7 @@ histsubchar(int c)   }   break;       case 'h': - if (!remtpath(&sline)) { + if (!remtpath(&sline, digitcount())) {       herrflush();       zerr("modifier failed: h");       return -1; @@ -856,7 +877,7 @@ histsubchar(int c)   }   break;       case 't': - if (!remlpaths(&sline)) { + if (!remlpaths(&sline, digitcount())) {       herrflush();       zerr("modifier failed: t");       return -1; @@ -1974,16 +1995,18 @@ chrealpath(char **junkptr)    /**/  int -remtpath(char **junkptr) +remtpath(char **junkptr, int count)  {      char *str = strend(*junkptr);        /* ignore trailing slashes */      while (str >= *junkptr && IS_DIRSEP(*str))   --str; -    /* skip filename */ -    while (str >= *junkptr && !IS_DIRSEP(*str)) - --str; +    if (!count) { + /* skip filename */ + while (str >= *junkptr && !IS_DIRSEP(*str)) +     --str; +    }      if (str < *junkptr) {   if (IS_DIRSEP(**junkptr))       *junkptr = dupstring ("/"); @@ -1992,6 +2015,34 @@ remtpath(char **junkptr)     return 0;      } + +    if (count) +    { + /* +  * Return this many components, so start from the front. +  * Leading slash counts as one component, consistent with +  * behaviour of repeated applications of :h. +  */ + char *strp = *junkptr; + while (strp < str) { +     if (IS_DIRSEP(*strp)) { + if (--count <= 0) { +     if (strp == *junkptr) + ++strp; +     *strp = '\0'; +     return 1; + } + /* Count consecutive separators as one */ + while (IS_DIRSEP(strp[1])) +     ++strp; +     } +     ++strp; + } + + /* Full string needed */ + return 1; +    } +      /* repeated slashes are considered like a single slash */      while (str > *junkptr && IS_DIRSEP(str[-1]))   --str; @@ -2040,7 +2091,7 @@ rembutext(char **junkptr)    /**/  mod_export int -remlpaths(char **junkptr) +remlpaths(char **junkptr, int count)  {      char *str = strend(*junkptr);   @@ -2050,12 +2101,29 @@ remlpaths(char **junkptr)       --str;   str[1] = '\0';      } -    for (; str >= *junkptr; --str) - if (IS_DIRSEP(*str)) { -     *str = '\0'; -     *junkptr = dupstring(str + 1); -     return 1; +    for (;;) { + for (; str >= *junkptr; --str) { +     if (IS_DIRSEP(*str)) { + if (--count > 0) { +     if (str > *junkptr) { + --str; + break; +     } else { + /* Whole string needed */ + return 1; +     } + } + *str = '\0'; + *junkptr = dupstring(str + 1); + return 1; +     }   } + /* Count consecutive separators as 1 */ + while (str >= *junkptr && IS_DIRSEP(*str)) +     --str; + if (str <= *junkptr) +     break; +    }      return 0;  }   diff --git a/Src/subst.c b/Src/subst.c index 60eb33390..b132f251b 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -3438,7 +3438,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,       s--;       if (unset(KSHARRAYS) || inbrace) {   if (!isarr) -     modify(&val, &s); +     modify(&val, &s, inbrace);   else {       char *ss;       char **ap = aval; @@ -3447,12 +3447,12 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,         while ((*pp = *ap++)) {   ss = s; - modify(pp++, &ss); + modify(pp++, &ss, inbrace);       }       if (pp == aval) {   char *t = "";   ss = s; - modify(&t, &ss); + modify(&t, &ss, inbrace);       }       s = ss;   } @@ -4182,6 +4182,12 @@ arithsubst(char *a, char **bptr, char *rest)   * PTR is an in/out parameter.  On entry it contains the string of colon   * modifiers.  On return it points past the last recognised modifier.   * + * INBRACE is non-zero if we are in some form of a bracketed or + * parenthesised expression; it is zero for modifiers ocurring + * in an an unbracketed variable substitution.  This means that + * $foo:t222 is treated ias ${foo:t}222 rather than ${foo:t222} + * for backward compatibility. + *   * Example:   *     ENTRY:   *str is "."   *ptr is ":AN"   *     RETURN:  *str is "/home/foobar" (equal to $PWD)   *ptr points to the "N" @@ -4189,7 +4195,7 @@ arithsubst(char *a, char **bptr, char *rest)    /**/  void -modify(char **str, char **ptr) +modify(char **str, char **ptr, int inbrace)  {      char *ptr1, *ptr2, *ptr3, *lptr, c, *test, *sep, *t, *tt, tc, *e;      char *copy, *all, *tmp, sav, sav1, *ptr1end; @@ -4202,6 +4208,8 @@ modify(char **str, char **ptr)   *str = dupstring(*str);        while (**ptr == ':') { + int count = 0; +   lptr = *ptr;   (*ptr)++;   wall = gbal = 0; @@ -4214,10 +4222,8 @@ modify(char **str, char **ptr)              case 'a':              case 'A':       case 'c': -     case 'h':       case 'r':       case 'e': -     case 't':       case 'l':       case 'u':       case 'q': @@ -4226,6 +4232,17 @@ modify(char **str, char **ptr)   c = **ptr;   break;   +     case 'h': +     case 't': + c = **ptr; + if (inbrace && idigit((*ptr)[1])) { +     do { + count = 10 * count + ((*ptr)[1] - '0'); + ++(*ptr); +     } while (idigit((*ptr)[1])); + } + break; +       case 's':   c = **ptr;   (*ptr)++; @@ -4392,7 +4409,7 @@ modify(char **str, char **ptr)   break;       }       case 'h': - remtpath(©); + remtpath(©, count);   break;       case 'r':   remtext(©); @@ -4401,7 +4418,7 @@ modify(char **str, char **ptr)   rembutext(©);   break;       case 't': - remlpaths(©); + remlpaths(©, count);   break;       case 'l':   copy = casemodify(tt, CASMOD_LOWER); @@ -4478,7 +4495,7 @@ modify(char **str, char **ptr)       break;   }   case 'h': -     remtpath(str); +     remtpath(str, count);       break;   case 'r':       remtext(str); @@ -4487,7 +4504,7 @@ modify(char **str, char **ptr)       rembutext(str);       break;   case 't': -     remlpaths(str); +     remlpaths(str, count);       break;   case 'l':       *str = casemodify(*str, CASMOD_LOWER); diff --git a/Test/D02glob.ztst b/Test/D02glob.ztst index 08b71dc8e..5638e1255 100644 --- a/Test/D02glob.ztst +++ b/Test/D02glob.ztst @@ -700,3 +700,31 @@   print ${value//[${foo}b-z]/x}  0:handling of - range in complicated pattern context  >xx + + pathtotest=glob.tmp/my/test/dir/that/does/not/exist + mkdir -p $pathtotest + print $pathtotest(:h) + print $pathtotest(:h0) + print $pathtotest(:h10) + print $pathtotest(:h3) + print $pathtotest(:h2) + print $pathtotest(:h1) + print $pathtotest(:t) + print $pathtotest(:t0) + print $pathtotest(:t10) + print $pathtotest(:t3) + print $pathtotest(:t2) + print $pathtotest(:t1) +0:modifiers :h and :t with numbers (main test is in D04parameter.ztst) +>glob.tmp/my/test/dir/that/does/not +>glob.tmp/my/test/dir/that/does/not +>glob.tmp/my/test/dir/that/does/not/exist +>glob.tmp/my/test +>glob.tmp/my +>glob.tmp +>exist +>exist +>glob.tmp/my/test/dir/that/does/not/exist +>does/not/exist +>not/exist +>exist diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index 1ec650352..194c3e287 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -2445,3 +2445,80 @@ F:behavior, see http://austingroupbugs.net/view.php?id=888      : <<< ${(F)x/y}    }  0:Separation / join logic regresssion test + +  testpath=/one/two/three/four +  for (( i = 0; i <= 6; ++i )); do +    eval "print \$testpath:t$i" +    eval "print \${testpath:t$i}" +  done +0:t with trailing digits +>four0 +>four +>four1 +>four +>four2 +>three/four +>four3 +>two/three/four +>four4 +>one/two/three/four +>four5 +>/one/two/three/four +>four6 +>/one/two/three/four + +  testpath=/one/two/three/four +  for (( i = 0; i <= 6; ++i )); do +    eval "print \$testpath:h$i" +    eval "print \${testpath:h$i}" +  done +0:h with trailing digits +>/one/two/three0 +>/one/two/three +>/one/two/three1 +>/ +>/one/two/three2 +>/one +>/one/two/three3 +>/one/two +>/one/two/three4 +>/one/two/three +>/one/two/three5 +>/one/two/three/four +>/one/two/three6 +>/one/two/three/four + +  testpath=/a/quite/long/path/to/do/messy/stuff/with +  print $testpath:h2:t3:h5:t16:h2n2 +  print ${testpath:t5:h2} +  print ${testpath:t5:h2:t} +  print ${testpath:h6:t4:h3:t2:h} +  print ${testpath:h10:t10:t6:h3} +  print ${testpath:t9:h} +  print ${testpath:t9:h:t} +0:Combinations of :h and :t with and without trailing digits +>/a/quite/long/path/to/do/messy/stuff2:t3:h5:t16:h2n2 +>to/do +>do +>long +>path/to/do +>a/quite/long/path/to/do/messy/stuff +>stuff + + testpath=///this//has////lots//and////lots//of////slashes + print ${testpath:h3} + print ${testpath:t4} +0:Multiple slashes are treated as one in :h and :t but are not removed +>///this//has +>and////lots//of////slashes + + testpath=trailing/slashes/are/removed/// + print ${testpath:h} + print ${testpath:h2} + print ${testpath:t} + print ${testpath:t2} +0:Modifiers :h and :t remove trailing slashes before examining path +>trailing/slashes/are +>trailing/slashes +>removed +>are/removed diff --git a/Test/W01history.ztst b/Test/W01history.ztst index 6ef9b11cc..96d0beb61 100644 --- a/Test/W01history.ztst +++ b/Test/W01history.ztst @@ -58,3 +58,26 @@  *?*  F:Check that a history bug introduced by workers/34160 is working again.  # Discarded line of error output consumes prompts printed by "zsh -i". + + $ZTST_testdir/../Src/zsh -fis <<<' + echo /my/path/for/testing + echo !1:1:h10 + echo !1:1:h3 + echo !1:1:h2 + echo !1:1:h1 + echo !1:1:t10 + echo !1:1:t3 + echo !1:1:t2 + echo !1:1:t1 + echo !1:1:t3:h2' 2>/dev/null +0:Modifiers :h and :t with arguments +>/my/path/for/testing +>/my/path/for/testing +>/my/path +>/my +>/ +>/my/path/for/testing +>path/for/testing +>for/testing +>testing +>path/for