From 5eb53bf88d3153510f0a5304e921b46419fe5721 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sun, 22 Apr 2012 18:10:42 +0000 Subject: 30431 with typo in _typeset fix: add ${...:|...} and ${...:*...} operators, as documented --- ChangeLog | 10 +++++++++- Completion/Zsh/Command/_typeset | 6 ++++-- Doc/Zsh/expn.yo | 13 +++++++++++++ Src/params.c | 2 +- Src/subst.c | 43 +++++++++++++++++++++++++++++++++++++++++ Test/D04parameter.ztst | 23 ++++++++++++++++++++++ 6 files changed, 93 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index ea0a02f06..64d199b15 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2012-04-22 Peter Stephenson + + * 30431 (typo in _typeset fixed): + Completion/Zsh/Command/_typeset, Doc/Zsh/expn.yo, ASrc/params.c, + Src/subst.c, Test/D04parameter.ztst: add ${...:|...} and + ${...:*...} operators for removal or inclusion of results + by array element. + 2012-04-21 Barton E. Schaefer * 30433: Src/hist.c: double backslash is not line continuation. @@ -16223,5 +16231,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5636 $ +* $Revision: 1.5637 $ ***************************************************** diff --git a/Completion/Zsh/Command/_typeset b/Completion/Zsh/Command/_typeset index 9c9165563..d44783d64 100644 --- a/Completion/Zsh/Command/_typeset +++ b/Completion/Zsh/Command/_typeset @@ -75,9 +75,11 @@ if [[ "$state" = vars_eq ]]; then if (( $+opt_args[-w] ));then _wanted files expl 'zwc file' _files -g '*.zwc(-.)' elif [[ $service = autoload || -n $opt_args[(i)-[uU]] ]]; then - args=(${^fpath}/*(:t)) + args=(${^fpath}/*(-.:t)) # Filter out functions already loaded or marked for autoload. - args=(${args:#(${(kj.|.)~functions})}) + local -a funckeys + funckeys=(${(k)functions}) + args=(${args:|funckeys}) _wanted functions expl 'shell function' compadd -a args else _functions diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 25c44f331..dbbdc5073 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -604,6 +604,19 @@ If var(name) is an array the matching array elements are removed (use the `tt((M))' flag to remove the non-matched elements). ) +item(tt(${)var(name)tt(:|)var(arrayname)tt(}))( +If var(arrayname) is the name (N.B., not contents) of an array +variable, then any elements contained in var(arrayname) are removed +from the substitution of var(name). If the substitution is scalar, +either because var(name) is a scalar variable or the expression is +quoted, the elements of var(arrayname) are instead tested against the +entire expression. +) +item(tt(${)var(name)tt(:*)var(arrayname)tt(}))( +Similar to the preceding subsitution, but in the opposite sense, +so that entries present in both the original substitution and as +elements of var(arrayname) are retained and others removed. +) xitem(tt(${)var(name)tt(:)var(offset)tt(})) item(tt(${)var(name)tt(:)var(offset)tt(:)var(length)tt(}))( This syntax gives effects similar to parameter subscripting diff --git a/Src/params.c b/Src/params.c index b18fb90a6..24062e03a 100644 --- a/Src/params.c +++ b/Src/params.c @@ -3493,7 +3493,7 @@ arrayuniq_freenode(HashNode hn) } /**/ -static HashTable +HashTable newuniqtable(zlong size) { HashTable ht = newhashtable((int)size, "arrayuniq", NULL); diff --git a/Src/subst.c b/Src/subst.c index dac536f14..82645ccfa 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -2876,6 +2876,49 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) } break; } + } else if (inbrace && (*s == '|' || *s == Bar || + *s == '*' || *s == Star)) { + int intersect = (*s == '*' || *s == Star); + char **compare = getaparam(++s), **ap, **apsrc; + if (compare) { + HashTable ht = newuniqtable(arrlen(compare)+1); + int present; + for (ap = compare; *ap; ap++) + (void)addhashnode2(ht, *ap, (HashNode) + zhalloc(sizeof(struct hashnode))); + if (!vunset && isarr) { + if (!copied) { + aval = arrdup(aval); + copied = 1; + } + for (ap = apsrc = aval; *apsrc; apsrc++) { + untokenize(*apsrc); + present = (gethashnode2(ht, *apsrc) != NULL); + if (intersect ? present : !present) { + if (ap != apsrc) { + *ap = *apsrc; + } + ap++; + } + } + *ap = NULL; + } else { + if (vunset) { + if (unset(UNSET)) { + *idend = '\0'; + zerr("%s: parameter not set", idbeg); + deletehashtable(ht); + return NULL; + } + val = dupstring(""); + } else { + present = (gethashnode2(ht, val) != NULL); + if (intersect ? !present : present) + val = dupstring(""); + } + } + deletehashtable(ht); + } } else { /* no ${...=...} or anything, but possible modifiers. */ /* * Handler ${+...}. TODO: strange, why do we handle this only diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index 30e4ba0ab..d5a6a403e 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -169,6 +169,29 @@ >a-string-with-slashes >a-string-with-slashes + args=('one' '#foo' '(bar' "'three'" two) + mod=('#foo' '(bar' "'three'" sir_not_appearing_in_this_film) + print ${args:|mod} + print ${args:*mod} + print "${(@)args:|mod}" + print "${(@)args:*mod}" + args=(two words) + mod=('one word' 'two words') + print "${args:|mod}" + print "${args:*mod}" + scalar='two words' + print ${scalar:|mod} + print ${scalar:*mod} +0:"|" array exclusion and "*" array intersection +>one two +>#foo (bar 'three' +>one two +>#foo (bar 'three' +> +>two words +> +>two words + str1='twocubed' array=(the number of protons in an oxygen nucleus) print $#str1 ${#str1} "$#str1 ${#str1}" $#array ${#array} "$#array ${#array}" -- cgit 1.4.1