* [key]+=val [not found] <CGME20170925103513eucas1p2b7d91180ccc6defe455daca9248ae222@eucas1p2.samsung.com> @ 2017-09-25 10:35 ` Peter Stephenson 2017-09-25 17:53 ` [key]+=val Bart Schaefer 0 siblings, 1 reply; 7+ messages in thread From: Peter Stephenson @ 2017-09-25 10:35 UTC (permalink / raw) To: Zsh Hackers' List I'm intending to make it so that foo+=([key]+=val) does something useful (appending to foo[key]) but foo=([key]+=val) doesn't (just creates the value), because you're starting with an empty set of values in foo so there's nothing to append to. Does this sound reasonable? It's a messy layering violation otherwise so it would need a good reason to do it differently. pws ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [key]+=val 2017-09-25 10:35 ` [key]+=val Peter Stephenson @ 2017-09-25 17:53 ` Bart Schaefer 2017-09-26 9:32 ` [key]+=val Peter Stephenson 0 siblings, 1 reply; 7+ messages in thread From: Bart Schaefer @ 2017-09-25 17:53 UTC (permalink / raw) To: Zsh Hackers' List On Mon, Sep 25, 2017 at 3:35 AM, Peter Stephenson <p.stephenson@samsung.com> wrote: > > foo=([key]+=val) > > doesn't (just creates the value), because you're starting with an empty > set of values in foo so there's nothing to append to. Does this sound > reasonable? It's a messy layering violation otherwise so it would need > a good reason to do it differently. Ksh says: $ typeset -A foo $ foo=([samekey]+=val [samekey]+=ue [samekey]+=grows) $ typeset -p foo typeset -A foo=([samekey]=valuegrows) ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [key]+=val 2017-09-25 17:53 ` [key]+=val Bart Schaefer @ 2017-09-26 9:32 ` Peter Stephenson 2017-09-26 17:28 ` [key]+=val Bart Schaefer 0 siblings, 1 reply; 7+ messages in thread From: Peter Stephenson @ 2017-09-26 9:32 UTC (permalink / raw) To: Zsh Hackers' List On Mon, 25 Sep 2017 10:53:25 -0700 Bart Schaefer <schaefer@brasslantern.com> wrote: > On Mon, Sep 25, 2017 at 3:35 AM, Peter Stephenson > <p.stephenson@samsung.com> wrote: > > > > foo=([key]+=val) > > > > doesn't (just creates the value), because you're starting with an empty > > set of values in foo so there's nothing to append to. Does this sound > > reasonable? It's a messy layering violation otherwise so it would need > > a good reason to do it differently. > > Ksh says: > > $ typeset -A foo > $ foo=([samekey]+=val [samekey]+=ue [samekey]+=grows) > $ typeset -p foo > typeset -A foo=([samekey]=valuegrows) That's actually not too hard, and in fact it helped me think through a slightly neater (and less leak-prone) way of updating normal arrays. What I was worried about was starting off in a context where we're creating a new array except we're not really creating a new array because we're digging into an old one... in this case, we're always referring to elements in the array we're creating, which I can live with. Here's what I've got. I haven't complicated the documentation by noting the edge case you mentioned. pws diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo index 430f097..a71dc66 100644 --- a/Doc/Zsh/params.yo +++ b/Doc/Zsh/params.yo @@ -145,7 +145,8 @@ indent(var(name)tt(+=LPAR())tt([)var(key)tt(]=)var(value) ...tt(RPAR())) In the second form var(key) may specify an existing index as well as an index off the end of the old array; any existing value is overwritten by -var(value). +var(value). Also, it is possible to use tt([)var(key)tt(]+=)var(value) +to append to the existing value at that key. Within the parentheses on the right hand side of either form of the assignment, newlines and semicolons are treated the same as white space, @@ -180,7 +181,9 @@ indent(var(name)tt(+=LPAR())var(key) var(value) ...tt(RPAR())) indent(var(name)tt(+=LPAR())tt([)var(key)tt(]=)var(value) ...tt(RPAR())) This adds a new key/value pair if the key is not already present, and -replaces the value for the existing key if it is. +replaces the value for the existing key if it is. In the second +form it is also possible to use tt([)var(key)tt(]+=)var(value) to +append to the existing value at that key. To create an empty array (including associative arrays), use one of: ifzman() diff --git a/Src/params.c b/Src/params.c index 4d4d080..3236f71 100644 --- a/Src/params.c +++ b/Src/params.c @@ -3208,13 +3208,15 @@ assignaparam(char *s, char **val, int flags) * This is an ordinary array with key / value pairs. */ int maxlen, origlen, nextind; - char **fullval; + char **fullval, **origptr; zlong *subscripts = (zlong *)zhalloc(arrlen(val) * sizeof(zlong)); zlong *iptr = subscripts; if (flags & ASSPM_AUGMENT) { - maxlen = origlen = arrlen(v->pm->gsu.a->getfn(v->pm)); + origptr = v->pm->gsu.a->getfn(v->pm); + maxlen = origlen = arrlen(origptr); } else { maxlen = origlen = 0; + origptr = NULL; } nextind = 0; for (aptr = val; *aptr; ) { @@ -3245,25 +3247,36 @@ assignaparam(char *s, char **val, int flags) } fullval[maxlen] = NULL; if (flags & ASSPM_AUGMENT) { - char **srcptr = v->pm->gsu.a->getfn(v->pm); + char **srcptr = origptr; for (aptr = fullval; aptr <= fullval + origlen; aptr++) { - *aptr = ztrdup(*srcptr); + *aptr = ztrdup(*srcptr); srcptr++; } } iptr = subscripts; nextind = 0; for (aptr = val; *aptr; ++aptr) { + char *old; if (**aptr == Marker) { + int augment = ((*aptr)[1] == '+'); zsfree(*aptr); zsfree(*++aptr); /* Index, no longer needed */ - fullval[*iptr] = *++aptr; + old = fullval[*iptr]; + if (augment && old) { + fullval[*iptr] = bicat(old, *++aptr); + zsfree(*aptr); + } else { + fullval[*iptr] = *++aptr; + } nextind = *iptr + 1; ++iptr; } else { + old = fullval[nextind]; fullval[nextind] = *aptr; ++nextind; } + if (old) + zsfree(old); /* aptr now on value in both cases */ } if (*aptr) { /* Shouldn't be possible */ @@ -3828,8 +3841,20 @@ arrhashsetfn(Param pm, char **val, int flags) ht = paramtab = newparamtable(17, pm->node.nam); } for (aptr = val; *aptr; ) { - if (**aptr == Marker) + int eltflags = 0; + if (**aptr == Marker) { + /* Either all elements have Marker or none. Checked in caller. */ + if ((*aptr)[1] == '+') { + /* Actually, assignstrvalue currently doesn't handle this... */ + eltflags = ASSPM_AUGMENT; + /* ...so we'll use the trick from setsparam(). */ + v->start = INT_MAX; + } else { + v->start = 0; + } + v->end = -1; zsfree(*aptr++); + } /* The parameter name is ztrdup'd... */ v->pm = createparam(*aptr, PM_SCALAR|PM_UNSET); /* @@ -3840,7 +3865,7 @@ arrhashsetfn(Param pm, char **val, int flags) v->pm = (Param) paramtab->getnode(paramtab, *aptr); zsfree(*aptr++); /* ...but we can use the value without copying. */ - setstrvalue(v, *aptr++); + assignstrvalue(v, *aptr++, eltflags); } paramtab = opmtab; pm->gsu.h->setfn(pm, ht); diff --git a/Src/subst.c b/Src/subst.c index 55b5444..eef0dc7 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -53,16 +53,25 @@ keyvalpairelement(LinkList list, LinkNode node) if ((start = (char *)getdata(node)) && start[0] == Inbrack && (end = strchr(start+1, Outbrack)) && - end[1] == Equals) { + /* ..]=value or ]+=Value */ + (end[1] == Equals || + (end[1] == '+' && end[2] == Equals))) { static char marker[2] = { Marker, '\0' }; + static char marker_plus[3] = { Marker, '+', '\0' }; *end = '\0'; dat = start + 1; singsub(&dat); untokenize(dat); - setdata(node, marker); - node = insertlinknode(list, node, dat); - dat = end + 2; + if (end[1] == '+') { + setdata(node, marker_plus); + node = insertlinknode(list, node, dat); + dat = end + 3; + } else { + setdata(node, marker); + node = insertlinknode(list, node, dat); + dat = end + 2; + } singsub(&dat); untokenize(dat); return insertlinknode(list, node, dat); diff --git a/Src/zsh.h b/Src/zsh.h index b6e2001..c1138bf 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -228,7 +228,9 @@ struct mathfunc { * - In pattern character arrays as guaranteed not to mark a character in * a string. * - In assignments with the ASSPM_KEY_VALUE flag set in order to - * mark that there is a key / value pair following. + * mark that there is a key / value pair following. If this + * comes from [key]=value the Marker is followed by a null; + * if from [key]+=value the Marker is followed by a '+' then a null. * All the above are local uses --- any case where the Marker has * escaped beyond the context in question is an error. */ diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index abac8f7..4f8e76a 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -2302,3 +2302,39 @@ F:behavior, see http://austingroupbugs.net/view.php?id=888 >KVA2two >KVA3three >* + + local -a keyvalarray + keyvalarray=(1 2 3) + keyvalarray+=([1]+=a [2]=b) + print $keyvalarray +0:Append to element(s) of array +>1a b 3 + + local -A keyvalhash + keyvalhash=([a]=a [b]=b [c]=c) + keyvalhash+=([a]+=yee [b]=ee) + local key val + for key in "${(ok)keyvalhash[@]}"; do + val=${keyvalhash[$key]} + print -r -- $key $val + done +0:Append to element(s) of associative array +>a ayee +>b ee +>c c + + local -A keyvalarray + keyvalarray=([1]=who [2]=anyway [1]+=is [1]+=that [1]+=mysterious [1]+=man) + print -rl -- ${(kv)keyvalarray} +0:Append to element of associative array on creation +>1 +>whoisthatmysteriousman +>2 +>anyway + + local -A keyvalhash + keyvalhash=([one]=hows [one]+=your [one]+=father [one]+=today) + print -rl -- ${(kv)keyvalhash} +0:Append to element of associative array on creation +>one +>howsyourfathertoday ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [key]+=val 2017-09-26 9:32 ` [key]+=val Peter Stephenson @ 2017-09-26 17:28 ` Bart Schaefer 2017-09-27 8:42 ` [key]+=val Peter Stephenson 0 siblings, 1 reply; 7+ messages in thread From: Bart Schaefer @ 2017-09-26 17:28 UTC (permalink / raw) To: Zsh Hackers' List On Sep 26, 10:32am, Peter Stephenson wrote: } } + local -A keyvalarray } + keyvalarray=([1]=who [2]=anyway [1]+=is [1]+=that [1]+=mysterious [1]+=man) } + print -rl -- ${(kv)keyvalarray} } +0:Append to element of associative array on creation } +>1 } +>whoisthatmysteriousman } +>2 } +>anyway } + } + local -A keyvalhash } + keyvalhash=([one]=hows [one]+=your [one]+=father [one]+=today) } + print -rl -- ${(kv)keyvalhash} } +0:Append to element of associative array on creation } +>one } +>howsyourfathertoday Did you intend for both of those tests to use associative arrays? ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [key]+=val 2017-09-26 17:28 ` [key]+=val Bart Schaefer @ 2017-09-27 8:42 ` Peter Stephenson 2017-09-27 8:59 ` [key]+=val Peter Stephenson 2017-09-27 16:22 ` [key]+=val Peter Stephenson 0 siblings, 2 replies; 7+ messages in thread From: Peter Stephenson @ 2017-09-27 8:42 UTC (permalink / raw) To: Zsh Hackers' List On Tue, 26 Sep 2017 10:28:52 -0700 Bart Schaefer <schaefer@brasslantern.com> wrote: > Did you intend for both of those tests to use associative arrays? No, I've fixed the first test and submitted this. Thanks pws ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [key]+=val 2017-09-27 8:42 ` [key]+=val Peter Stephenson @ 2017-09-27 8:59 ` Peter Stephenson 2017-09-27 16:22 ` [key]+=val Peter Stephenson 1 sibling, 0 replies; 7+ messages in thread From: Peter Stephenson @ 2017-09-27 8:59 UTC (permalink / raw) To: Zsh Hackers' List I think I'm basically done with the [key]=val syntax. One further possible change might be to enforce the use of that syntax for associative (but not normal) arrays when KSH_ARRAYS is set. That might cause problems with some half-converted scripts. It doesn't seem worth a separate option just for that. pws ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [key]+=val 2017-09-27 8:42 ` [key]+=val Peter Stephenson 2017-09-27 8:59 ` [key]+=val Peter Stephenson @ 2017-09-27 16:22 ` Peter Stephenson 1 sibling, 0 replies; 7+ messages in thread From: Peter Stephenson @ 2017-09-27 16:22 UTC (permalink / raw) To: Zsh Hackers' List Some tests for normal arrays with KSH_ARRAYS set. diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index d6ed648..5ffaaa1 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -2231,6 +2231,20 @@ F:behavior, see http://austingroupbugs.net/view.php?id=888 >two >three + (setopt KSH_ARRAYS + local keyvalarray + keyvalarray=([0]=one [2]=three) + print -l "${keyvalarray[@]}" + keyvalarray+=([1]=two) + print -l "${keyvalarray[@]}") +0:[key]=val for normal arrays with KSH_ARRAYS +>one +> +>three +>one +>two +>three + typeset -A keyvalhash touch foo Xnot_globbedX key="another key" val="another value" @@ -2258,6 +2272,17 @@ F:behavior, see http://austingroupbugs.net/view.php?id=888 >7 >1 2 3 4 5 6 7 + (setopt KSH_ARRAYS + local keyvalarray + keyvalarray=(1 2 3) + keyvalarray+=([4]=5 [6]=7) + keyvalarray+=([3]=4 [5]=6) + print ${#keyvalarray[*]} + print ${keyvalarray[*]}) +0:append to normal array using [key]=val with KSH_ARRAYS +>7 +>1 2 3 4 5 6 7 + local -A keyvalhash keyvalhash=(['1first element!']=first' 'value ["2second element?"]=second" "value @@ -2288,6 +2313,19 @@ F:behavior, see http://austingroupbugs.net/view.php?id=888 >new_sixth >seventh + (setopt KSH_ARRAYS + local keyvalarray + keyvalarray=(first [1]=second third [5]=sixth seventh [4]=fifth new_sixth) + print -l "${keyvalarray[@]}") +0:mixed syntax [key]=val with normal arrays with KSH_ARRAYS +>first +>second +>third +> +>fifth +>new_sixth +>seventh + local -A keyvalhash keyvalhash=(1 one [2]=two 3 three) 1:Mixed syntax with [key]=val not allowed for hash. @@ -2303,6 +2341,17 @@ F:behavior, see http://austingroupbugs.net/view.php?id=888 >KVA3three >* + (setopt KSH_ARRAYS + touch KVA1one KVA2two KVA3three + local keyvalarray + keyvalarray=(KVA* [3]=*) + print -l "${keyvalarray[@]}") +0:Globbing in non-[key]=val parts of mixed syntax with KSH_ARRAYS +>KVA1one +>KVA2two +>KVA3three +>* + local -a keyvalarray keyvalarray=(1 2 3) keyvalarray+=([1]+=a [2]=b) @@ -2310,6 +2359,14 @@ F:behavior, see http://austingroupbugs.net/view.php?id=888 0:Append to element(s) of array >1a b 3 + (setopt KSH_ARRAYS + local -a keyvalarray + keyvalarray=(1 2 3) + keyvalarray+=([0]+=a [1]=b) + print ${keyvalarray[*]}) +0:Append to element(s) of array with KSH_ARRAYS +>1a b 3 + local -A keyvalhash keyvalhash=([a]=a [b]=b [c]=c) keyvalhash+=([a]+=yee [b]=ee) @@ -2326,7 +2383,15 @@ F:behavior, see http://austingroupbugs.net/view.php?id=888 local -a keyvalarray keyvalarray=([1]=who [2]=anyway [1]+=is [1]+=that [1]+=mysterious [1]+=man) print -rl -- "${keyvalarray[@]}" -0:Append to element of associative array on creation +0:Append to element of array on creation +>whoisthatmysteriousman +>anyway + + (setopt KSH_ARRAYS + local -a keyvalarray + keyvalarray=([0]=who [1]=anyway [0]+=is [0]+=that [0]+=mysterious [0]+=man) + print -rl -- "${keyvalarray[@]}") +0:Append to element of array on creation with KSH_ARRAYS >whoisthatmysteriousman >anyway ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2017-09-27 16:22 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- [not found] <CGME20170925103513eucas1p2b7d91180ccc6defe455daca9248ae222@eucas1p2.samsung.com> 2017-09-25 10:35 ` [key]+=val Peter Stephenson 2017-09-25 17:53 ` [key]+=val Bart Schaefer 2017-09-26 9:32 ` [key]+=val Peter Stephenson 2017-09-26 17:28 ` [key]+=val Bart Schaefer 2017-09-27 8:42 ` [key]+=val Peter Stephenson 2017-09-27 8:59 ` [key]+=val Peter Stephenson 2017-09-27 16:22 ` [key]+=val Peter Stephenson
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).