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 2ce14f23 for ; Tue, 18 Jun 2019 13:01:01 +0000 (UTC) Received: (qmail 22146 invoked by alias); 18 Jun 2019 13:00:51 -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: 44421 Received: (qmail 24870 invoked by uid 1010); 18 Jun 2019 13:00:50 -0000 X-Qmail-Scanner-Diagnostics: from mailout2.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.12):SA:0(-7.0/5.0):. Processed in 3.29989 secs); 18 Jun 2019 13:00:50 -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.12 as permitted sender) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout2.w1.samsung.com 20190618130010euoutp02a693964e6f27369d84cb98a22df24feb~pTHS3jF0_0797607976euoutp02C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1560862810; bh=dvWW9a8GVN4a2Hefqxgs2/7aucXwnDvblFSCGxrf6rc=; h=Subject:From:To:Date:References:From; b=ZSDmNN475lp/UE0+QqHPwVAFUs3Km3tEJF4KkleCpRd3n1iO3HPQ1qAltXYwceNqt ZvC8bClFMJWzfyEBf6w4lihIUao4AFVxRfXUu9th4NPccosiTxSO4/6+jU5+IigGb8 D+3JMwibvjuNN27U/kpPDqOE/pFPV4Aah54CL0iY= X-AuditID: cbfec7f2-3615e9c0000010ca-fa-5d08e0586939 Message-ID: <1560862806.7731.11.camel@samsung.com> Subject: PATCH: trailing components From: Peter Stephenson To: Zsh Hackers' List Date: Tue, 18 Jun 2019 14:00:06 +0100 X-Mailer: Evolution 3.18.5.2-0ubuntu3.2 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrDIsWRmVeSWpSXmKPExsWy7djPc7oRDzhiDXpX6FocbH7I5MDoserg B6YAxigum5TUnMyy1CJ9uwSujFUn/7IWnFGvOHvoPksD4x/5LkZODgkBE4lV7bNZQGwhgRWM El/6PbsYuYDsPiaJxcunMkM4vUwSN5f2scB03N33lhUisZxR4u/ag2xwVbc2T2OHcM4wSmza fZ4JwrnAKPH+TxsTSD+vgJFE38+PQIM5OIQFlCWmvo4ACbMJGEpM3TSbESQsIqAt0f5RDCTM IqAq8fLHZVaIzRoSG24eg5oiKHFy5hOwi5gF5CWat84GO1VC4AybxIQ1TewQDS4SJ25dhLKF JV4d3wJly0j83zmfCaKhnVFizaTX7BBOD9DVR+8wQlRZS/Tdvgh2EbOApsT6XfoQYUeJ5Ud3 sYKEJQT4JG68FYQ4gk9i0rbpzBBhXomONiGIajWJHU1bGSHCMhJP1yhAmB4S7+7aTGBUnIXk mVlInpmFsHUBI/MqRvHU0uLc9NRiw7zUcr3ixNzi0rx0veT83E2MwDRw+t/xTzsYv15KOsQo wMGoxMMr0cweK8SaWFZcmXuIUYKDWUmEd6oxR6wQb0piZVVqUX58UWlOavEhRmkOFiVx3mqG B9FCAumJJanZqakFqUUwWSYOTqkGRik7Ob8F/WHVN8yF3qXJ/3NZOotpXudJU08e0zjpJStj NaK228mpzk6dbXRJXL3aoMN2/juPpthlO/9dU5rzXPfUKfG7OfxZx3Rnf4/+kVE0syEnd3et /jaTqzOj2RoVH0YsirWMrq1xrraq380r9oP1BdcKP6nbixbl1frNWsy5eXHW5VhfJZbijERD Leai4kQAlEYUIP8CAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrOLMWRmVeSWpSXmKPExsVy+t/xu7rhDzhiDU48srA42PyQyYHRY9XB D0wBjFF6NkX5pSWpChn5xSW2StGGFkZ6hpYWekYmlnqGxuaxVkamSvp2NimpOZllqUX6dgl6 GatO/mUtOKNecfbQfZYGxj/yXYycHBICJhJ3971l7WLk4hASWMoosePLXjaIhIzEpysf2SFs YYk/17rA4kIC3UwSS6erQTScYZT4N2k/VPcFRon+xv9gHbwCRhJ9Pz8ydzFycAgLKEtMfR0B EmYTMJSYumk2I0hYREBbov2jGEiYRUBV4uWPy6wgNrOApkTr9t9QezUkNtw8xgQxUVDi5Mwn LBA18hLNW2czT2AUmIWkZRaSsllIyhYwMq9iFEktLc5Nzy021CtOzC0uzUvXS87P3cQIDORt x35u3sF4aWPwIUYBDkYlHt6CVvZYIdbEsuLK3EOMEhzMSiK8U405YoV4UxIrq1KL8uOLSnNS iw8xmgIdPpFZSjQ5HxhleSXxhqaG5haWhubG5sZmFkrivB0CB2OEBNITS1KzU1MLUotg+pg4 OKUaGK3EtHYIa3Hdm3fp+oZJAtc8v792/cyz5Ubux/kaRw8kL7XlOmumcO7JqR9v4py/bvdN YLMLZm3c07Tw99usN7/ckkJfWmv1KEkHfnl/8mPkoq+7XY2vCAafKpHRP5eQe83s+BXDjXN7 lk6aP+Ux44UNrFu6Ch/fnZn868t+3/nhUl0+2QKLU64rsRRnJBpqMRcVJwIABmqH1HoCAAA= X-CMS-MailID: 20190618130008eucas1p176cc19c1c8b831fc30b4bf7b3294f3af 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: I needed to preserve a number of trailing components of a path (other than one) and couldn't think of an easy way of doing it.  Rather than craft obscure pattern substitutions, or use an ad-hoc expression to strip the prefix, I came up with a patch to add an optional number after the "t" in history style modifiers to do this.  I put it after rather than before because history-style colon expressions are quite sensitive to what the first character is after the colon. Before I come up with tests and fix up the ensuing failures, you can let me know if there's a better way of doing this to save me the trouble. pws diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index a212d742d..d28a30767 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -316,9 +316,11 @@ 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))( +item(tt(t) [ var(digits) ])(  Remove all leading pathname components, leaving the tail.  This works -like `tt(basename)'. +like `tt(basename)'.  Any trailing slashes are first removed. +If followed by any number of decimal digits, that number of trailing +components is preserved.  )  item(tt(u))(  Convert the words to all uppercase. 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/hist.c b/Src/hist.c index 901cd3b1a..2117f2bd6 100644 --- a/Src/hist.c +++ b/Src/hist.c @@ -798,7 +798,7 @@ histsubchar(int c)   c = (cflag) ? ':' : ingetc();   cflag = 0;   if (c == ':') { -     int gbal = 0; +     int gbal = 0, count;         if ((c = ingetc()) == 'g') {   gbal = 1; @@ -856,7 +856,18 @@ histsubchar(int c)   }   break;       case 't': - if (!remlpaths(&sline)) { + c = ingetc(); + if (idigit(c)) { +     count = 0; +     do { + count = 10 * count + (c - '0'); + c = ingetc(); +     } while (idigit(c)); + } + else +     count = 1; + inungetc(c); + if (!remlpaths(&sline, count)) {       herrflush();       zerr("modifier failed: t");       return -1; @@ -2040,7 +2051,7 @@ rembutext(char **junkptr)    /**/  mod_export int -remlpaths(char **junkptr) +remlpaths(char **junkptr, int count)  {      char *str = strend(*junkptr);   @@ -2050,12 +2061,21 @@ 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 && str > *junkptr) { +     --str; +     break; + } + *str = '\0'; + *junkptr = dupstring(str + 1); + return 1; +     }   } + if (str <= *junkptr) +     break; +    }      return 0;  }   diff --git a/Src/subst.c b/Src/subst.c index 60eb33390..d1fff2e67 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -4193,7 +4193,7 @@ modify(char **str, char **ptr)  {      char *ptr1, *ptr2, *ptr3, *lptr, c, *test, *sep, *t, *tt, tc, *e;      char *copy, *all, *tmp, sav, sav1, *ptr1end; -    int gbal, wall, rec, al, nl, charlen, dellen; +    int gbal, wall, rec, al, nl, charlen, dellen, count = 1;      convchar_t del;        test = NULL; @@ -4217,7 +4217,6 @@ modify(char **str, char **ptr)       case 'h':       case 'r':       case 'e': -     case 't':       case 'l':       case 'u':       case 'q': @@ -4226,6 +4225,17 @@ modify(char **str, char **ptr)   c = **ptr;   break;   +     case 't': + c = **ptr; + if (idigit((*ptr)[1])) { +     count = 0; +     do { + count = 10 * count + ((*ptr)[1] - '0'); + ++(*ptr); +     } while (idigit((*ptr)[1])); + } + break; +       case 's':   c = **ptr;   (*ptr)++; @@ -4401,7 +4411,7 @@ modify(char **str, char **ptr)   rembutext(©);   break;       case 't': - remlpaths(©); + remlpaths(©, count);   break;       case 'l':   copy = casemodify(tt, CASMOD_LOWER); @@ -4487,7 +4497,7 @@ modify(char **str, char **ptr)       rembutext(str);       break;   case 't': -     remlpaths(str); +     remlpaths(str, count);       break;   case 'l':       *str = casemodify(*str, CASMOD_LOWER);