Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
PATCH: Enable extendedglob in pattern with ${(*)name/pattern/replacement}
- X-seq: zsh-workers 47364
- From: Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx>
- To: Zsh hackers list <zsh-workers@xxxxxxx>
- Subject: PATCH: Enable extendedglob in pattern with ${(*)name/pattern/replacement}
- Date: Sat, 5 Sep 2020 20:05:04 -0700
- Archived-at: <https://zsh.org/workers/47364>
- Archived-at: <http://www.zsh.org/sympa/arcsearch_id/zsh-workers/2020-09/CAH%2Bw%3D7bOcvJ_PChh_8TwZZM%2B2e-ONY9eap_6o%3DnMWcZkR_yBjQ%40mail.gmail.com>
- Authentication-results: zsh.org; iprev=pass (mail-ot1-f50.google.com) smtp.remote-ip=209.85.210.50; dkim=pass header.d=brasslantern-com.20150623.gappssmtp.com header.s=20150623 header.a=rsa-sha256; dmarc=none header.from=brasslantern.com; arc=none
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=brasslantern-com.20150623.gappssmtp.com; s=20150623; h=mime-version:from:date:message-id:subject:to; bh=iy11KE4cCdYfgFtMyGKvcDm9rJ4JNhocs7G/y/T9gbg=; b=nMj1QuwBbNfXEfnX3UNo5YSR9ffilvidceTfKCO7HQAvAmqFPF+qNGX4qR98oVefN6 DfGHS8QqkplLFw1VIcMYRqIyipJ1EgD4rs06pSWo2HIcDTzFgMsppi/xK8Zrm6ppM3ZM zYwQRKMNR/lXtBnZwxzlzJ+cXrC0GCjfd+pLMVBqAALlJRcTp6P7CaQqugf2gHZmlQ2i +paTi3zvnfqm9we+FgR+ZWS0wxGkGSVUoR0z7sgQ3glr5b1AoArV+M/++kP4n1l09t5T L0l9yOq050Z0bMGOYsniTHHa7ENLhA8SRknhRDlOdxlJ7m084l+UqQ8W38Arc9/Ob2YX IiOg==
- List-archive: <http://www.zsh.org/sympa/arc/zsh-workers>
- List-help: <mailto:sympa@zsh.org?subject=help>
- List-id: <zsh-workers.zsh.org>
- List-owner: <mailto:zsh-workers-request@zsh.org>
- List-post: <mailto:zsh-workers@zsh.org>
- List-subscribe: <mailto:sympa@zsh.org?subject=subscribe%20zsh-workers>
- List-unsubscribe: <mailto:sympa@zsh.org?subject=unsubscribe%20zsh-workers>
- Sender: zsh-workers-request@xxxxxxx
In retrospect I'm surprised this wasn't thought of before. With this
you can for example enable backreferences without having to turn on
extendedglob for the whole surrounding context.
A different character could be chosen if (*) seems unwise for some
reason. It should also be fairly straightforward to make (**) toggle
the option if there's a reason to force extendedglob off.
Patch includes (very brief) doc, and a test case.
diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo
index cbdae4d58..b3396721f 100644
--- a/Doc/Zsh/expn.yo
+++ b/Doc/Zsh/expn.yo
@@ -1422,7 +1422,7 @@ error, and the flag itself has no effect.
enditem()
The following flags are meaningful with the tt(${)...tt(#)...tt(}) or
-tt(${)...tt(%)...tt(}) forms. The tt(S) and tt(I) flags may also be
+tt(${)...tt(%)...tt(}) forms. The tt(S), tt(I), and tt(*) flags may also be
used with the tt(${)...tt(/)...tt(}) forms.
startitem()
@@ -1488,6 +1488,10 @@ will remove the same matches as for `tt(#)', but in reverse order, and the
form using `tt(%%)' will remove the same matches as for `tt(##)' in reverse
order.
)
+item(tt(*))(
+Enable tt(EXTENDED_GLOB) for substitution via tt(${)...tt(/)...tt(}) or
+tt(${)...tt(//)...tt(}).
+)
item(tt(B))(
Include the index of the beginning of the match in the result.
)
diff --git a/Src/subst.c b/Src/subst.c
index b98ddaf02..2af61653a 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -1708,7 +1708,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
/*
* This expressive name refers to the set of flags which
* is applied to matching for #, %, / and their doubled variants:
- * (M), (R), (B), (E), (N), (S).
+ * (M), (R), (B), (E), (N), (S), (*).
*/
int flags = 0;
/* Value from (I) flag, used for ditto. */
@@ -1930,6 +1930,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
case '@':
nojoin = 2; /* nojoin = 2 means force */
break;
+ case '*':
+ case Star:
+ flags |= SUB_EGLOB;
+ break;
case 'M':
flags |= SUB_MATCH;
break;
@@ -2810,7 +2814,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
c == '#' || c == Pound ||
c == '?' || c == Quest ||
c == '/')) {
-
+ int eglob = isset(EXTENDEDGLOB);
/*
* Default index is 1 if no (I) or (I) gave zero. But
* why don't we set the default explicitly at the start
@@ -2832,9 +2836,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
char *ptr;
/*
* previous flags are irrelevant, except for (S) which
- * indicates shortest substring; else look for longest.
+ * indicates shortest substring; else look for longest,
+ # and (*) which temporarily enables extended globbing.
*/
- flags = (flags & SUB_SUBSTR) ? 0 : SUB_LONG;
+ flags = ((flags & SUB_SUBSTR) ? 0 : SUB_LONG)|(flags & SUB_EGLOB);
if ((c = *s) == '/') {
/* doubled, so replace all occurrences */
flags |= SUB_GLOBAL;
@@ -3136,7 +3141,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
for (ap = aval; *ap; ap++) {
untokenize(*ap);
}
+ if (flags & SUB_EGLOB)
+ opts[EXTENDEDGLOB] = 1;
getmatcharr(&aval, s, flags, flnum, replstr);
+ opts[EXTENDEDGLOB] = eglob;
} else {
if (vunset) {
if (vunset > 0 && unset(UNSET)) {
@@ -3151,7 +3159,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
copied = 1;
untokenize(val);
}
+ if (flags & SUB_EGLOB)
+ opts[EXTENDEDGLOB] = 1;
getmatch(&val, s, flags, flnum, replstr);
+ opts[EXTENDEDGLOB] = eglob;
}
break;
}
diff --git a/Src/zsh.h b/Src/zsh.h
index 94f5099c6..6cf1b4186 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1991,6 +1991,7 @@ struct tieddata {
#define SUB_START 0x1000 /* force match at start with SUB_END
* and no SUB_SUBSTR */
#define SUB_LIST 0x2000 /* no substitution, return list of matches */
+#define SUB_EGLOB 0x4000 /* use extended globbing in patterns */
/*
* Structure recording multiple matches inside a test string.
diff --git a/Test/D02glob.ztst b/Test/D02glob.ztst
index f250244e7..176846d46 100644
--- a/Test/D02glob.ztst
+++ b/Test/D02glob.ztst
@@ -792,6 +792,11 @@
*>*/glob.tmp/(flip|flop)
*>*/glob.tmp/(flip|flop)/trailing/components
+ unsetopt extendedglob
+ print -r -- ${(*)=${(@s.+.):-A+B}/(#b)(?)/-${(L)match[1]} ${match[1]}}
+0:the '*' qualfier enables extended_glob for pattern matching
+>-a A -b B
+
%clean
# Fix unreadable-directory permissions so ztst can clean up properly
Messages sorted by:
Reverse Date,
Date,
Thread,
Author