Subject: PATCH: Allow / in full pattern alternations
From: Mikael Magnusson <[email-masked]>
To: [email-masked]
Date: Mon, 11 Apr 2016 14:06:14 +0200
List-Id: Zsh Workers List <zsh-workers.zsh.org>

Well, it was a bit easier than I thought.

% print -l (${(~j:|:)${:-$^fpath/rep*}})
/home/mikaelh/.zsh/functions/repoint
/home/mikaelh/.zsh/functions/repointmany
/usr/local/share/zsh/5.2-dev-1-mika/functions/replace-argument
/usr/local/share/zsh/5.2-dev-1-mika/functions/replace-string
/usr/local/share/zsh/5.2-dev-1-mika/functions/replace-string-again

This patch is obviously pretty ugly, and just intended as a proof of
concept / pile of crap, and it will leak stuff / do weird things if
there was an error in a sub-globpattern.

It is also obviously not intended for inclusion, I just wanted to see
what the code might look like and what would be needed. But if someone
is struck by some inspiration about how to implement this in a way that
is less horrible, feel free to say how :).

---
 Src/glob.c | 47 ++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 36 insertions(+), 11 deletions(-)

diff --git a/Src/glob.c b/Src/glob.c
index 7848598..610396d 100644
--- a/Src/glob.c
+++ b/Src/glob.c
@@ -1829,17 +1829,27 @@ zglob(LinkList list, LinkNode np, int nountok)
 	    quals = newquals;
     }
     q = parsepat(str);
+    int specialhack = 0;
     if (!q || errflag) {	/* if parsing failed */
-	restore_globstate(saved);
-	if (unset(BADPATTERN)) {
-	    if (!nountok)
-		untokenize(ostr);
-	    insertlinknode(list, node, ostr);
+	char *par = str;
+	if (*str == zpc_special[ZPC_INPAR] &&
+	    !skipparens(Inpar, Outpar, (char **)&par) &&
+	    !*par && zpc_special[ZPC_BAR] && strchr(str, zpc_special[ZPC_BAR]))
+	{
+	    specialhack = 1;
+	    errflag &= ~ERRFLAG_ERROR;
+	} else {
+	    restore_globstate(saved);
+	    if (unset(BADPATTERN)) {
+		if (!nountok)
+		    untokenize(ostr);
+		insertlinknode(list, node, ostr);
+		return;
+	    }
+	    errflag &= ~ERRFLAG_ERROR;
+	    zerr("bad pattern: %s", ostr);
 	    return;
 	}
-	errflag &= ~ERRFLAG_ERROR;
-	zerr("bad pattern: %s", ostr);
-	return;
     }
     if (!gf_nsorts) {
 	gf_sortlist[0].tp = gf_sorts = (shortcircuit ? GS_NONE : GS_NAME);
@@ -1852,9 +1862,24 @@ zglob(LinkList list, LinkNode np, int nountok)
     matchct = 0;
     pattrystart();
 
-    /* The actual processing takes place here: matches go into  *
-     * matchbuf.  This is the only top-level call to scanner(). */
-    scanner(q, shortcircuit);
+    if (!specialhack) {
+	/* The actual processing takes place here: matches go into  *
+	 * matchbuf.  This is the only top-level call to scanner(). */
+	scanner(q, shortcircuit);
+    } else {
+	str++;
+	while (*str) {
+	    char *next = strchr(str, zpc_special[ZPC_BAR]);
+	    if (!next) next = strchr(str, Outpar);
+	    if (!next) break;
+	    *next = '\0';
+	    q = parsepat(str);
+	    // XXX handle errors magically
+	    scanner(q, shortcircuit);
+	    str = next+1;
+	}
+    }
+
 
     /* Deal with failures to match depending on options */
     if (matchct)
-- 
2.6.1