Merge branch 'ph/parseopt'
* ph/parseopt: parse-options: new option type to treat an option-like parameter as an argument. parse-opt: bring PARSE_OPT_HIDDEN and NONEG to git-rev-parse --parseopt
This commit is contained in:
commit
1cbcefb107
@ -325,7 +325,7 @@ The lines after the separator describe the options.
|
|||||||
Each line of options has this format:
|
Each line of options has this format:
|
||||||
|
|
||||||
------------
|
------------
|
||||||
<opt_spec><arg_spec>? SP+ help LF
|
<opt_spec><flags>* SP+ help LF
|
||||||
------------
|
------------
|
||||||
|
|
||||||
`<opt_spec>`::
|
`<opt_spec>`::
|
||||||
@ -334,10 +334,17 @@ Each line of options has this format:
|
|||||||
is necessary. `h,help`, `dry-run` and `f` are all three correct
|
is necessary. `h,help`, `dry-run` and `f` are all three correct
|
||||||
`<opt_spec>`.
|
`<opt_spec>`.
|
||||||
|
|
||||||
`<arg_spec>`::
|
`<flags>`::
|
||||||
an `<arg_spec>` tells the option parser if the option has an argument
|
`<flags>` are of `*`, `=`, `?` or `!`.
|
||||||
(`=`), an optional one (`?` though its use is discouraged) or none
|
* Use `=` if the option takes an argument.
|
||||||
(no `<arg_spec>` in that case).
|
|
||||||
|
* Use `?` to mean that the option is optional (though its use is discouraged).
|
||||||
|
|
||||||
|
* 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
|
||||||
|
documented in linkgit:gitcli[5].
|
||||||
|
|
||||||
|
* Use `!` to not make the corresponding negated long option available.
|
||||||
|
|
||||||
The remainder of the line, after stripping the spaces, is used
|
The remainder of the line, after stripping the spaces, is used
|
||||||
as the help associated to the option.
|
as the help associated to the option.
|
||||||
|
@ -322,18 +322,24 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
|
|||||||
o->type = OPTION_CALLBACK;
|
o->type = OPTION_CALLBACK;
|
||||||
o->help = xstrdup(skipspaces(s));
|
o->help = xstrdup(skipspaces(s));
|
||||||
o->value = &parsed;
|
o->value = &parsed;
|
||||||
|
o->flags = PARSE_OPT_NOARG;
|
||||||
o->callback = &parseopt_dump;
|
o->callback = &parseopt_dump;
|
||||||
switch (s[-1]) {
|
while (s > sb.buf && strchr("*=?!", s[-1])) {
|
||||||
case '=':
|
switch (*--s) {
|
||||||
s--;
|
case '=':
|
||||||
break;
|
o->flags &= ~PARSE_OPT_NOARG;
|
||||||
case '?':
|
break;
|
||||||
o->flags = PARSE_OPT_OPTARG;
|
case '?':
|
||||||
s--;
|
o->flags &= ~PARSE_OPT_NOARG;
|
||||||
break;
|
o->flags |= PARSE_OPT_OPTARG;
|
||||||
default:
|
break;
|
||||||
o->flags = PARSE_OPT_NOARG;
|
case '!':
|
||||||
break;
|
o->flags |= PARSE_OPT_NONEG;
|
||||||
|
break;
|
||||||
|
case '*':
|
||||||
|
o->flags |= PARSE_OPT_HIDDEN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s - sb.buf == 1) /* short option only */
|
if (s - sb.buf == 1) /* short option only */
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
|
|
||||||
struct optparse_t {
|
struct optparse_t {
|
||||||
const char **argv;
|
const char **argv;
|
||||||
int argc;
|
const char **out;
|
||||||
|
int argc, cpidx;
|
||||||
const char *opt;
|
const char *opt;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -159,6 +160,16 @@ static int parse_long_opt(struct optparse_t *p, const char *arg,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
rest = skip_prefix(arg, options->long_name);
|
rest = skip_prefix(arg, options->long_name);
|
||||||
|
if (options->type == OPTION_ARGUMENT) {
|
||||||
|
if (!rest)
|
||||||
|
continue;
|
||||||
|
if (*rest == '=')
|
||||||
|
return opterror(options, "takes no value", flags);
|
||||||
|
if (*rest)
|
||||||
|
continue;
|
||||||
|
p->out[p->cpidx++] = arg - 2;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (!rest) {
|
if (!rest) {
|
||||||
/* abbreviated? */
|
/* abbreviated? */
|
||||||
if (!strncmp(options->long_name, arg, arg_end - arg)) {
|
if (!strncmp(options->long_name, arg, arg_end - arg)) {
|
||||||
@ -242,14 +253,13 @@ static NORETURN void usage_with_options_internal(const char * const *,
|
|||||||
int parse_options(int argc, const char **argv, const struct option *options,
|
int parse_options(int argc, const char **argv, const struct option *options,
|
||||||
const char * const usagestr[], int flags)
|
const char * const usagestr[], int flags)
|
||||||
{
|
{
|
||||||
struct optparse_t args = { argv + 1, argc - 1, NULL };
|
struct optparse_t args = { argv + 1, argv, argc - 1, 0, NULL };
|
||||||
int j = 0;
|
|
||||||
|
|
||||||
for (; args.argc; args.argc--, args.argv++) {
|
for (; args.argc; args.argc--, args.argv++) {
|
||||||
const char *arg = args.argv[0];
|
const char *arg = args.argv[0];
|
||||||
|
|
||||||
if (*arg != '-' || !arg[1]) {
|
if (*arg != '-' || !arg[1]) {
|
||||||
argv[j++] = args.argv[0];
|
args.out[args.cpidx++] = args.argv[0];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,9 +296,9 @@ int parse_options(int argc, const char **argv, const struct option *options,
|
|||||||
usage_with_options(usagestr, options);
|
usage_with_options(usagestr, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
memmove(argv + j, args.argv, args.argc * sizeof(*argv));
|
memmove(args.out + args.cpidx, args.argv, args.argc * sizeof(*args.out));
|
||||||
argv[j + args.argc] = NULL;
|
args.out[args.cpidx + args.argc] = NULL;
|
||||||
return j + args.argc;
|
return args.cpidx + args.argc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define USAGE_OPTS_WIDTH 24
|
#define USAGE_OPTS_WIDTH 24
|
||||||
@ -328,6 +338,8 @@ void usage_with_options_internal(const char * const *usagestr,
|
|||||||
pos += fprintf(stderr, "--%s", opts->long_name);
|
pos += fprintf(stderr, "--%s", opts->long_name);
|
||||||
|
|
||||||
switch (opts->type) {
|
switch (opts->type) {
|
||||||
|
case OPTION_ARGUMENT:
|
||||||
|
break;
|
||||||
case OPTION_INTEGER:
|
case OPTION_INTEGER:
|
||||||
if (opts->flags & PARSE_OPT_OPTARG)
|
if (opts->flags & PARSE_OPT_OPTARG)
|
||||||
pos += fprintf(stderr, " [<n>]");
|
pos += fprintf(stderr, " [<n>]");
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
enum parse_opt_type {
|
enum parse_opt_type {
|
||||||
/* special types */
|
/* special types */
|
||||||
OPTION_END,
|
OPTION_END,
|
||||||
|
OPTION_ARGUMENT,
|
||||||
OPTION_GROUP,
|
OPTION_GROUP,
|
||||||
/* options with no arguments */
|
/* options with no arguments */
|
||||||
OPTION_BIT,
|
OPTION_BIT,
|
||||||
@ -84,6 +85,7 @@ struct option {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define OPT_END() { OPTION_END }
|
#define OPT_END() { OPTION_END }
|
||||||
|
#define OPT_ARGUMENT(l, h) { OPTION_ARGUMENT, 0, (l), NULL, NULL, (h) }
|
||||||
#define OPT_GROUP(h) { OPTION_GROUP, 0, NULL, NULL, NULL, (h) }
|
#define OPT_GROUP(h) { OPTION_GROUP, 0, NULL, NULL, NULL, (h) }
|
||||||
#define OPT_BIT(s, l, v, h, b) { OPTION_BIT, (s), (l), (v), NULL, (h), 0, NULL, (b) }
|
#define OPT_BIT(s, l, v, h, b) { OPTION_BIT, (s), (l), (v), NULL, (h), 0, NULL, (b) }
|
||||||
#define OPT_BOOLEAN(s, l, v, h) { OPTION_BOOLEAN, (s), (l), (v), NULL, (h) }
|
#define OPT_BOOLEAN(s, l, v, h) { OPTION_BOOLEAN, (s), (l), (v), NULL, (h) }
|
||||||
|
@ -21,6 +21,9 @@ string options
|
|||||||
--st <st> get another string (pervert ordering)
|
--st <st> get another string (pervert ordering)
|
||||||
-o <str> get another string
|
-o <str> get another string
|
||||||
|
|
||||||
|
magic arguments
|
||||||
|
--quux means --quux
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
test_expect_success 'test help' '
|
test_expect_success 'test help' '
|
||||||
@ -114,4 +117,17 @@ test_expect_success 'detect possible typos' '
|
|||||||
git diff expect.err output.err
|
git diff expect.err output.err
|
||||||
'
|
'
|
||||||
|
|
||||||
|
cat > expect <<EOF
|
||||||
|
boolean: 0
|
||||||
|
integer: 0
|
||||||
|
string: (not set)
|
||||||
|
arg 00: --quux
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'keep some options as arguments' '
|
||||||
|
test-parse-options --quux > output 2> output.err &&
|
||||||
|
test ! -s output.err &&
|
||||||
|
git diff expect output
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
@ -20,6 +20,8 @@ int main(int argc, const char **argv)
|
|||||||
OPT_STRING(0, "string2", &string, "str", "get another string"),
|
OPT_STRING(0, "string2", &string, "str", "get another string"),
|
||||||
OPT_STRING(0, "st", &string, "st", "get another string (pervert ordering)"),
|
OPT_STRING(0, "st", &string, "st", "get another string (pervert ordering)"),
|
||||||
OPT_STRING('o', NULL, &string, "str", "get another string"),
|
OPT_STRING('o', NULL, &string, "str", "get another string"),
|
||||||
|
OPT_GROUP("magic arguments"),
|
||||||
|
OPT_ARGUMENT("quux", "means --quux"),
|
||||||
OPT_END(),
|
OPT_END(),
|
||||||
};
|
};
|
||||||
int i;
|
int i;
|
||||||
|
Loading…
Reference in New Issue
Block a user