Merge branch 'nv/parseopt-opt-arg'

Enhance "rev-parse --parseopt" mode to help parsing options with
an optional parameter.

* nv/parseopt-opt-arg:
  rev-parse --parseopt: add the --stuck-long mode
  Use the word 'stuck' instead of 'sticked'
This commit is contained in:
Junio C Hamano 2013-12-05 12:59:03 -08:00
Родитель c5a77e8f92 f8c872127d
Коммит 3576f113cb
7 изменённых файлов: 63 добавлений и 14 удалений

Просмотреть файл

@ -50,6 +50,10 @@ Options for --parseopt
the first non-option argument. This can be used to parse sub-commands
that take options themselves.
--stuck-long::
Only meaningful in `--parseopt` mode. Output the options in their
long form if available, and with their arguments stuck.
Options for Filtering
~~~~~~~~~~~~~~~~~~~~~
@ -285,7 +289,9 @@ Each line of options has this format:
`<flags>` are of `*`, `=`, `?` or `!`.
* Use `=` if the option takes an argument.
* Use `?` to mean that the option is optional (though its use is discouraged).
* Use `?` to mean that the option takes an optional argument. You
probably want to use the `--stuck-long` mode to be able to
unambiguously parse the optional argument.
* Use `*` to mean that this option should not be listed in the usage
generated for the `-h` argument. It's shown for `--help-all` as

Просмотреть файл

@ -72,11 +72,11 @@ scripting Git:
* splitting short options to separate words (prefer `git foo -a -b`
to `git foo -ab`, the latter may not even work).
* when a command line option takes an argument, use the 'sticked' form. In
* when a command line option takes an argument, use the 'stuck' form. In
other words, write `git foo -oArg` instead of `git foo -o Arg` for short
options, and `git foo --long-opt=Arg` instead of `git foo --long-opt Arg`
for long options. An option that takes optional option-argument must be
written in the 'sticked' form.
written in the 'stuck' form.
* when you give a revision parameter to a command, make sure the parameter is
not ambiguous with a name of a file in the work tree. E.g. do not write
@ -165,7 +165,7 @@ $ git foo -o Arg
----------------------------
However, this is *NOT* allowed for switches with an optional value, where the
'sticked' form must be used:
'stuck' form must be used:
----------------------------
$ git describe --abbrev HEAD # correct
$ git describe --abbrev=10 HEAD # correct

Просмотреть файл

@ -29,9 +29,9 @@ that allow to change the behavior of a command.
The parse-options API allows:
* 'sticked' and 'separate form' of options with arguments.
`-oArg` is sticked, `-o Arg` is separate form.
`--option=Arg` is sticked, `--option Arg` is separate form.
* 'stuck' and 'separate form' of options with arguments.
`-oArg` is stuck, `-o Arg` is separate form.
`--option=Arg` is stuck, `--option Arg` is separate form.
* Long options may be 'abbreviated', as long as the abbreviation
is unambiguous.

Просмотреть файл

@ -30,6 +30,8 @@ static int abbrev_ref;
static int abbrev_ref_strict;
static int output_sq;
static int stuck_long;
/*
* Some arguments are relevant "revision" arguments,
* others are about output format or other details.
@ -320,12 +322,15 @@ static int parseopt_dump(const struct option *o, const char *arg, int unset)
struct strbuf *parsed = o->value;
if (unset)
strbuf_addf(parsed, " --no-%s", o->long_name);
else if (o->short_name)
else if (o->short_name && (o->long_name == NULL || !stuck_long))
strbuf_addf(parsed, " -%c", o->short_name);
else
strbuf_addf(parsed, " --%s", o->long_name);
if (arg) {
strbuf_addch(parsed, ' ');
if (!stuck_long)
strbuf_addch(parsed, ' ');
else if (o->long_name)
strbuf_addch(parsed, '=');
sq_quote_buf(parsed, arg);
}
return 0;
@ -351,6 +356,8 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
OPT_BOOL(0, "stop-at-non-option", &stop_at_non_option,
N_("stop parsing after the "
"first non-option argument")),
OPT_BOOL(0, "stuck-long", &stuck_long,
N_("output in stuck long form")),
OPT_END(),
};

2
diff.c
Просмотреть файл

@ -3394,7 +3394,7 @@ int parse_long_opt(const char *opt, const char **argv,
if (prefixcmp(arg, opt))
return 0;
arg += strlen(opt);
if (*arg == '=') { /* sticked form: --option=value */
if (*arg == '=') { /* stuck form: --option=value */
*optarg = arg + 1;
return 1;
}

2
diff.h
Просмотреть файл

@ -244,7 +244,7 @@ extern struct diff_filepair *diff_unmerge(struct diff_options *, const char *pat
#define DIFF_SETUP_USE_SIZE_CACHE 4
/*
* Poor man's alternative to parse-option, to allow both sticked form
* Poor man's alternative to parse-option, to allow both stuck form
* (--option=value) and separate form (--option value).
*/
extern int parse_long_opt(const char *opt, const char **argv,

Просмотреть файл

@ -12,9 +12,11 @@ usage: some-command [options] <args>...
-h, --help show the help
--foo some nifty option --foo
--bar ... some cool option --bar with an argument
-b, --baz a short and long option
An option group Header
-C[...] option C with an optional argument
-d, --data[=...] short and long option with an optional argument
Extras
--extra1 line above used to cause a segfault but no longer does
@ -31,9 +33,11 @@ h,help show the help
foo some nifty option --foo
bar= some cool option --bar with an argument
b,baz a short and long option
An option group Header
C? option C with an optional argument
d,data? short and long option with an optional argument
Extras
extra1 line above used to cause a segfault but no longer does
@ -45,16 +49,16 @@ test_expect_success 'test --parseopt help output' '
'
cat > expect <<EOF
set -- --foo --bar 'ham' -- 'arg'
set -- --foo --bar 'ham' -b -- 'arg'
EOF
test_expect_success 'test --parseopt' '
git rev-parse --parseopt -- --foo --bar=ham arg < optionspec > output &&
git rev-parse --parseopt -- --foo --bar=ham --baz arg < optionspec > output &&
test_cmp expect output
'
test_expect_success 'test --parseopt with mixed options and arguments' '
git rev-parse --parseopt -- --foo arg --bar=ham < optionspec > output &&
git rev-parse --parseopt -- --foo arg --bar=ham --baz < optionspec > output &&
test_cmp expect output
'
@ -99,4 +103,36 @@ test_expect_success 'test --parseopt --keep-dashdash --stop-at-non-option withou
test_cmp expect output
'
cat > expect <<EOF
set -- --foo --bar='z' --baz -C'Z' --data='A' -- 'arg'
EOF
test_expect_success 'test --parseopt --stuck-long' '
git rev-parse --parseopt --stuck-long -- --foo --bar=z -b arg -CZ -dA <optionspec >output &&
test_cmp expect output
'
cat > expect <<EOF
set -- --data='' -C --baz -- 'arg'
EOF
test_expect_success 'test --parseopt --stuck-long and empty optional argument' '
git rev-parse --parseopt --stuck-long -- --data= arg -C -b <optionspec >output &&
test_cmp expect output
'
cat > expect <<EOF
set -- --data --baz -- 'arg'
EOF
test_expect_success 'test --parseopt --stuck-long and long option with unset optional argument' '
git rev-parse --parseopt --stuck-long -- --data arg -b <optionspec >output &&
test_cmp expect output
'
test_expect_success 'test --parseopt --stuck-long and short option with unset optional argument' '
git rev-parse --parseopt --stuck-long -- -d arg -b <optionspec >output &&
test_cmp expect output
'
test_done