zsh-workers
 help / color / mirror / code / Atom feed
* Re: PATCH: param stuff and was: PATCH: 3.1.5-pws-12: _brace_parameter
@ 1999-03-16 11:50 Sven Wischnowsky
  1999-03-25 12:00 ` ${...:-...} again and subst clarification E: " Andrej Borsenkow
  0 siblings, 1 reply; 12+ messages in thread
From: Sven Wischnowsky @ 1999-03-16 11:50 UTC (permalink / raw)
  To: zsh-workers


Peter Stephenson wrote:

> >   The behavior is a bit weird, though, because `${foo-bar}' uses
> >   `multsub', too. I haven't changed the call to it, yet, so the result 
> >   is that the `bar' is broken into an array -- always. This means that 
> >   `${#:-$foo}' will yield `1' for strings and the number of elements
> >   if `bar' is `$baz' where `baz' is an array. I didn't change it
> >   because I wanted to ask what it should do first, suggestions are:
> > 
> >   1) let it treat the `bar' always as a string (i.e. let it never be
> >      split into array elements); I guess this is what most people
> >      would expect (and in the manual the thing is called `word')
> 
> Since (without shwordsplit)
> 
>   % args() { print $#; }
>   % args ${foo:-foo bar}
>   1
> 
> this is the natural thing to do.

I liked this one best, too, so the patch below implements it.

> >   2) like 1), but if combined with the `A' flag, let it be treated as
> >      an array
> 
> Some extension like this is reasonable, but the obvious candidate is
> ${(w)#:-foo bar}, which is supposed to have exactly this effect on $# for a
> string.
> 
>  % foo="foo bar"
>  % print ${(w)#foo}
>  2

Right, hadn't thought of that.

Bye
 Sven

--- os/subst.c	Mon Mar 15 10:52:31 1999
+++ Src/subst.c	Tue Mar 16 12:46:13 1999
@@ -1273,7 +1273,7 @@
 	case '-':
 	    if (vunset) {
 		val = dupstring(s);
-		multsub(&val, &aval, &isarr, NULL);
+		multsub(&val, NULL, &isarr, NULL);
 		copied = 1;
 	    }
 	    break;

--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 12+ messages in thread
* RE: PATCH: param stuff and was: PATCH: 3.1.5-pws-12: _brace_parameter
@ 1999-03-17 14:59 Sven Wischnowsky
  0 siblings, 0 replies; 12+ messages in thread
From: Sven Wischnowsky @ 1999-03-17 14:59 UTC (permalink / raw)
  To: zsh-workers


Andrej Borsenkow wrote:

> > It's actually completely predictable, once you know the rule.
> >
> 
> 'course. What I tried to explain, that there is probably a dozen of people,
> who know these rules :-( (correct me if I'm wrong)
> 
> O.K. Is it intentional?
> 
> itsrm2% foo=(axb cxd)
> itsrm2% print -l ${(s/x/)foo}
> a
> b c
> d
> 
> I won't argue, if this is correct or not. I'd just to point out
> a) if this is intentional, it should be documented
> b) it is very different from word splitting (which is referred to in
> manual). In this case, *every* resulting word is splitted:
> 
> itsrm2% foo=("a b" "c d")
> itsrm2% print -l ${=foo}
> a
> b
> c
> d

The `s' flag just says where to split -- without it is done at the
well known places, with it it is done only at the string given with
the flag.

> The second question is, what is applied first - flags or modifications?
> Again, after soms tests :-)
> 
> itsrm2% foo=(ax1 bx1)
> itsrm2% print -l ${(s/x/)foo%%1*}
> a
>  b
> 
> I don't argue, that it may be predictable. Unfortunately, I simply fail to
> find the rule ...

Modification is done first. Splitting is done at the very end, in this 
case.

So the above does: apply the `%%1*', yielding the two elements `ax'
and `bx'. The `s' flag makes them be joined as usual and then broken at 
the `x's, yielding the three elements `a', ` b', and `'. Since you
didn't enclose it in quotes that last one is removed so you can't see
it. But with `"${(@s/x/)foo%%1*}" you can. And I can almost see you
trying `print -l "${(s/x/)foo%%1*}" now ;-) Perhaps surprisingly this
gives `a' and `', because without the `(@)' flag, the array elements
are first joined and re-separated at the `x's and then the `%%1*' is
applied -- which looks a bit like a bug, but then again, maybe not.

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 12+ messages in thread
* RE: PATCH: param stuff and was: PATCH: 3.1.5-pws-12: _brace_parameter
@ 1999-03-17 10:35 Sven Wischnowsky
  0 siblings, 0 replies; 12+ messages in thread
From: Sven Wischnowsky @ 1999-03-17 10:35 UTC (permalink / raw)
  To: zsh-workers


