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