zsh-workers
 help / color / mirror / code / Atom feed
From: Peter Stephenson <p.stephenson@samsung.com>
To: Zsh Hackers' List <zsh-workers@zsh.org>
Subject: PATCH: trailing components
Date: Tue, 18 Jun 2019 14:00:06 +0100	[thread overview]
Message-ID: <1560862806.7731.11.camel@samsung.com> (raw)
In-Reply-To: <CGME20190618130008eucas1p176cc19c1c8b831fc30b4bf7b3294f3af@eucas1p1.samsung.com>

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(&copy);
 			break;
 		    case 't':
-			remlpaths(&copy);
+			remlpaths(&copy, 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);


       reply	other threads:[~2019-06-18 13:01 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CGME20190618130008eucas1p176cc19c1c8b831fc30b4bf7b3294f3af@eucas1p1.samsung.com>
2019-06-18 13:00 ` Peter Stephenson [this message]
2019-06-18 13:37   ` Daniel Shahaf
2019-06-18 13:54     ` Peter Stephenson
2019-06-18 14:45       ` Mikael Magnusson
2019-06-18 15:39         ` Peter Stephenson
2019-06-18 19:37       ` Daniel Shahaf
2019-06-19 15:02         ` Peter Stephenson
2019-06-20 10:14           ` Peter Stephenson
2019-06-18 14:42     ` Mikael Magnusson

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=1560862806.7731.11.camel@samsung.com \
    --to=p.stephenson@samsung.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).