Andrej Borsenkow wrote:

> > This ounds good, but can't be done easily (I think). The problem is
> > that in the case of a `${${...}...}' the code currently just takes the
> > inner `${...}' and calls `prefork()' on it (which does most of the
> > expansions). The result is a list of strings and no other
> > information. So here, the result of an one-element array and an scalar
> > is indistinguishable. This means that we have to say in the *outer*
> > `${...}' if we want the result of the inner one to be treated as an array.
> 
> Can I formulate it as: every substitution is done as if it were the
> top-level one?

As a wish? Yes, and as I said, I'd like to have this, too.

> >
> > The problem is that this is even more uncompatible with previous
> > version than what we have now.
> >
> 
> The problem ZSH always had (and have) is very poor documentation. I think,
> the (partial) reason for it is, nobody actually knows, how it behaves. New
> features are added on ad-hoc basis, without clear picture, how the whole
> works.

This isn't a new feature, it is an attempt at making things more
consistent, more usable. Before the patches I made There was no way to 
get the inner `${...}' be treated as an array. I found this when
implementing `_long_options' where I had an expression roughly like
`${${(P)foo}[1]}'. At one point the array whose name was stored in
`foo' happened to have only one element and suddenly I got the first
character of it, not the whole element -- and there was no way to get
it. With the changed code `${(@)${(P)foo}[1]}' this works.

> Currently there are several ZSH wizards that either know all ins and outs by
> heart or know source code. It is virtually impossible for ordinary user to
> use the power ZSH provides, because the only way to do it is by trial and
> error. You never can tell, what is a result of a (mildly complicated)
> expression simply by looking at it.
> 
> Can anybody explain (in the manual) how ZSH substitution really works?
> Returning to my example:
> 
> bor@itsrm2:~%> foo=(bar baz)
> bor@itsrm2:~%> print "${(@)${foo}[1]}"
> bar baz
> bor@itsrm2:~%> print "${${(@)foo}[1]}"
> b
> 
> Could anybody explain, why? We take the value of foo, that is (bar baz). The
> whole is quoted, so it is converted to scalar. Then, all of a sudden, this
> scalar is converted back to array! Why?  What about second? On the top
> level, (@) prevents array->scalar converting:
> 
> bor@itsrm2:~%> print -l "${(@)foo}"
> bar
> baz
> 
> But why it does not happen with inner ${(@)foo} in the above case? How can I
> take array slice in double quotes?

Because (as I said in the part of my message you quoted at the top),
the outer one doesn't say that the inenr one should be treated as an
array:

  % foo=(bar baz)
  % echo "${(@)${(@)foo}[1]}"
  bar

The behavior is consistent in that in quotes you need a `(@)' in the
outer one to get the inner one split. That's all. And, as I said in a
part of the message you didn't quote I agree that this is a bit ugly
since the `(@)' has two meanings. In my example: the inner `${...}' is 
splitted into two strings due to the `(@)' in the inner expression.
Then the `(@)' in the outer expression ensures that these strings are
treated as different elements by the subscript. And finally, if we had 
a subscript selecting more than one element or no subscript at all,
the `(@)' in the outer expression would also make the result be
treated as separate strings by the `echo'.

> That is only one example of inconsistency. The answer "it is implemented
> this way" is very weak argument. What I'd like to hear - *why* is it
> implemented this way.

