From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27265 invoked from network); 30 Aug 1999 09:49:43 -0000 Received: from sunsite.auc.dk (130.225.51.30) by ns1.primenet.com.au with SMTP; 30 Aug 1999 09:49:43 -0000 Received: (qmail 21519 invoked by alias); 30 Aug 1999 09:49:32 -0000 Mailing-List: contact zsh-workers-help@sunsite.auc.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 7540 Received: (qmail 21512 invoked from network); 30 Aug 1999 09:49:28 -0000 Date: Mon, 30 Aug 1999 11:49:27 +0200 (MET DST) Message-Id: <199908300949.LAA20865@beta.informatik.hu-berlin.de> From: Sven Wischnowsky To: zsh-workers@sunsite.auc.dk Subject: PATCH: new parameter expansion type? 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