1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-01-01 05:16:05 +01:00

32949 (wip 32928, 32937): Add :^ syntax for zipping two arrays

This commit is contained in:
Mikael Magnusson 2014-07-31 19:39:26 +02:00
parent 1f396dbe25
commit b8751cb9d7
4 changed files with 166 additions and 0 deletions

View file

@ -1,3 +1,8 @@
2014-08-04 Mikael Magnusson <mikachu@gmail.com>
* 32949 (wip 32928, 32937): Doc/Zsh/expn.yo, Src/subst.c,
Test/D04parameter.ztst: Add :^ and :^^ for zipping arrays.
2014-08-03 Peter Stephenson <p.w.stephenson@ntlworld.com>
* Doc/Zsh/builtins.yo: 32944: Doc/Zsh/builtins.yo: read -qs is

View file

@ -636,6 +636,30 @@ 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(arrayname)tt(}))
item(tt(${)var(name)tt(:^^)var(arrayname)tt(}))(
Zips two arrays, such that the output array is twice as long as the
shortest (longest for `tt(:^^)') of tt(name) and tt(arrayname), with
the elements alternatingly being picked from them. For `tt(:^)', if one
of the input arrays is longer, the output will stop when the end of the
shorter array is reached. Thus,
example(a=(1 2 3 4); b=(a b); print ${a:^b})
will output `tt(1 a 2 b)'. For `tt(:^^)', then the input is repeated
until all of the longer array has been used up and the above will output
`tt(1 a 2 b 3 a 4 b)'.
Either or both inputs may be a scalar, they will be treated as an array
of length 1 with the scalar as the only element. If either array is empty,
the other array is output with no extra elements inserted.
Currently the following code will output `tt(a b)' and `tt(1)' as two separate
elements, which can be unexpected. The second print provides a workaround which
should continue to work if this is changed.
example(a=(a b); b=(1 2); print -l "${a:^b}"; print -l "${${a:^b}}")
)
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

View file

@ -2878,6 +2878,67 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
}
break;
}
} else if (inbrace && (*s == '^' || *s == Hat)) {
char **zip, **ap, **apsrc;
int shortest = 1;
++s;
if (*s == '^' || *s == Hat) {
shortest = 0;
++s;
}
if (*itype_end(s, IIDENT, 0)) {
untokenize(s);
zerr("not an identifier: %s", s);
return NULL;
}
if (vunset) {
if (unset(UNSET)) {
*idend = '\0';
zerr("%s: parameter not set", idbeg);
return NULL;
}
val = dupstring("");
} else {
char *sval;
zip = getaparam(s);
if (!zip) {
sval = getsparam(s);
if (sval)
zip = hmkarray(sval);
}
if (!isarr) aval = mkarray(val);
if (zip) {
char **out;
int alen, ziplen, outlen, i = 0;
alen = arrlen(aval);
ziplen = arrlen(zip);
outlen = shortest ^ (alen > ziplen) ? alen : ziplen;
if (!shortest && (alen == 0 || ziplen == 0)) {
if (ziplen)
aval = arrdup(zip);
} else {
out = zhalloc(sizeof(char *) * (2 * outlen + 1));
while (i < outlen) {
if (copied)
out[i*2] = aval[i % alen];
else
out[i*2] = dupstring(aval[i % alen]);
out[i*2+1] = dupstring(zip[i % ziplen]);
i++;
}
out[i*2] = NULL;
aval = out;
copied = 1;
isarr = 1;
}
} else {
if (unset(UNSET)) {
zerr("%s: parameter not set", s);
return NULL;
}
val = dupstring("");
}
}
} else if (inbrace && (*s == '|' || *s == Bar ||
*s == '*' || *s == Star)) {
int intersect = (*s == '*' || *s == Star);

View file

@ -1560,3 +1560,79 @@
0:Intersection and disjunction with empty parameters
>0
>0
foo=(a b c)
bar=(1 2 3)
print ${foo:^bar}
print ${foo:^^bar}
foo=(a b c d)
bar=(1 2)
print ${foo:^bar}
print ${foo:^^bar}
foo=('a a' b)
bar=(1 '2 2')
print -l "${foo:^bar}"
print -l "${(@)foo:^bar}"
0:Zipping arrays, correct output
>a 1 b 2 c 3
>a 1 b 2 c 3
>a 1 b 2
>a 1 b 2 c 1 d 2
# maybe this should be changed to output "a a b 1"
>a a b
>1
>a a
>1
>b
>2 2
foo=(a b c)
bar=()
print ${foo:^bar}
print ${foo:^^bar}
print ${bar:^foo}
print ${bar:^^foo}
print ${bar:^bar}
print ${bar:^^bar}
0:Zipping arrays, one or both inputs empty
>
>a b c
>
>a b c
>
>
foo=text
bar=()
print ${foo:^bar}
print ${bar:^^foo}
bar=other
print ${foo:^bar}
bar=(array elements)
print ${foo:^bar}
print ${foo:^^bar}
print ${bar:^foo}
print ${bar:^^foo}
0:Zipping arrays, scalar input
>
>text
>text other
>text array
>text array text elements
>array text
>array text elements text
foo=(a b c)
print ${foo:^^^bar}
1:Zipping arrays, parsing
?(eval):2: not an identifier: ^bar
(setopt nounset
print ${foo:^noexist})
1:Zipping arrays, NO_UNSET part 1
?(eval):2: noexist: parameter not set
(setopt nounset
print ${noexist:^foo})
1:Zipping arrays, NO_UNSET part 2
?(eval):2: noexist: parameter not set