zsh-workers
 help / color / mirror / code / Atom feed
* Re: [PATCH] Forcing array interpretation in parameter substitution
@ 2017-04-13 16:29 Sebastian Gniazdowski
  2017-04-13 21:03 ` Bart Schaefer
  0 siblings, 1 reply; 3+ messages in thread
From: Sebastian Gniazdowski @ 2017-04-13 16:29 UTC (permalink / raw)
  To: zsh-workers

Just realized that this isn't a "5.0.2" or so thing. Great commit really, it allows to index (z) result, or (s::) result, when there is no split and instead of array, a string is returned:

>: var="abc"; echo ${${(z)var}[1]}; echo ${${(Az)var}[1]} "<- so (A) does help"
a
abc <- so (A) does help

I wonder if there can be any workaround for older versions, tried (@z) or silly (0z) etc., and no make-array effect occurs.

--
Sebastian Gniazdowski
psprint /at/ zdharma.org


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] Forcing array interpretation in parameter substitution
  2017-04-13 16:29 [PATCH] Forcing array interpretation in parameter substitution Sebastian Gniazdowski
@ 2017-04-13 21:03 ` Bart Schaefer
  0 siblings, 0 replies; 3+ messages in thread
From: Bart Schaefer @ 2017-04-13 21:03 UTC (permalink / raw)
  To: zsh-workers

On Apr 13,  6:29pm, Sebastian Gniazdowski wrote:
}
} Just realized that this isn't a "5.0.2" or so thing.
} 
} I wonder if there can be any workaround for older versions

This is sort of ugly, because (z) itself is failing to return an array
when the string to be split has only one word.  The workaround described
in users/22497 does the right thing for (s::) but not for (z).

For (z) you need to force array-ness by splitting some other way and
then also add (z).  E.g.:

var="abc"; echo ${${(Afz)reply::=$var}[1]}

Of course if there are embedded newlines that are quoted, (f) will
break them incorrectly, so you need something more like

echo ${${(Aps:\0:z)reply::=$var}[1]}

Which still breaks if you have embedded NUL bytes in $var, but ...


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH] Forcing array interpretation in parameter substitution
@ 2017-02-25 22:47 Bart Schaefer
  0 siblings, 0 replies; 3+ messages in thread
From: Bart Schaefer @ 2017-02-25 22:47 UTC (permalink / raw)
  To: zsh-workers

} The problem is that nesting ${${...}} "wants" to treat the inner ${...}
} as a scalar, and will do so unless something else forces it to be an
} array.  (f) doesn't accomplish that because $(dirs -v) produces only
} one line of output with the final newline stripped, so there is nothing
} for (f) to split on.  (@) won't accomplish it because it only means
} that things that are already arrays should remain so.
} 
} So what can be done to force interpretation as an array here?

I occurred to me in one of those "why didn't we do this before?" moments
that there's no reason the (A) flag has to have meaning only in context
of ${name=value}.

I haven't found anything obviously wrong with the following patch and
all tests still pass.


diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo
index 43ecd31..402afdb 100644
--- a/Doc/Zsh/expn.yo
+++ b/Doc/Zsh/expn.yo
@@ -955,15 +955,25 @@ This is distinct from em(field splitting) by the tt(f), tt(s)
 or tt(z) flags, which still applies within each array element.
 )
 item(tt(A))(
-Assign as an array parameter with `tt(${)...tt(=)...tt(})',
+Convert the subsitution into an array expression, even if it otherwise
+would be scalar.  This has lower precedence than subscripting, so one
+level of nested expansion is required in order that subscripts apply
+to array elements.  Thus tt(${${LPAR()A)tt(RPAR())var(name)tt(}[1]})
+yields the full value of var(name) when var(name) is scalar.
+
+This assigns an array parameter with `tt(${)...tt(=)...tt(})',
 `tt(${)...tt(:=)...tt(})' or `tt(${)...tt(::=)...tt(})'.
-If this flag is repeated (as in `tt(AA)'), assign an associative
+If this flag is repeated (as in `tt(AA)'), assigns an associative
 array parameter.  Assignment is made before sorting or padding;
 if field splitting is active, the var(word) part is split before
 assignment.  The var(name) part may be a subscripted range for
 ordinary arrays; when assigning an associative array, the var(word)
 part em(must) be converted to an array, for example by using
 `tt(${(AA)=)var(name)tt(=)...tt(})' to activate field splitting.
+
+Surrounding context such as additional nesting or use of the value
+in a scalar assignment may cause the array to be joined back into
+a single string again.
 )
 item(tt(a))(
 Sort in array index order; when combined with `tt(O)' sort in reverse
diff --git a/Src/subst.c b/Src/subst.c
index 4df53bd..02dbe28 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -2902,6 +2902,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
 		    } else
 			setaparam(idbeg, a);
 		    isarr = 1;
+		    arrasg = 0;
 		} else {
 		    untokenize(val);
 		    setsparam(idbeg, ztrdup(val));
@@ -3784,6 +3785,16 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
 	insertlinknode(l, n, dupstring(fstr)); /* appended, no incnode */
 	*fstr = '\0';
     }
+    if (arrasg && !isarr) {
+	/*
+	 * Caller requested this be forced to an array even if scalar.
+	 * Any point in distinguishing arrasg == 2 (assoc array) here?
+	 */
+	l->list.flags |= LF_ARRAY;
+	aval = hmkarray(val);
+	isarr = 1;
+	DPUTS(!val, "value is NULL in paramsubst, empty array");
+    }
     if (isarr) {
 	char *x;
 	char *y;


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2017-04-13 21:03 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-13 16:29 [PATCH] Forcing array interpretation in parameter substitution Sebastian Gniazdowski
2017-04-13 21:03 ` Bart Schaefer
  -- strict thread matches above, loose matches on Subject: below --
2017-02-25 22:47 Bart Schaefer

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).