Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: [PATCH]: Revamped (P) expansion flag



Sorry guys,

Frank has just informed me that the patch didn't come through. So I'm
reattaching it, providing a link (http://gist.github.com/264099), and
providing a repo (git://github.com/Nomexous/zsh.git) where the changes
can be retrieved from the "pflag" branch.

Michael Hwang

On Sat, Dec 26, 2009 at 5:48 PM, Michael Hwang
<michael.a.hwang@xxxxxxxxx> wrote:
> Hello all,
>
> In my opinion, the current behavior of the P expansion flag is not
> intuitive, and possibly even buggy. For instance:
>
> % FOO='hello!'
> % REF='FOO BAR'
> % print ${(P)${REF}}
> hello!
>
> In this case, ${(P)${REF}} should expand to nothing, because 'FOO BAR'
> is not a proper parameter name. However, the current logic takes only
> as much as makes sense, and ignores the rest. This creates confusion
> with arrays:
>
> % ARRAY=(FOO CLUE SHOE)
> % FOO=zsh
> % CLUE=is
> % SHOE=awesome
> % print ${(P)${ARRAY}}
> zsh
>
> One would think that each element of the reference ARRAY would
> replaced by the value of the variable in that element. However, zsh
> will just take the value of FOO, as it's the longest string that makes
> sense as a variable name.
>
> On the more buggy-ish side:
>
> % STRING='zsh is awesome!'
> % STR='zsh sucks... :-/'
> % REF=STRING
> % print ${(P)REF[1,3]}
> zsh sucks... :-/
>
> As ${(P)REF} is really ${(P)${REF}}, one would think that that
> ${(P)REF[1,3]} would be expanded as ${(P)${REF}[1,3]}. But as you can
> see, it is instead expanded as ${(P)${REF[1,3]}}.
>
> This patch fixes all these problems. The concept of "subexpression" no
> longer applies with the P flag. Instead, one should consider whether
> or not the "inside" expression (I call it a "reference") expands to
> more than one word.
>
> Notably:
> 1.) A reference can now be a mix of plain text and expansions. For
> example, ${(P)${FOO}_BAR}.
> 2.) A reference can be quoted. Note that ${(P)"REF"} is now possible,
> and expands as if it were ${(P)"${REF}"}.
> 3.) If the reference expands to more than one word, then each element
> will be expanded to take on the value of that variable. (See below.)
>
> It is simplest with quotes:
>
> % FOO='zsh.org'
> % REF=FOO
> % print ${(P)"REF"}
> zsh.org
> % print ${(P)"${REF}"}
> zsh.org
>
> Fairly straight forward. But notice what happens when our reference
> expands to a non-valid parameter name:
>
> % FOO='merry xmas!'
> % REF='FOO FOO'
> % print ${(P)"${REF}"}
>
> % print ${(P)"REF"}
>
>
> Now try mixing (in quotes):
>
> % FOOBAR='buy champagne for new year'
> % REF=FOO
> % print ${(P)"${REF}BAR"}
> buy champagne for new year
>
> The expansion takes on the value of the variable name that the insides
> expand to.
>
> Without quotes, array references are possible.
>
> % REFS=(A B C)
> % A=1
> % B=2
> % C=3
> % print -l -- ${(P)${REFS}}
> 1
> 2
> 3
>
> It is also possible to have an array reference with an element that
> refers to an array parameter:
>
> % REFS=(A B C)
> % A=1
> % B=(2 two)
> % C=3
> % print -l -- ${(P)${REFS}}
> 1
> 2
> two
> 3
>
> And finally, mixing, non-quoted.
>
> % REFS=(FOO CLUE SHOE)
> % FOOBAR=zsh
> % CLUEBAR=is
> % SHOEBAR=awesome
> % print ${(P)${^REFS}BAR}
> zsh is awesome
>
> Note that ${(P)${REFS}BAR} would just expand to "awesome", as
> ${REFS}BAR expands to the words "FOO" "CLUE" "SHOEBAR", with FOO and
> CLUE not being set.
>
> Please test these changes. paramsubst() took a long time to
> understand, so I'm sure that I've introduced a bug or two.
>
> Michael Hwang
>


Messages sorted by: Reverse Date, Date, Thread, Author