Because noone yet took the time to implement it differently... But
seriously: I'm pretty sure noone would object if you (or someone else) 
changes the way the inner expression is expanded as long as it does
not differ from what we have now (or before my patches) in the simple
cases. Having this cleaned up would be nice, indeed. If I were to
implement this I'd probably play with calling `paramsubst()' directly
in `multsub()' if the things starts with `${'. And then I'd have to
think a lot about and play a lot with a inner `$(...)' where we have
the problem that they can't have flags, so with them we *will* have to 
specify in the outer `${...}' what should be done with the result of
expanding it -- if we need different ways.
I'm not that unlucky with the current behavior and too busy in other
parts of the code (you may have noticed ;-), so I won't do more work
here now...

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 12+ messages in thread
* RE: PATCH: param stuff and was: PATCH: 3.1.5-pws-12: _brace_parameter
@ 1999-03-17  9:09 Sven Wischnowsky
  1999-03-17  9:59 ` Andrej Borsenkow
  0 siblings, 1 reply; 12+ messages in thread
From: Sven Wischnowsky @ 1999-03-17  9:09 UTC (permalink / raw)
  To: zsh-workers


[The road leading to our buildin is build anew and yesterday someone
cut the cable that is our only connection to the main building. Our
system administrators say that everything is working again, although I 
haven't got all the messages from the list, yet. So this is also a test...]

Andrej Borsenkow wrote:

> > - makes the treatment of `${${...}...}' (hopefully) consistent (and
> >   this is a answer to one of Peter's questions above). The rule is:
> >   the inner `${...}' is broken into array elements if it yields more
> >   than one word and the whole thing is not quoted or if it is quoted and
> >   the `@' flag is used. I'd like to hear comments if you think that
> >   this looks and feels like the right thing.
> 
> What do you mean "one word"?

I only meant that one can't `break' *one* word into multiple `array
elements'.

> Array with single element yields one word. And
> it is very important with subscription (that behaves very funny anyway - see
> later). I prefer the case, when array yields array irrespectively of number
> of the elements.



> This is suggestion I had long ago. May be, it is the same, as you mean, but
> explicitly stated:
> 
> without qoutes
> 
>  - ${array} always gives array
>  - ${scalar} always gives scalar
>  - ${array[sub]} gives scalar
>  - ${array[sub1,sub2]} gives array (slice)
>  - ${(split)something} always gives array (may be, with single element)
>  - ${(join)something} always gives scalar
>  - $~ is considred "spliting" in this respect
> 
> in quotes
> 
>  - without (@) all yields scalar
>  - with (@) the result is array _for_the_next_level_ (for those operations,
> that yield array). The point is, the flags and subscription are applied, as
> if it were array - and the result is converted to scalar unless (@) is given
> as well.
> 
> That is, "${${(@)array}[1,3]} gives 1,2,3 elements of array as scalar. And
> "${(@)${(@)array}[1,3]}" - the same, but as three words.

This ounds good, but can't be done easily (I think). The problem is
that in the case of a `${${...}...}' the code currently just takes the 
inner `${...}' and calls `prefork()' on it (which does most of the
expansions). The result is a list of strings and no other
information. So here, the result of an one-element array and an scalar 
is indistinguishable. This means that we have to say in the *outer*
`${...}' if we want the result of the inner one to be treated as an array.

Hence these results:

> ....
> 
> bor@itsrm2:~%> foo=bar
> bor@itsrm2:~%> print ${${foo}[1]}
> bar
> 
> Sorry? Why ${foo} suddenly becomes array?
> 

1) The `${foo}' yields one word and the whole thing is not quoted, so we
get an array for it and that is then subscripted.

> bor@itsrm2:~%> print "${${foo}[1]}"
> b
> 
> With some imagination ...

2) The thing is quoted, we get a scalar and then the first char of it.

> bor@itsrm2:~%> print "${${(@)foo}[1]}"
> b
> 
> ??? Und I always believed, ${(@)foo} is array ...

3) The `(@)' has no effect because `prefork()' doesn't know about it,
gives us no information about it and since the whole thing is in
quotes, we get a scalar for the inner `${...}'.

> bor@itsrm2:~%> print "${(@)${foo}[1]}"
> bar
> 
> Poor, poor ZSH users ...

4) The `(@)' says that the `${foo}' is to be treated as an array, that is 
subscripted, and the result is broken into separate quoted words
(which you won't notice since there is only one).

Ok. Unless someone changes the code so that `multsub()' gets
information from a `paramsubst()' called via `prefork()' we are stuck
with it. But maybe we should add a new flag for the `turn the inner
<whatever> into an array', and make `(@)' work only at the outermost
level with the obvious meaning.

The problem is that this is even more uncompatible with previous
version than what we have now.

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 12+ messages in thread
* PATCH: param stuff and was: PATCH: 3.1.5-pws-12: _brace_parameter
@ 1999-03-15  9:46 Sven Wischnowsky
  1999-03-15 13:49 ` Peter Stephenson
  1999-03-16 18:07 ` Andrej Borsenkow
  0 siblings, 2 replies; 12+ messages in thread
From: Sven Wischnowsky @ 1999-03-15  9:46 UTC (permalink / raw)
  To: zsh-workers


Peter Stephenson wrote:

> This wasn't working for me.  The following version is.  Do I really need
> all those (@)?  I was too lazy to experiment.  In fact, why do I need the
> double quotes in this case?  There's no harm here in eliding empty
> elements.

In this case (and some others in the example functions) we almost
certainly don't need the double quotes (and hence no `(@)'), this is
just a habit of mine...

Over the weekend I had prepared the patch below, which

- improves the parsing of a subscript on the left hand side of an
  parameter assignment. Previously somthing like `a[${i%%\=*}]=foo'
  didn't work because the (very simple) parsing done found the `='
  inside the brackets and then tried to use that to separate the two
  sides of the assignment. For array-assignments it worked.
  The hunk in `compinit' makes use of this -- that's the place where I 
  discovered it.
- makes the treatment of `${${...}...}' (hopefully) consistent (and
  this is a answer to one of Peter's questions above). The rule is:
  the inner `${...}' is broken into array elements if it yields more
  than one word and the whole thing is not quoted or if it is quoted and
  the `@' flag is used. I'd like to hear comments if you think that
  this looks and feels like the right thing.
