summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2008-03-08 21:29:59 -0800
committerJunio C Hamano <gitster@pobox.com>2008-03-08 21:29:59 -0800
commit1cbcefb107776ce2da374697bb4f6e2bd22ff73f (patch)
tree1d1bcd19b1433a8c18220e083414be93881657ca
parent175f5595511b047a320e5c6163c642ac1fc34681 (diff)
parent580d5bffdea56dfae1e745dbda94f326bb161274 (diff)
downloadgit-1cbcefb107776ce2da374697bb4f6e2bd22ff73f.tar.gz
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
-rw-r--r--Documentation/git-rev-parse.txt17
-rw-r--r--builtin-rev-parse.c28
-rw-r--r--parse-options.c26
-rw-r--r--parse-options.h2
-rwxr-xr-xt/t0040-parse-options.sh16
-rw-r--r--test-parse-options.c2
6 files changed, 68 insertions, 23 deletions
diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index f02f6bbb49..6513c2efe1 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -325,7 +325,7 @@ The lines after the separator describe the options.
Each line of options has this format:
------------
-<opt_spec><arg_spec>? SP+ help LF
+<opt_spec><flags>* SP+ help LF
------------
`<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
`<opt_spec>`.
-`<arg_spec>`::
- an `<arg_spec>` tells the option parser if the option has an argument
- (`=`), an optional one (`?` though its use is discouraged) or none
- (no `<arg_spec>` in that case).
+`<flags>`::
+ `<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 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
as the help associated to the option.
diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c
index 90dbb9d7c1..0351d54435 100644
--- a/builtin-rev-parse.c
+++ b/builtin-rev-parse.c
@@ -322,18 +322,24 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
o->type = OPTION_CALLBACK;
o->help = xstrdup(skipspaces(s));
o->value = &parsed;
+ o->flags = PARSE_OPT_NOARG;
o->callback = &parseopt_dump;
- switch (s[-1]) {
- case '=':
- s--;
- break;
- case '?':
- o->flags = PARSE_OPT_OPTARG;
- s--;
- break;
- default:
- o->flags = PARSE_OPT_NOARG;
- break;
+ while (s > sb.buf && strchr("*=?!", s[-1])) {
+ switch (*--s) {
+ case '=':
+ o->flags &= ~PARSE_OPT_NOARG;
+ break;
+ case '?':
+ o->flags &= ~PARSE_OPT_NOARG;
+ o->flags |= PARSE_OPT_OPTARG;
+ break;
+ case '!':
+ o->flags |= PARSE_OPT_NONEG;
+ break;
+ case '*':
+ o->flags |= PARSE_OPT_HIDDEN;
+ break;
+ }
}
if (s - sb.buf == 1) /* short option only */
diff --git a/parse-options.c b/parse-options.c
index d9562ba504..b32c9ea66c 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -6,7 +6,8 @@
struct optparse_t {
const char **argv;
- int argc;
+ const char **out;
+ int argc, cpidx;
const char *opt;
};
@@ -159,6 +160,16 @@ static int parse_long_opt(struct optparse_t *p, const char *arg,
continue;
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) {
/* abbreviated? */
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,
const char * const usagestr[], int flags)
{
- struct optparse_t args = { argv + 1, argc - 1, NULL };
- int j = 0;
+ struct optparse_t args = { argv + 1, argv, argc - 1, 0, NULL };
for (; args.argc; args.argc--, args.argv++) {
const char *arg = args.argv[0];
if (*arg != '-' || !arg[1]) {
- argv[j++] = args.argv[0];
+ args.out[args.cpidx++] = args.argv[0];
continue;
}
@@ -286,9 +296,9 @@ int parse_options(int argc, const char **argv, const struct option *options,
usage_with_options(usagestr, options);
}
- memmove(argv + j, args.argv, args.argc * sizeof(*argv));
- argv[j + args.argc] = NULL;
- return j + args.argc;
+ memmove(args.out + args.cpidx, args.argv, args.argc * sizeof(*args.out));
+ args.out[args.cpidx + args.argc] = NULL;
+ return args.cpidx + args.argc;
}
#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);
switch (opts->type) {
+ case OPTION_ARGUMENT:
+ break;
case OPTION_INTEGER:
if (opts->flags & PARSE_OPT_OPTARG)
pos += fprintf(stderr, " [<n>]");
diff --git a/parse-options.h b/parse-options.h
index 102ac31fb7..dc0807834f 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -4,6 +4,7 @@
enum parse_opt_type {
/* special types */
OPTION_END,
+ OPTION_ARGUMENT,
OPTION_GROUP,
/* options with no arguments */
OPTION_BIT,
@@ -84,6 +85,7 @@ struct option {
};
#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_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) }
diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
index 0e2933a984..c23f0ace85 100755
--- a/t/t0040-parse-options.sh
+++ b/t/t0040-parse-options.sh
@@ -21,6 +21,9 @@ string options
--st <st> get another string (pervert ordering)
-o <str> get another string
+magic arguments
+ --quux means --quux
+
EOF
test_expect_success 'test help' '
@@ -114,4 +117,17 @@ test_expect_success 'detect possible typos' '
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
diff --git a/test-parse-options.c b/test-parse-options.c
index eed8a02c65..73360d7512 100644
--- a/test-parse-options.c
+++ b/test-parse-options.c
@@ -20,6 +20,8 @@ int main(int argc, const char **argv)
OPT_STRING(0, "string2", &string, "str", "get another string"),
OPT_STRING(0, "st", &string, "st", "get another string (pervert ordering)"),
OPT_STRING('o', NULL, &string, "str", "get another string"),
+ OPT_GROUP("magic arguments"),
+ OPT_ARGUMENT("quux", "means --quux"),
OPT_END(),
};
int i;