diff options
author | dana <dana@dana.is> | 2025-04-13 18:00:54 -0500 |
---|---|---|
committer | dana <dana@dana.is> | 2025-04-19 18:48:31 -0500 |
commit | 8c3c45732131433645686cdb6bbbb8974230c5a9 (patch) | |
tree | ccaa627886d33bf6d8ae2c84b08e511880870eef | |
parent | 494fcd1799d4d2d236d3183de12b0c99ceb83b1c (diff) | |
download | zsh-8c3c45732131433645686cdb6bbbb8974230c5a9.tar.gz zsh-8c3c45732131433645686cdb6bbbb8974230c5a9.zip |
53483: zparseopts -G: accept only '--' as parsing terminator
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | Doc/Zsh/mod_zutil.yo | 14 | ||||
-rw-r--r-- | Src/Modules/zutil.c | 6 | ||||
-rw-r--r-- | Test/V12zparseopts.ztst | 25 |
4 files changed, 41 insertions, 8 deletions
@@ -1,5 +1,9 @@ 2025-04-19 dana <dana@dana.is> + * 53483: Doc/Zsh/mod_zutil.yo, Src/Modules/zutil.c, + Test/V12zparseopts.ztst: with `zparseopts -G`, accept only + '--' as parsing terminator + * 53482: Src/Modules/zutil.c, Src/Modules/Test/V12zparseopts.ztst: with `zparseopts -G`, always add options options with optional args to array with = diff --git a/Doc/Zsh/mod_zutil.yo b/Doc/Zsh/mod_zutil.yo index 76907352f..19f9989f4 100644 --- a/Doc/Zsh/mod_zutil.yo +++ b/Doc/Zsh/mod_zutil.yo @@ -242,8 +242,8 @@ Note that it is an error to give any var(spec) without an Unless the tt(-E) option is given, parsing stops at the first string that isn't described by one of the var(spec)s. Even with tt(-E), -parsing always stops at a positional parameter equal to `tt(-)' or -`tt(-)tt(-)'. See also tt(-F). +parsing always stops at a positional parameter equal to `tt(-)tt(-)' or +(without tt(-G)) `tt(-)'. See also tt(-F). The var(opt) description must be one of the following. Any of the special characters can appear in the option name provided it is preceded by a @@ -314,9 +314,9 @@ as the values. item(tt(-D))( If this option is given, all options found are removed from the positional parameters of the calling shell or shell function, up to but not including -any not described by the var(spec)s. If the first such parameter is `tt(-)' -or `tt(-)tt(-)', it is removed as well. This is similar to using the -tt(shift) builtin. +any not described by the var(spec)s. If the first such parameter is +`tt(-)tt(-)' or (without tt(-G)) `tt(-)', it is removed as well. This is +similar to using the tt(shift) builtin. ) item(tt(-E))( This changes the parsing rules to em(not) stop at the first string @@ -364,6 +364,10 @@ A mandatory option-argument given in a separate parameter from its option (as in `tt(-)tt(-foo) tt(bar)'), or any option-argument given to a short option in the same parameter, is always treated the same regardless of whether this option is in effect. + +Lastly, when this option is active, only `tt(-)tt(-)' is treated as an +explicit option-parsing terminator in the parsed arguments; a single +`tt(-)' is considered a normal operand. ) item(tt(-K))( With this option, the arrays specified with the tt(-a) option and with the diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c index ef99303d2..676fe1872 100644 --- a/Src/Modules/zutil.c +++ b/Src/Modules/zutil.c @@ -1955,8 +1955,8 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) params = getaparam((paramsname = paramsname ? paramsname : "argv")); np = cp = pp = ((extract && del) ? arrdup(params) : params); for (; (o = *pp); pp++) { - /* Not an option */ - if (*o != '-') { + /* Not an option. With GNU style, this includes '-' */ + if (*o != '-' || (gnu && !o[1])) { if (extract) { if (del) *cp++ = o; @@ -1964,7 +1964,7 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) } else break; } - /* '-' or '--', end parsing */ + /* '--' or (with non-GNU style, see above) '-', end parsing */ if (!o[1] || (o[1] == '-' && !o[2])) { if (del && extract) *cp++ = o; diff --git a/Test/V12zparseopts.ztst b/Test/V12zparseopts.ztst index e465d0e0c..e6139ea5e 100644 --- a/Test/V12zparseopts.ztst +++ b/Test/V12zparseopts.ztst @@ -341,3 +341,28 @@ >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):zparseopts:2: 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 |