- allows the `${#:-foo}' Peter found. I think there is no harm in
  allowing it.
  The behavior is a bit weird, though, because `${foo-bar}' uses
  `multsub', too. I haven't changed the call to it, yet, so the result 
  is that the `bar' is broken into an array -- always. This means that 
  `${#:-$foo}' will yield `1' for strings and the number of elements
  if `bar' is `$baz' where `baz' is an array. I didn't change it
  because I wanted to ask what it should do first, suggestions are:

  1) let it treat the `bar' always as a string (i.e. let it never be
     split into array elements); I guess this is what most people
     would expect (and in the manual the thing is called `word')
  2) like 1), but if combined with the `A' flag, let it be treated as
     an array
  3) do the same as for `${${...}...}', i.e., treat it as an array
     unless the whole thing is quoted (or quoted and with the `@')
     flag

  Note that none of these will change the behavior of things that
  worked before, the difference appears only if it is combined with `#'.

Bye
 Sven

diff -u os/parse.c Src/parse.c
--- os/parse.c	Fri Mar 12 20:47:16 1999
+++ Src/parse.c	Fri Mar 12 21:31:35 1999
@@ -955,9 +955,17 @@
 	    nocorrect = 1;
 	else if (tok == ENVSTRING) {
 	    struct varasg *v = (struct varasg *)make_varnode();
+	    char *p;
 
 	    v->type = PM_SCALAR;
-	    equalsplit(v->name = tokstr, &v->str);
+	    v->name = tokstr;
+	    for (p = tokstr; *p && *p != Inbrack && *p != '='; p++);
+	    if (*p == Inbrack && !skipparens(Inbrack, Outbrack, &p) &&
+		*p == '=') {
+		*p = '\0';
+		v->str = p + 1;
+	    } else
+		equalsplit(tokstr, &v->str);
 	    addlinknode(c->vars, v);
 	    isnull = 0;
 	} else if (tok == ENVARRAY) {
diff -u os/subst.c Src/subst.c
--- os/subst.c	Fri Mar 12 20:47:16 1999
+++ Src/subst.c	Fri Mar 12 21:16:49 1999
@@ -941,6 +941,7 @@
 	} else if ((*s == '#' || *s == Pound) &&
 		   (iident(s[1])
 		    || s[1] == '*' || s[1] == Star || s[1] == '@'
+		    || s[1] == '-' || (s[1] == ':' && s[2] == '-')
 		    || (isstring(s[1]) && (s[2] == Inbrace || s[2] == Inpar))))
 	    getlen = 1 + whichlen, s++;
 	else if (*s == '~' || *s == Tilde) {
@@ -976,7 +977,7 @@
 	skipparens(*s, *s == Inpar ? Outpar : Outbrace, &s);
 	sav = *s;
 	*s = 0;
-	if (multsub(&val, (((quoted || aspar) && !nojoin) ? NULL : &aval),
+	if (multsub(&val, ((!aspar && (!quoted || nojoin)) ? &aval : NULL),
 		    &isarr, NULL) &&
 	    quoted) {
 	    isarr = -1;
diff -u oc/Core/compinit Completion/Core/compinit
--- oc/Core/compinit	Fri Mar 12 20:40:19 1999
+++ Completion/Core/compinit	Fri Mar 12 21:33:23 1999
@@ -221,12 +221,11 @@
 # set key `baz' to the empty string.
 
 compconf() {
-  local i name
+  local i
 
   for i; do
     if [[ "$i" = *\=* ]]; then
-      name="${i%%\=*}"
-      compconfig[$name]="${i#*\=}"
+      compconfig[${i%%\=*}]="${i#*\=}"
     else
       compconfig[$i]=''
     fi

--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


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

end of thread, other threads:[~1999-03-25 12:03 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-03-16 11:50 PATCH: param stuff and was: PATCH: 3.1.5-pws-12: _brace_parameter Sven Wischnowsky
1999-03-25 12:00 ` ${...:-...} again and subst clarification E: " Andrej Borsenkow
  -- strict thread matches above, loose matches on Subject: below --
1999-03-17 14:59 Sven Wischnowsky
1999-03-17 10:35 Sven Wischnowsky
1999-03-17  9:09 Sven Wischnowsky
1999-03-17  9:59 ` Andrej Borsenkow
1999-03-17 10:08   ` Peter Stephenson
1999-03-17 14:35     ` Andrej Borsenkow
1999-03-17 14:52       ` Peter Stephenson
1999-03-15  9:46 Sven Wischnowsky
1999-03-15 13:49 ` Peter Stephenson
1999-03-16 18:07 ` Andrej Borsenkow

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