Zparseopts with associative array in older version of zsh

zsh

I am confused by the differing behavior of zparseopts in two different versions of zsh. Basically I am trying to set a list of default option values in an associative array and overwrite these defaults with any options specified on the command line. The below code works well for zsh 5.0.6 but behaves oddly for 4.3.6– specifically, in zsh 4.3.6, my whole array of defaults is overwritten if a single key is overwritten.

myscript

typeset -A opts
opts=(
--opt1 a
--opt2 b
)

zparseopts -A opts -K -- -opt1: -opt2:
echo ${(k)opts}

Running the script

$ myscript 
--opt1 --opt2  # both zsh 4.3.6 and 5.0.6

$ myscript --opt1 x
--opt1 --opt2  # zsh 5.0.6; element of array is replaced
--opt1         # zsh 4.3.6; adding an element overwrites the whole array, no more opt2

This behavior is confusing because 4.3.6 and 5.0.6 have identical entries for the -K option to zparseopts:

-K With this option, the arrays specified with the -a and -A
options and with the `=array' forms are kept unchanged when none
of the specs for them is used. This allows assignment of
default values to them before calling zparseopts.

Best Answer

Replace the last line of your script with echo ${(kv)opts}. Running with 4.3.6 and 5.0.6 should show that 4.3.6 interprets -K to reset opts if any options are given, while 5.0.6 only resets opts[--opt1] when --opt1 is used (leaving --opt2 or any other entry alone).

(Note this appeared to change sometime between 5.0.2 and 5.0.6; you might want to ask on the zsh-workers mailing list to confirm.)=

Related Question