* Replacing getopts with zparseopts @ 2011-05-15 14:34 Thorsten Kampe 2011-05-15 18:00 ` Bart Schaefer 0 siblings, 1 reply; 4+ messages in thread From: Thorsten Kampe @ 2011-05-15 14:34 UTC (permalink / raw) To: zsh-users Hi, "From Bash to Z Shell" mentions that one could possibly use zparseopts instead of getopts - for instance to get long GNU style options ("-- long-option"). Unfortunately neither the book nor the man page were too helpful (my fault) in "translating" the standard option case. Could someone help me to create the below simple construct with zparseopts and making sure that "-d" and "--debug", "-h" and "--help", and "-v" and "--verbose" refer to the same option?! ## while getopts dhv opt do case $opt in (d) setopt xtrace;; (h) print_help exit;; (v) print_version exit;; (\?) print_usage >&2 exit 1;; esac done ## Thanks in advance, Thorsten ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: Replacing getopts with zparseopts 2011-05-15 14:34 Replacing getopts with zparseopts Thorsten Kampe @ 2011-05-15 18:00 ` Bart Schaefer 2011-05-15 18:49 ` Thorsten Kampe 0 siblings, 1 reply; 4+ messages in thread From: Bart Schaefer @ 2011-05-15 18:00 UTC (permalink / raw) To: zsh-users On May 15, 4:34pm, Thorsten Kampe wrote: } } Could someone help me to create the below simple construct with } zparseopts and making sure that "-d" and "--debug", "-h" and "--help", } and "-v" and "--verbose" refer to the same option?! This depends on what you intend by "refer to the same option." All zparseopts does is read (and possibly strip) the options from the command line and place their values in parameters. It's then up to later code to interpret the parameters correctly. For example with "zparseopts -A opthash ..." there isn't any direct way to tell zparseopts that both "-d" and "--debug" should place a value in $opthash[d]. If you want to use the -A form, you have to later check for ${opthash[(i)-d|--debug]} or in some other way check for both/either. If you use individual arrays for each option, then you can do this: local -a debug help vers usage zparseopts d=debug -debug=debug \ h=help -help=help \ v=vers -version=vers \ \?=usage and e.g. $+debug[1] indicates whether one of -d or --debug was used, and the value in $debug will tell you which one. However, if *both* were used, $debug will contain both, whereas if -d were used twice, it would appear in $debug only once. Compare this to "zparseopts -d+=debug" in which two uses of -d places two array elements in $debug. } ## } while getopts dhv opt } do case $opt in } (d) setopt xtrace;; } } (h) print_help } exit;; } } (v) print_version } exit;; } } (\?) print_usage >&2 } exit 1;; } esac } done } ## It's probably obvious but to conclude the example begun above: [[ -n $debug ]] && setopt xtrace [[ -n $help ]] && { print_help; exit } [[ -n $version ]] && { print_version; exit } [[ -n $usage ]] && { print_usage >&2; exit 1 } Note here we don't know in what *order* the options were given, so when both -h and -v appear in either order it'll always print the help and then exit. You could instead write -- [[ -n $version ]] && print_version [[ -n $help ]] && print_help [[ -n "$help$version" ]] && exit -- to print both the version and the help when -h and -v are both used in any order. For this simple a case, zparseopts doesn't really save you any effort; in fact it's probably a bit worse than getopts except that it handles the long option forms. Where zparseopts really gets useful is when for example you are writing a wrapper function for another command. In that case you can create a zparseopts description of the options taken by the wrapped command, and use "zparseopts -D ..." to strip them out of the command line so the wrapper can manipulate what's left. ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: Replacing getopts with zparseopts 2011-05-15 18:00 ` Bart Schaefer @ 2011-05-15 18:49 ` Thorsten Kampe 2011-05-16 18:44 ` Bart Schaefer 0 siblings, 1 reply; 4+ messages in thread From: Thorsten Kampe @ 2011-05-15 18:49 UTC (permalink / raw) To: zsh-users * Bart Schaefer (Sun, 15 May 2011 11:00:05 -0700) > On May 15, 4:34pm, Thorsten Kampe wrote: > } Could someone help me to create the below simple construct with > } zparseopts and making sure that "-d" and "--debug", "-h" and "--help", > } and "-v" and "--verbose" refer to the same option?! [...] > For this simple a case, zparseopts doesn't really save you any effort; > in fact it's probably a bit worse than getopts except that it handles > the long option forms. So zparseopts is not a "better getopts". So what do people use to be able to use (and parse) long options?? Thorsten ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: Replacing getopts with zparseopts 2011-05-15 18:49 ` Thorsten Kampe @ 2011-05-16 18:44 ` Bart Schaefer 0 siblings, 0 replies; 4+ messages in thread From: Bart Schaefer @ 2011-05-16 18:44 UTC (permalink / raw) To: zsh-users On May 15, 8:49pm, Thorsten Kampe wrote: } } So zparseopts is not a "better getopts". So what do people use to be } able to use (and parse) long options?? This might be helpful. With the patch below, one can e.g. do zparseopts -M d=opt_d -debug=d and have both the -d and the --debug options stashed in the $opt_d array. There's a remaining buglet here that I haven't decided how to handle: Given the above spec, the $d array is also created (or reset) but is always empty. The most straightforward fix for this would be simply to assert that -M always implies -K. The patch also fixes this bug: torch% zparseopts -- -debug=d zparseopts: missing option descriptions The problem is that the generic command parser handles "--" natively, removing it from the arguments passed to bin_zparseopts(), which then caused "-debug=d" to be ignored. Index: Doc/Zsh/mod_zutil.yo =================================================================== diff -c -r1.6 mod_zutil.yo --- Doc/Zsh/mod_zutil.yo 26 Nov 2007 17:38:13 -0000 1.6 +++ Doc/Zsh/mod_zutil.yo 16 May 2011 17:39:16 -0000 @@ -178,7 +178,7 @@ This implements some internals of the tt(_regex_arguments) function. ) findex(zparseopts) -item(tt(zparseopts) [ tt(-D) ] [ tt(-K) ] [ tt(-E) ] [ tt(-a) var(array) ] [ tt(-A) var(assoc) ] var(specs))( +item(tt(zparseopts) [ tt(-D) ] [ tt(-K) ] [ tt(-M) ] [ tt(-E) ] [ tt(-a) var(array) ] [ tt(-A) var(assoc) ] var(specs))( This builtin simplifies the parsing of options in positional parameters, i.e. the set of arguments given by tt($*). Each var(spec) describes one option and must be of the form `var(opt)[tt(=)var(array)]'. If an option @@ -255,6 +255,15 @@ of the var(specs) for them is used. This allows assignment of default values to them before calling tt(zparseopts). ) +item(tt(-M))( +This changes the assignment rules to implement a map among equivalent +option names. If any var(spec) uses the `tt(=)var(array)' form, the +string var(array) is interpreted as the name of another var(spec), +which is used to choose where to store the values. If no other var(spec) +is found, the values are stored as usual. This changes only the way the +values are stored, not the way tt($*) is parsed, so results may be +unpredicable if the `var(name)tt(+)' specifier is used inconsistently. +) item(tt(-E))( This changes the parsing rules to em(not) stop at the first string that isn't described by one of the var(spec)s. It can be used to test @@ -288,5 +297,15 @@ I.e., the option tt(-b) and its arguments are taken from the positional parameters and put into the array tt(bar). + +The tt(-M) option can be used like this: + +example(set -- -a -bx -c y -cz baz -cend +zparseopts -A bar -M a=foo b+: c:=b) + +to have the effect of + +example(foo=(-a) +bar=(-a '' -b xyz)) ) enditem() Index: Src/Modules/zutil.c =================================================================== diff -c -r1.11 zutil.c --- Src/Modules/zutil.c 21 Dec 2010 16:41:16 -0000 1.11 +++ Src/Modules/zutil.c 16 May 2011 18:15:53 -0000 @@ -1405,6 +1405,7 @@ #define ZOF_OPT 2 #define ZOF_MULT 4 #define ZOF_SAME 8 +#define ZOF_MAP 16 struct zoptarr { Zoptarr next; @@ -1466,6 +1467,12 @@ char *n = dyncat("-", d->name); int new = 0; + while (d->flags & ZOF_MAP) { + Zoptdesc map = get_opt_desc(d->arr->name); + if (!map || !strcmp(map->name, n+1)) + break; + d = map; + } if (!(d->flags & ZOF_MULT)) v = d->vals; if (!v) { @@ -1513,7 +1520,7 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) { char *o, *p, *n, **pp, **aval, **ap, *assoc = NULL, **cp, **np; - int del = 0, f, extract = 0, keep = 0; + int del = 0, flags = 0, extract = 0, keep = 0; Zoptdesc sopts[256], d; Zoptarr a, defarr = NULL; Zoptval v; @@ -1531,6 +1538,7 @@ case '-': if (o[2]) args--; + /* else unreachable, default parsing removes "--" */ o = NULL; break; case 'D': @@ -1557,6 +1565,14 @@ } keep = 1; break; + case 'M': + if (o[2]) { + args--; + o = NULL; + break; + } + flags |= ZOF_MAP; + break; case 'a': if (defarr) { zwarnnam(nam, "default array given more than once"); @@ -1578,6 +1594,10 @@ opt_arrs = defarr; break; case 'A': + if (assoc) { + zwarnnam(nam, "associative array given more than once"); + return 1; + } if (o[2]) assoc = o + 2; else if (*args) @@ -1587,6 +1607,11 @@ return 1; } break; + default: + /* Anything else is an option description */ + args--; + o = NULL; + break; } if (!o) { o = ""; @@ -1602,11 +1627,11 @@ return 1; } while ((o = dupstring(*args++))) { + int f = 0; if (!*o) { zwarnnam(nam, "invalid option description: %s", o); return 1; } - f = 0; for (p = o; *p; p++) { if (*p == '\\' && p[1]) p++; @@ -1633,6 +1658,7 @@ a = NULL; if (*p == '=') { *p++ = '\0'; + f |= flags; if (!(a = get_opt_arr(p))) { a = (Zoptarr) zhalloc(sizeof(*a)); a->name = p; ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2011-05-16 18:45 UTC | newest] Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2011-05-15 14:34 Replacing getopts with zparseopts Thorsten Kampe 2011-05-15 18:00 ` Bart Schaefer 2011-05-15 18:49 ` Thorsten Kampe 2011-05-16 18:44 ` Bart Schaefer
Code repositories for project(s) associated with this public inbox https://git.vuxu.org/mirror/zsh/ This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).