Code

parse-options: new option type to treat an option-like parameter as an argument.
authorPierre Habouzit <madcoder@debian.org>
Sun, 2 Mar 2008 10:35:56 +0000 (11:35 +0100)
committerJunio C Hamano <gitster@pobox.com>
Sun, 2 Mar 2008 22:07:47 +0000 (14:07 -0800)
This is meant to be used to keep --not and --all during revision parsing.

Signed-off-by: Pierre Habouzit <madcoder@debian.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
parse-options.c
parse-options.h
t/t0040-parse-options.sh
test-parse-options.c

index d9562ba5047ff1c9994755a4dbec5162b551c788..b32c9ea66c7ae1e83564cd25d63d5cfd6c1589b5 100644 (file)
@@ -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>]");
index 102ac31fb727acfdc3c2159e1525c7bcca94e1ef..dc0807834f9135b82c289b429a8d2ea13ee53be8 100644 (file)
@@ -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) }
index 0e2933a984fcf6a23b60e54ed43c411c699d4347..c23f0ace85c83f54fd7562d72af6ef6c1ea2eca3 100755 (executable)
@@ -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
index eed8a02c6589bcb9af46188b56054eace3cd4d19..73360d75126af2f231b3cfdad26a47e18fff0a39 100644 (file)
@@ -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;