Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
PATCH: new parameter expansion type?
- X-seq: zsh-workers 7540
- From: Sven Wischnowsky <wischnow@xxxxxxxxxxxxxxxxxxxxxxx>
- To: zsh-workers@xxxxxxxxxxxxxx
- Subject: PATCH: new parameter expansion type?
- Date: Mon, 30 Aug 1999 11:49:27 +0200 (MET DST)
- Mailing-list: contact zsh-workers-help@xxxxxxxxxxxxxx; run by ezmlm
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@xxxxxxxxxxxxxxxxxxxxxxx
Messages sorted by:
Reverse Date,
Date,
Thread,
Author