From: Sven Wischnowsky <wischnow@informatik.hu-berlin.de>
To: zsh-workers@sunsite.auc.dk
Subject: PATCH: new parameter expansion type?
Date: Mon, 30 Aug 1999 11:49:27 +0200 (MET DST) [thread overview]
Message-ID: <199908300949.LAA20865@beta.informatik.hu-berlin.de> (raw)
This is from `_arguments':
if [[ "$def" = :* ]]; then
opt=yes
else
opt=''
fi
... the completion functions are full of these -- always making me
wish that we had some kind of ternary operator in parameter
expansions. The patch below implements this:
${name^pattern^then^else}
Gives you the (substituted) `then' string if the expansion of `name'
matches the `pattern' and otherwise it gives you the `else'
string. The first `^' may be doubled to negate the test. `^'s in the
`pattern' and the `then' may be quoted with two bacslashes (as in
`${../..}'). The `^else' may be omitted in which case it expands to
nothing (not even the empty string if you are using this on an array)
if the `pattern' doesn't match. Finally, the `then' and the `else' may
be only a `.' to make them expand to the original string (needed if
used on arrays).
Ok, the `.' thingy is just because I couldn't think of a better
character/syntax (suggestions?) and this isn't as powerful as I would
like it because `then' and `else' can't expand to arrays. Maybe we
could make `${(A)foo^?^$arr1^$arr2}' do that (and maybe we could do
the same for `${(A)foo:-$arr}'.
But then, maybe you don't like this at all...
Bye
Sven
--- os/subst.c Sun Aug 29 20:02:43 1999
+++ Src/subst.c Sun Aug 29 21:38:14 1999
@@ -725,6 +725,8 @@
char *sep = NULL, *spsep = NULL;
char *premul = NULL, *postmul = NULL, *preone = NULL, *postone = NULL;
char *replstr = NULL; /* replacement string for /orig/repl */
+ char *thenstr, *elsestr; /* then and else for ${..^..^..^..} */
+ int negpat = 0;
zlong prenum = 0, postnum = 0;
int copied = 0;
int arrasg = 0;
@@ -1227,7 +1229,8 @@
*s == '%' ||
*s == '#' || *s == Pound ||
*s == '?' || *s == Quest ||
- *s == '/')) {
+ *s == '/' ||
+ *s == '^' || *s == Hat)) {
if (!flnum)
flnum++;
@@ -1282,7 +1285,47 @@
untokenize(replstr);
*ptr = '\0';
}
+ if (s[-1] == '^' || s[-1] == Hat) {
+ char *ptr = s;
+ if (*s == s[-1]) {
+ s++;
+ negpat = 1;
+ }
+ for (ptr = s; *ptr && *ptr != '^' && *ptr != Hat; ptr++)
+ if (*ptr == '\\' && (ptr[1] == '^' || ptr[1] == Hat))
+ chuck(ptr);
+ if (!*ptr || !ptr[1]) {
+ zerr("missing `then' string", NULL, 0);
+ return NULL;
+ }
+ *ptr++ = '\0';
+ thenstr = ptr;
+ for (; *ptr && *ptr != '^' && *ptr != Hat; ptr++)
+ if (*ptr == '\\' && (ptr[1] == '^' || ptr[1] == Hat))
+ chuck(ptr);
+ if (*ptr) {
+ elsestr = ptr + 1;
+ if (elsestr[0] == '\\' && elsestr[1] == '.')
+ elsestr++;
+ if (elsestr[0] == '.' && !elsestr[1])
+ elsestr = (char *) 1;
+ else {
+ singsub(&elsestr);
+ untokenize(elsestr);
+ }
+ *ptr = '\0';
+ } else
+ elsestr = NULL;
+ if (thenstr[0] == '\\' && thenstr[1] == '.')
+ thenstr++;
+ if (thenstr[0] == '.' && !thenstr[1])
+ thenstr = (char *) 1;
+ else {
+ singsub(&thenstr);
+ untokenize(thenstr);
+ }
+ }
if (colf)
flags |= SUB_ALL;
/*
@@ -1396,6 +1439,8 @@
case '#':
case Pound:
case '/':
+ case '^':
+ case Hat:
if (qt) {
int one = noerrs, oef = errflag, haserr;
@@ -1417,26 +1462,65 @@
char t = s[-1];
singsub(&s);
- if (t == '/' && (flags & SUB_SUBSTR)) {
- if (*s == '#' || *s == '%') {
- flags &= ~SUB_SUBSTR;
- if (*s == '%')
- flags |= SUB_END;
- s++;
- } else if (*s == '\\') {
- s++;
+ if (t == '^' || t == Hat) {
+ if (!vunset && isarr) {
+ char **ap, **pp;
+ Patprog pprg;
+
+ if (!(pprg = patcompile(s, PAT_STATIC, NULL))) {
+ zerr("bad pattern: %s", s, 0);
+ return NULL;
+ }
+ if (!copied)
+ aval = arrdup(aval), copied = 1;
+ for (ap = pp = aval; *ap; ap++) {
+ if ((!!pattry(pprg, *ap)) ^ negpat)
+ *pp++ = dupstring(thenstr == ((char *) 1) ?
+ *ap : thenstr);
+ else if (elsestr)
+ *pp++ = dupstring(elsestr == ((char *) 1) ?
+ *ap : elsestr);
+ }
+ *pp = NULL;
+ } else {
+ Patprog pprg;
+
+ if (vunset)
+ val = dupstring("");
+ if ((pprg = patcompile(s, PAT_STATIC, NULL)) &&
+ ((!!pattry(pprg, val)) ^ negpat))
+ val = dupstring(thenstr == ((char *) 1) ?
+ val : thenstr);
+ else if (elsestr)
+ val = dupstring(elsestr == ((char *) 1) ?
+ val : elsestr);
+ else {
+ vunset = 1;
+ val = dupstring("");
+ }
+ copied = 1;
+ }
+ } else {
+ if (t == '/' && (flags & SUB_SUBSTR)) {
+ if (*s == '#' || *s == '%') {
+ flags &= ~SUB_SUBSTR;
+ if (*s == '%')
+ flags |= SUB_END;
+ s++;
+ } else if (*s == '\\') {
+ s++;
+ }
+ }
+ if (!vunset && isarr) {
+ getmatcharr(&aval, s, flags, flnum, replstr);
+ copied = 1;
+ } else {
+ if (vunset)
+ val = dupstring("");
+ getmatch(&val, s, flags, flnum, replstr);
+ copied = 1;
}
}
- }
-
- if (!vunset && isarr) {
- getmatcharr(&aval, s, flags, flnum, replstr);
- copied = 1;
- } else {
- if (vunset)
- val = dupstring("");
- getmatch(&val, s, flags, flnum, replstr);
- copied = 1;
}
break;
}
--- od/Zsh/expn.yo Sun Aug 29 20:02:39 1999
+++ Doc/Zsh/expn.yo Sun Aug 29 22:00:54 1999
@@ -447,6 +447,21 @@
while in the second case, the shortest matches are taken and the
result is `tt(spy spy lispy star)'.
)
+xitem(tt(${)var(name)tt(^)var(pattern)tt(^)var(then)tt(^)var(else)tt(}))
+item(tt(${)var(name)tt(^^)var(pattern)tt(^)var(then)tt(^)var(else)tt(}))(
+If the expansion of var(name) matches the var(pattern), the var(then)
+string is substituted, otherwise the var(else) string is
+substituted. In the second form the var(pattern) is taken to be
+negated (even if the tt(EXTENDED_GLOB) option is not set. The
+var(else) string with the preceding `tt(^)' may be omitted in which
+case the expansion behaves as if var(name) were unset (or, if
+var(name) is an array, as if the element compared did not exist). In
+the var(pattern) and the var(then) string a `tt(^)' may be included by
+preceding it with two backslashes. Finally, the var(then) and
+var(else) string may consist of only a dot to make it expand to the
+original string. To make them expand to only a dot, the string
+`tt(\.)' has to be used.
+)
item(tt(${#)var(spec)tt(}))(
If var(spec) is one of the above substitutions, substitute
the length in characters of the result instead of
--
Sven Wischnowsky wischnow@informatik.hu-berlin.de
next reply other threads:[~1999-08-30 9:49 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
1999-08-30 9:49 Sven Wischnowsky [this message]
1999-08-30 10:06 ` Andrej Borsenkow
1999-08-30 10:58 ` Tanaka Akira
1999-08-30 16:05 ` Bart Schaefer
1999-08-30 16:10 ` Peter Stephenson
1999-08-30 10:38 Sven Wischnowsky
1999-08-31 13:18 ` Andrej Borsenkow
1999-08-31 8:50 Sven Wischnowsky
1999-08-31 17:47 ` Bart Schaefer
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=199908300949.LAA20865@beta.informatik.hu-berlin.de \
--to=wischnow@informatik.hu-berlin.de \
--cc=zsh-workers@sunsite.auc.dk \
/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).