about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
authorOliver Kiddle <opk@zsh.org>2021-11-12 20:33:52 +0100
committerOliver Kiddle <opk@zsh.org>2021-11-12 20:33:52 +0100
commitdfb7ac94bb4c28472d759a61ea3c2dab30cf9cd3 (patch)
tree1894d81725e4825c1b1948c0ccf1236b439e3710 /Src
parent631576de0f7b4e52487175e3e017e5136424b626 (diff)
downloadzsh-dfb7ac94bb4c28472d759a61ea3c2dab30cf9cd3.tar.gz
zsh-dfb7ac94bb4c28472d759a61ea3c2dab30cf9cd3.tar.xz
zsh-dfb7ac94bb4c28472d759a61ea3c2dab30cf9cd3.zip
49561: add zformat -F option, similar to -f but ternary expressions check for existence instead of doing math evaluation
Diffstat (limited to 'Src')
-rw-r--r--Src/Modules/zutil.c48
1 files changed, 32 insertions, 16 deletions
diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c
index 691ba6c2f..2f17c03f1 100644
--- a/Src/Modules/zutil.c
+++ b/Src/Modules/zutil.c
@@ -776,10 +776,12 @@ bin_zstyle(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
  *   ousedp	(*outp)[*ousedp] is where to write next
  *   olenp	*olenp is the size allocated for *outp
  *   endchar    Terminator character in addition to `\0' (may be '\0')
+ *   presence   -F: Ternary expressions test emptyness instead
  *   skip	If 1, don't output, just parse.
  */
 static char *zformat_substring(char* instr, char **specs, char **outp,
-			       int *ousedp, int *olenp, int endchar, int skip)
+			       int *ousedp, int *olenp, int endchar,
+			       int presence, int skip)
 {
     char *s;
 
@@ -813,20 +815,29 @@ static char *zformat_substring(char* instr, char **specs, char **outp,
 	    if (testit && STOUC(*s)) {
 		int actval, testval, endcharl;
 
-		/*
-		 * One one number is useful for ternary expressions.
-		 * Remember to put the sign back.
-		 */
+		/* Only one number is useful for ternary expressions. */
 		testval = (min >= 0) ? min : (max >= 0) ? max : 0;
-		if (right)
-		    testval *= -1;
 
-		if (specs[STOUC(*s)])
-		    actval = (int)mathevali(specs[STOUC(*s)]);
-		else
-		    actval = 0;
-		/* zero means values are equal, i.e. true */
-		actval -= testval;
+		if (specs[STOUC(*s)] && *specs[STOUC(*s)]) {
+		    if (presence) {
+			if (testval)
+#ifdef MULTIBYTE_SUPPORT
+			    if (isset(MULTIBYTE))
+				actval = MB_METASTRWIDTH(specs[STOUC(*s)]);
+			    else
+#endif
+				actval = strlen(specs[STOUC(*s)]);
+		        else
+			    actval = 1;
+			actval = right ? (testval < actval) : (testval >= actval);
+		    } else {
+			if (right) /* put the sign back */
+			    testval *= -1;
+			/* zero means values are equal, i.e. true */
+			actval = (int)mathevali(specs[STOUC(*s)]) - testval;
+		    }
+		} else
+		    actval = presence ? !right : testval;
 
 		/* careful about premature end of string */
 		if (!(endcharl = *++s))
@@ -837,10 +848,10 @@ static char *zformat_substring(char* instr, char **specs, char **outp,
 		 * vice versa... unless we are already skipping.
 		 */
 		if (!(s = zformat_substring(s+1, specs, outp, ousedp,
-					    olenp, endcharl, skip || actval)))
+			    olenp, endcharl, presence, skip || actval)))
 		    return NULL;
 		if (!(s = zformat_substring(s+1, specs, outp, ousedp,
-					    olenp, ')', skip || !actval)))
+			    olenp, ')', presence, skip || !actval)))
 		    return NULL;
 	    } else if (skip) {
 		continue;
@@ -912,6 +923,7 @@ static int
 bin_zformat(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
 {
     char opt;
+    int presence = 0;
 
     if (args[0][0] != '-' || !(opt = args[0][1]) || args[0][2]) {
 	zwarnnam(nam, "invalid argument: %s", args[0]);
@@ -920,6 +932,9 @@ bin_zformat(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
     args++;
 
     switch (opt) {
+    case 'F':
+	presence = 1;
+	/* fall-through */
     case 'f':
 	{
 	    char **ap, *specs[256] = {0}, *out;
@@ -939,7 +954,8 @@ bin_zformat(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
 	    }
 	    out = (char *) zhalloc(olen = 128);
 
-	    zformat_substring(args[1], specs, &out, &oused, &olen, '\0', 0);
+	    zformat_substring(args[1], specs, &out, &oused, &olen, '\0',
+		    presence, 0);
 	    out[oused] = '\0';
 
 	    setsparam(args[0], ztrdup(out));