# Test zparseopts from the zsh/zutil module %prep if zmodload zsh/zutil 2> /dev/null; then # Produce a string representing an associative array ordered by its keys order_assoc() { local -a _arr for 2 in "${(@kP)1}"; do _arr+=( "${(q-)2} ${(q-)${(P)1}[$2]}" ) done print -r - ${(j< >)${(@o)_arr}} } else ZTST_unimplemented="can't load the zsh/zutil module for testing" fi %test () { zparseopts -D -F ''; print -r - ${(q+)@} } - foo () { zparseopts -D -F ''; print -r - ${(q+)@} } -x () { zparseopts -D -F - ''; print -r - ${(q+)@} } - foo () { zparseopts -D -F - ''; print -r - ${(q+)@} } -x () { zparseopts -D -F - -; print -r - ${(q+)@} } - foo () { zparseopts -D -F - -; print -r - ${(q+)@} } -x 0:zparseopts with empty option spec (no options recognised) >foo ?(anon): bad option: -x >-x >foo ?(anon): bad option: -x >-x >foo ?(anon): bad option: -x >-x () { zparseopts -F -- } -x () { zparseopts -F - } -x () { zparseopts -F - a } -x () { zparseopts -F - a } -x () { zparseopts -F a } -x 1:zparseopts without option specs, without array ?(anon):zparseopts: missing option descriptions ?(anon):zparseopts: missing option descriptions ?(anon):zparseopts: no default array defined: a ?(anon):zparseopts: no default array defined: a ?(anon):zparseopts: no default array defined: a () { local -a optv zparseopts -a optv - a b: c:- z print -r - ret: $?, optv: $optv, argv: $argv } -ab1 -c -d -e -z 0:zparseopts -a >ret: 0, optv: -a -b 1 -c-d, argv: -ab1 -c -d -e -z () { local -A opts zparseopts -A opts - a b: c:- z print -r - ret: $?, opts: "$( order_assoc opts )", argv: $argv } -ab1 -c -d -e -z 0:zparseopts -A >ret: 0, opts: -a '' -b 1 -c -d, argv: -ab1 -c -d -e -z () { local -a optv zparseopts -D -a optv - a b: c:- z print -r - ret: $?, optv: $optv, argv: $argv } -ab1 -c -d -e -z 0:zparseopts -D >ret: 0, optv: -a -b 1 -c-d, argv: -e -z () { local -a optv zparseopts -E -a optv - a b: c:- z print -r - ret: $?, optv: $optv, argv: $argv } -ab1 -c -d -e -z 0:zparseopts -E >ret: 0, optv: -a -b 1 -c-d -z, argv: -ab1 -c -d -e -z () { local -a optv zparseopts -D -E -a optv - a b: c:- z print -r - ret: $?, optv: $optv, argv: $argv } -ab1 -c -d -e -z 0:zparseopts -D -E >ret: 0, optv: -a -b 1 -c-d -z, argv: -e for 1 in '-a -x -z' '-ax -z' '-a --x -z' -axy -a-xy; do () { local -a optv zparseopts -D -E -F -a optv - a b: c:- z print -r - ret: $?, optv: $optv, argv: $argv } $=1 done 0:zparseopts -F ?(anon): bad option: -x >ret: 1, optv: , argv: -a -x -z ?(anon): bad option: -x >ret: 1, optv: , argv: -ax -z ?(anon): bad option: --x >ret: 1, optv: , argv: -a --x -z ?(anon): bad option: -x >ret: 1, optv: , argv: -axy ?(anon): bad option: -- >ret: 1, optv: , argv: -a-xy for 1 in '-a 1 2 3' '1 2 3'; do () { local -a optv=( -x -y -z ) zparseopts -D -K -a optv - a b: c:- z print -r - ret: $?, optv: $optv, argv: $argv } $=1 done 0:zparseopts -K -a >ret: 0, optv: -a, argv: 1 2 3 >ret: 0, optv: -x -y -z, argv: 1 2 3 for 1 in '-a 1 2 3' '1 2 3'; do () { local -A opts=( -b 1 -z '' ) zparseopts -D -K -A opts - a b: c:- z print -r - ret: $?, opts: "$( order_assoc opts )", argv: $argv } $=1 done 0:zparseopts -K -A >ret: 0, opts: -a '' -b 1 -z '', argv: 1 2 3 >ret: 0, opts: -b 1 -z '', argv: 1 2 3 fn() { local -a optv local -A opts zparseopts -D -M -a optv -A opts - a:=-aaa -aaa: print -r - ret: $?, optv: $optv, opts: "$( order_assoc opts )", argv: $argv } fn -a foo 1 2 3 fn --aaa foo 1 2 3 fn --aaa foo -a bar 1 2 3 fn -a foo --aaa bar 1 2 3 0:zparseopts -M >ret: 0, optv: -a foo, opts: --aaa foo, argv: 1 2 3 >ret: 0, optv: --aaa foo, opts: --aaa foo, argv: 1 2 3 >ret: 0, optv: -a bar, opts: --aaa bar, argv: 1 2 3 >ret: 0, optv: --aaa bar, opts: --aaa bar, argv: 1 2 3 () { local -a optv argvv=( -a -b -c 1 2 3 ) zparseopts -D -a optv -v argvv - a b c print -r - ret: $?, optv: $optv, argvv: $argvv, argv: $argv } -x -y -z 7 8 9 0:zparseopts -v >ret: 0, optv: -a -b -c, argvv: 1 2 3, argv: -x -y -z 7 8 9 () { local -a optv zparseopts -a optv -v argvv - a print -r - ret: $?, optv: $optv, argv: $argv } -a 0:zparseopts -v with unset parameter ?(anon):zparseopts:2: no such array: argvv >ret: 1, optv: , argv: -a () { local -a optv local argvv=1 zparseopts -a optv -v argvv - a print -r - ret: $?, optv: $optv, argv: $argv } -a 0:zparseopts -v with non-array argument ?(anon):zparseopts:3: no such array: argvv >ret: 1, optv: , argv: -a () { local -a optv aa ab zparseopts -a optv - a=aa b:=ab c:- z print -r - ret: $?, optv: $optv, aa: $aa, ab: $ab, argv: $argv } -ab1 -c -d 0:multiple arrays >ret: 0, optv: -c-d, aa: -a, ab: -b 1, argv: -ab1 -c -d for 1 in '-a - -b - - -b' '-a -- -b -- -- -b' '-a 1 -b - - -b'; do # -D alone strips - out () { local -a optv zparseopts -D -F -a optv - a b: c:- z print -r - '(-D )' ret: $?, optv: $optv, argv: $argv } $=1 # -D -E leaves - in () { local -a optv zparseopts -D -E -F -a optv - a b: c:- z print -r - '(-D -E)' ret: $?, optv: $optv, argv: $argv } $=1 done 0:-/-- handling >(-D ) ret: 0, optv: -a, argv: -b - - -b >(-D -E) ret: 0, optv: -a, argv: - -b - - -b >(-D ) ret: 0, optv: -a, argv: -b -- -- -b >(-D -E) ret: 0, optv: -a, argv: -- -b -- -- -b >(-D ) ret: 0, optv: -a, argv: 1 -b - - -b >(-D -E) ret: 0, optv: -a -b -, argv: 1 - -b # Escaping should always work, but it's optional on the first character for specs in '\+ \: \= \\' '+ : = \'; do () { local -a optv zparseopts -D -a optv - $=specs print -r - ret: $?, optv: $optv, argv: $argv } -+:=\\ 1 2 3 done () { local -a optv zparseopts -D -a optv - '-\:\:\::' print -r - ret: $?, optv: $optv, argv: $argv } --:::foo 1 2 3 0:special characters in option names >ret: 0, optv: -+ -: -= -\, argv: 1 2 3 >ret: 0, optv: -+ -: -= -\, argv: 1 2 3 >ret: 0, optv: --::: foo, argv: 1 2 3 for specs in \ '-foo: -foobar' '-foobar -foo:' '-foo: -foobar:' '-foobar: -foo:' do () { local -a optv zparseopts -a optv -D - $=specs print -r - ret: $?, optv: $optv, argv: $argv } --foobar 1 2 3 done 0:overlapping option specs without -G (scan order) >ret: 0, optv: --foobar, argv: 1 2 3 >ret: 0, optv: --foo bar, argv: 1 2 3 >ret: 0, optv: --foobar 1, argv: 2 3 >ret: 0, optv: --foo bar, argv: 1 2 3 for specs in \ '-foo: -foobar' '-foobar -foo:' '-foo: -foobar:' '-foobar: -foo:' do () { local -a optv zparseopts -a optv -D -G - $=specs print -r - ret: $?, optv: $optv, argv: $argv } --foobar 1 2 3 done 0:overlapping option specs with -G (scan order) >ret: 0, optv: --foobar, argv: 1 2 3 >ret: 0, optv: --foobar, argv: 1 2 3 >ret: 0, optv: --foobar 1, argv: 2 3 >ret: 0, optv: --foobar 1, argv: 2 3 () { local -a optv zparseopts -a optv - a b: c:- z print -r - ret: $?, optv: $optv, argv: $argv } -ab1 -c 0:missing optarg ?(anon): missing argument for option: -c >ret: 1, optv: , argv: -ab1 -c for spec in -foo: -foo:- -foo::; do () { local -a optv zparseopts -a optv -D -F - $=spec print -r - ret: $?, optv: $optv, argv: $argv } --foo=bar 1 2 3 done 0:zparseopts without -G, =optarg handling >ret: 0, optv: --foo =bar, argv: 1 2 3 >ret: 0, optv: --foo=bar, argv: 1 2 3 >ret: 0, optv: --foo=bar, argv: 1 2 3 for spec in -foo: -foo:- -foo::; do () { local -a optv zparseopts -a optv -D -F -G - $=spec print -r - ret: $?, optv: $optv, argv: $argv } --foo=bar 1 2 3 done 0:zparseopts -G, single parameter, with = >ret: 0, optv: --foo bar, argv: 1 2 3 >ret: 0, optv: --foo=bar, argv: 1 2 3 >ret: 0, optv: --foo=bar, argv: 1 2 3 for spec in -foo: -foo:- -foo:: ; do () { local -a optv zparseopts -a optv -D -F -G - $=spec print -r - ret: $?, optv: $optv, argv: $argv } --foobar 1 2 3 done 0:zparseopts -G, single parameter, without = ?(anon): bad option: --foobar >ret: 1, optv: , argv: --foobar 1 2 3 ?(anon): bad option: --foobar >ret: 1, optv: , argv: --foobar 1 2 3 ?(anon): bad option: --foobar >ret: 1, optv: , argv: --foobar 1 2 3 for spec in -foo: -foo:- -foo::; do () { local -a optv zparseopts -a optv -D -F -G - $=spec print -r - ret: $?, optv: $optv, argv: $argv } --foo bar 1 2 3 done 0:zparseopts -G, separate parameters >ret: 0, optv: --foo bar, argv: 1 2 3 >ret: 0, optv: --foo=bar, argv: 1 2 3 >ret: 0, optv: --foo=, argv: bar 1 2 3 for spec in -foo: -foo:- -foo::; do () { local -a optv zparseopts -a optv -D -F -G - $=spec print -r - ret: $?, optv: ${(j< >)${(q+)optv}}, argv: $argv } --foo= 1 2 3 done 0:zparseopts -G, empty optarg >ret: 0, optv: --foo '', argv: 1 2 3 >ret: 0, optv: '--foo=', argv: 1 2 3 >ret: 0, optv: '--foo=', argv: 1 2 3 for gopt in '' -G; do for spec args in \ f: '-fbar 1 2 3' \ f: '-f=bar 1 2 3' \ f: '-f bar 1 2 3' \ f:- '-fbar 1 2 3' \ f:- '-f=bar 1 2 3' \ f:- '-f bar 1 2 3' \ f:: '-fbar 1 2 3' \ f:: '-f=bar 1 2 3' \ f:: '-f bar 1 2 3' do () { local -a optv zparseopts -a optv -D -F $gopt - $=spec print -r - ret: $?, gopt: $gopt, optv: $optv, argv: $argv } $=args done done 0:short options, with and without -G >ret: 0, gopt: , optv: -f bar, argv: 1 2 3 >ret: 0, gopt: , optv: -f =bar, argv: 1 2 3 >ret: 0, gopt: , optv: -f bar, argv: 1 2 3 >ret: 0, gopt: , optv: -fbar, argv: 1 2 3 >ret: 0, gopt: , optv: -f=bar, argv: 1 2 3 >ret: 0, gopt: , optv: -fbar, argv: 1 2 3 >ret: 0, gopt: , optv: -fbar, argv: 1 2 3 >ret: 0, gopt: , optv: -f=bar, argv: 1 2 3 >ret: 0, gopt: , optv: -fbar, argv: 1 2 3 >ret: 0, gopt: -G, optv: -f bar, argv: 1 2 3 >ret: 0, gopt: -G, optv: -f =bar, argv: 1 2 3 >ret: 0, gopt: -G, optv: -f bar, argv: 1 2 3 >ret: 0, gopt: -G, optv: -fbar, argv: 1 2 3 >ret: 0, gopt: -G, optv: -f=bar, argv: 1 2 3 >ret: 0, gopt: -G, optv: -fbar, argv: 1 2 3 >ret: 0, gopt: -G, optv: -fbar, argv: 1 2 3 >ret: 0, gopt: -G, optv: -f=bar, argv: 1 2 3 >ret: 0, gopt: -G, optv: -f, argv: bar 1 2 3 for gopt in '' -G; do for spec args in \ foo: '-foobar 1 2 3' \ foo: '-foo=bar 1 2 3' \ foo: '-foo bar 1 2 3' \ foo:- '-foobar 1 2 3' \ foo:- '-foo=bar 1 2 3' \ foo:- '-foo bar 1 2 3' \ foo:: '-foobar 1 2 3' \ foo:: '-foo=bar 1 2 3' \ foo:: '-foo bar 1 2 3' do () { local -a optv zparseopts -a optv -D -F $gopt - $=spec print -r - ret: $?, gopt: $gopt, optv: $optv, argv: $argv } $=args done done 0:Sun-style long options, with and without -G >ret: 0, gopt: , optv: -foo bar, argv: 1 2 3 >ret: 0, gopt: , optv: -foo =bar, argv: 1 2 3 >ret: 0, gopt: , optv: -foo bar, argv: 1 2 3 >ret: 0, gopt: , optv: -foobar, argv: 1 2 3 >ret: 0, gopt: , optv: -foo=bar, argv: 1 2 3 >ret: 0, gopt: , optv: -foobar, argv: 1 2 3 >ret: 0, gopt: , optv: -foobar, argv: 1 2 3 >ret: 0, gopt: , optv: -foo=bar, argv: 1 2 3 >ret: 0, gopt: , optv: -foobar, argv: 1 2 3 ?(anon): bad option: -f >ret: 1, gopt: -G, optv: , argv: -foobar 1 2 3 >ret: 0, gopt: -G, optv: -foo bar, argv: 1 2 3 >ret: 0, gopt: -G, optv: -foo bar, argv: 1 2 3 ?(anon): bad option: -f >ret: 1, gopt: -G, optv: , argv: -foobar 1 2 3 >ret: 0, gopt: -G, optv: -foo=bar, argv: 1 2 3 >ret: 0, gopt: -G, optv: -foo=bar, argv: 1 2 3 ?(anon): bad option: -f >ret: 1, gopt: -G, optv: , argv: -foobar 1 2 3 >ret: 0, gopt: -G, optv: -foo=bar, argv: 1 2 3 >ret: 0, gopt: -G, optv: -foo=, argv: bar 1 2 3 for term in - --; do # With -D -E -G () { local -a optv zparseopts -a optv -D -E -F -G - -foo -bar print -r - ret: $?, term: $term, optv: $optv, argv: $argv } --foo x --bar $term --baz for gopt in '' -G; do # With -D + with/without -G () { local -a optv zparseopts -a optv -D -F $gopt - -foo -bar print -r - ret: $?, term: $term, gopt: $gopt, optv: $optv, argv: $argv } --foo $term --bar done done 0:only -- acts as explicit parsing terminator with -G ?(anon): bad option: --baz >ret: 1, term: -, optv: , argv: --foo x --bar - --baz >ret: 0, term: -, gopt: , optv: --foo, argv: --bar >ret: 0, term: -, gopt: -G, optv: --foo, argv: - --bar >ret: 0, term: --, optv: --foo --bar, argv: x -- --baz >ret: 0, term: --, gopt: , optv: --foo, argv: --bar >ret: 0, term: --, gopt: -G, optv: --foo, argv: --bar fn1() { zparseopts -F - a } fn2() { local -a optv zparseopts -a optv -F - a } fn3() { local -a optv zparseopts -a optv -nprog -F - a zparseopts -a optv -n prog -F - a } fn1 -x fn2 -x fn3 -x 1:zparseopts -n, internal vs external usage errors ?fn1:zparseopts:1: no default array defined: a ?fn2: bad option: -x ?prog: bad option: -x ?prog: bad option: -x () { zparseopts -DF - '' } -x () { local -a optv zparseopts -DFa optv - a typeset -p optv } -a 0:zparseopts option stacking ?(anon): bad option: -x >typeset -a optv=( -a ) () { local -a optv zparseopts -DFa optv -x } () { local -a optv zparseopts -DFa optv - -D typeset -p optv } --D () { local -a optv zparseopts -DFa optv - -DFa typeset -p optv } --DFa 0:zparseopts long-option spec guarding ?(anon):zparseopts:2: bad option: -x >typeset -a optv=( --D ) >typeset -a optv=( --DFa ) () { zparseopts -a } () { zparseopts -A } () { zparseopts -n } () { zparseopts -v } () { zparseopts -a '' } () { zparseopts -A '' } () { zparseopts -n '' } () { zparseopts -v '' } 1:zparseopts missing/empty optargs ?(anon):zparseopts: argument expected: -a ?(anon):zparseopts: argument expected: -A ?(anon):zparseopts: argument expected: -n ?(anon):zparseopts: argument expected: -v ?(anon):zparseopts: missing array name for -a ?(anon):zparseopts: missing array name for -A ?(anon):zparseopts: missing program name for -n ?(anon):zparseopts: missing array name for -v