{"thread":{"id":"12421","subject":"[PATCH] parse-opt: bring PARSE_OPT_HIDDEN to git-rev-parse --parseopt","startedAt":"2008-03-02T08:21:38Z","lastAt":"2008-03-02T10:35:56Z","messageCount":3,"participants":["Pierre Habouzit"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"70604","messageId":"20080302082138.GB5407@artemis.madism.org","threadId":"12421","inReplyTo":null,"subject":"[PATCH] parse-opt: bring PARSE_OPT_HIDDEN to git-rev-parse --parseopt","fromName":"Pierre Habouzit","fromEmail":"madcoder@debian.org","sentAt":"2008-03-02T08:21:38Z","receivedAt":"2008-03-02T08:21:38Z","isPatch":true,"sender":{"key":"madcoder@debian.org","avatar":"https://avatars.githubusercontent.com/u/44708?v=4"},"body":"Signed-off-by: Pierre Habouzit <madcoder@debian.org>\n---\n Documentation/git-rev-parse.txt |   15 ++++++++++-----\n builtin-rev-parse.c             |   25 ++++++++++++++-----------\n 2 files changed, 24 insertions(+), 16 deletions(-)\n\ndiff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt\nindex f02f6bb..e961c20 100644\n--- a/Documentation/git-rev-parse.txt\n+++ b/Documentation/git-rev-parse.txt\n@@ -325,7 +325,7 @@ The lines after the separator describe the options.\n Each line of options has this format:\n \n ------------\n-<opt_spec><arg_spec>? SP+ help LF\n+<opt_spec><flags>? SP+ help LF\n ------------\n \n `<opt_spec>`::\n@@ -334,10 +334,15 @@ Each line of options has this format:\n \tis necessary. `h,help`, `dry-run` and `f` are all three correct\n \t`<opt_spec>`.\n \n-`<arg_spec>`::\n-\tan `<arg_spec>` tells the option parser if the option has an argument\n-\t(`=`), an optional one (`?` though its use is discouraged) or none\n-\t(no `<arg_spec>` in that case).\n+`<flags>`::\n+\t`<flags>` are any suite of `*`, `=` or `?`.\n+\t* Use `=` if the option take an argument.\n+\n+\t* Use `?` to mean that the option is optional (though its use is discouraged).\n+\n+\t* Use `*` to mean that this option should not be listed in the usage\n+\t  generated for the `-h` argument. It's shown for `--help-all` as\n+\t  documented in linkgit:gitcli[5].\n \n The remainder of the line, after stripping the spaces, is used\n as the help associated to the option.\ndiff --git a/builtin-rev-parse.c b/builtin-rev-parse.c\nindex 90dbb9d..d1ea73a 100644\n--- a/builtin-rev-parse.c\n+++ b/builtin-rev-parse.c\n@@ -322,18 +322,21 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)\n \t\to->type = OPTION_CALLBACK;\n \t\to->help = xstrdup(skipspaces(s));\n \t\to->value = &parsed;\n+\t\to->flags = PARSE_OPT_NOARG;\n \t\to->callback = &parseopt_dump;\n-\t\tswitch (s[-1]) {\n-\t\tcase '=':\n-\t\t\ts--;\n-\t\t\tbreak;\n-\t\tcase '?':\n-\t\t\to->flags = PARSE_OPT_OPTARG;\n-\t\t\ts--;\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\to->flags = PARSE_OPT_NOARG;\n-\t\t\tbreak;\n+\t\twhile (s > sb.buf && strchr(\"*=?\", s[-1])) {\n+\t\t\tswitch (*--s) {\n+\t\t\tcase '=':\n+\t\t\t\to->flags &= ~PARSE_OPT_NOARG;\n+\t\t\t\tbreak;\n+\t\t\tcase '?':\n+\t\t\t\to->flags &= ~PARSE_OPT_NOARG;\n+\t\t\t\to->flags |= PARSE_OPT_OPTARG;\n+\t\t\t\tbreak;\n+\t\t\tcase '*':\n+\t\t\t\to->flags |= PARSE_OPT_HIDDEN;\n+\t\t\t\tbreak;\n+\t\t\t}\n \t\t}\n \n \t\tif (s - sb.buf == 1) /* short option only */\n-- \n1.5.4.3.343.g6846\n"},{"id":"70625","messageId":"20080302103515.GA21078@artemis.madism.org","threadId":"12421","inReplyTo":"20080302082138.GB5407@artemis.madism.org","subject":"[PATCH 2/3] parse-options: bring PARSE_OPT_NONEG to git-rev-parse --parseopt.","fromName":"Pierre Habouzit","fromEmail":"madcoder@debian.org","sentAt":"2008-03-02T10:35:15Z","receivedAt":"2008-03-02T10:35:15Z","isPatch":true,"sender":{"key":"madcoder@debian.org","avatar":"https://avatars.githubusercontent.com/u/44708?v=4"},"body":"Signed-off-by: Pierre Habouzit <madcoder@debian.org>\n---\n\n  While we're at it, this one could probably be squashed on top of the\n  previous one.\n\n Documentation/git-rev-parse.txt |    8 +++++---\n builtin-rev-parse.c             |    5 ++++-\n 2 files changed, 9 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt\nindex e961c20..6513c2e 100644\n--- a/Documentation/git-rev-parse.txt\n+++ b/Documentation/git-rev-parse.txt\n@@ -325,7 +325,7 @@ The lines after the separator describe the options.\n Each line of options has this format:\n \n ------------\n-<opt_spec><flags>? SP+ help LF\n+<opt_spec><flags>* SP+ help LF\n ------------\n \n `<opt_spec>`::\n@@ -335,8 +335,8 @@ Each line of options has this format:\n \t`<opt_spec>`.\n \n `<flags>`::\n-\t`<flags>` are any suite of `*`, `=` or `?`.\n-\t* Use `=` if the option take an argument.\n+\t`<flags>` are of `*`, `=`, `?` or `!`.\n+\t* Use `=` if the option takes an argument.\n \n \t* Use `?` to mean that the option is optional (though its use is discouraged).\n \n@@ -344,6 +344,8 @@ Each line of options has this format:\n \t  generated for the `-h` argument. It's shown for `--help-all` as\n \t  documented in linkgit:gitcli[5].\n \n+\t* Use `!` to not make the corresponding negated long option available.\n+\n The remainder of the line, after stripping the spaces, is used\n as the help associated to the option.\n \ndiff --git a/builtin-rev-parse.c b/builtin-rev-parse.c\nindex d1ea73a..0351d54 100644\n--- a/builtin-rev-parse.c\n+++ b/builtin-rev-parse.c\n@@ -324,7 +324,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)\n \t\to->value = &parsed;\n \t\to->flags = PARSE_OPT_NOARG;\n \t\to->callback = &parseopt_dump;\n-\t\twhile (s > sb.buf && strchr(\"*=?\", s[-1])) {\n+\t\twhile (s > sb.buf && strchr(\"*=?!\", s[-1])) {\n \t\t\tswitch (*--s) {\n \t\t\tcase '=':\n \t\t\t\to->flags &= ~PARSE_OPT_NOARG;\n@@ -333,6 +333,9 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)\n \t\t\t\to->flags &= ~PARSE_OPT_NOARG;\n \t\t\t\to->flags |= PARSE_OPT_OPTARG;\n \t\t\t\tbreak;\n+\t\t\tcase '!':\n+\t\t\t\to->flags |= PARSE_OPT_NONEG;\n+\t\t\t\tbreak;\n \t\t\tcase '*':\n \t\t\t\to->flags |= PARSE_OPT_HIDDEN;\n \t\t\t\tbreak;\n-- \n1.5.4.3.471.ga96e8.dirty\n\n"},{"id":"70628","messageId":"20080302103556.GB21078@artemis.madism.org","threadId":"12421","inReplyTo":"20080302082138.GB5407@artemis.madism.org","subject":"[PATCH 3/3] parse-options: new option type to treat an option-like parameter as an argument.","fromName":"Pierre Habouzit","fromEmail":"madcoder@debian.org","sentAt":"2008-03-02T10:35:56Z","receivedAt":"2008-03-02T10:35:56Z","isPatch":true,"sender":{"key":"madcoder@debian.org","avatar":"https://avatars.githubusercontent.com/u/44708?v=4"},"body":"This is meant to be used to keep --not and --all during revision parsing.\n\nSigned-off-by: Pierre Habouzit <madcoder@debian.org>\n---\n parse-options.c          |   26 +++++++++++++++++++-------\n parse-options.h          |    2 ++\n t/t0040-parse-options.sh |   16 ++++++++++++++++\n test-parse-options.c     |    2 ++\n 4 files changed, 39 insertions(+), 7 deletions(-)\n\ndiff --git a/parse-options.c b/parse-options.c\nindex be35785..8e64316 100644\n--- a/parse-options.c\n+++ b/parse-options.c\n@@ -6,7 +6,8 @@\n \n struct optparse_t {\n \tconst char **argv;\n-\tint argc;\n+\tconst char **out;\n+\tint argc, cpidx;\n \tconst char *opt;\n };\n \n@@ -159,6 +160,16 @@ static int parse_long_opt(struct optparse_t *p, const char *arg,\n \t\t\tcontinue;\n \n \t\trest = skip_prefix(arg, options->long_name);\n+\t\tif (options->type == OPTION_ARGUMENT) {\n+\t\t\tif (!rest)\n+\t\t\t\tcontinue;\n+\t\t\tif (*rest == '=')\n+\t\t\t\treturn opterror(options, \"takes no value\", flags);\n+\t\t\tif (*rest)\n+\t\t\t\tcontinue;\n+\t\t\tp->out[p->cpidx++] = arg - 2;\n+\t\t\treturn 0;\n+\t\t}\n \t\tif (!rest) {\n \t\t\t/* abbreviated? */\n \t\t\tif (!strncmp(options->long_name, arg, arg_end - arg)) {\n@@ -242,8 +253,7 @@ static NORETURN void usage_with_options_internal(const char * const *,\n int parse_options(int argc, const char **argv, const struct option *options,\n                   const char * const usagestr[], int flags)\n {\n-\tstruct optparse_t args = { argv + 1, argc - 1, NULL };\n-\tint j = 0;\n+\tstruct optparse_t args = { argv + 1, argv, argc - 1, 0, NULL };\n \n \tfor (; args.argc; args.argc--, args.argv++) {\n \t\tconst char *arg = args.argv[0];\n@@ -251,7 +261,7 @@ int parse_options(int argc, const char **argv, const struct option *options,\n \t\tif (*arg != '-' || !arg[1]) {\n \t\t\tif (flags & PARSE_OPT_STOP_AT_NON_OPTION)\n \t\t\t\tbreak;\n-\t\t\targv[j++] = args.argv[0];\n+\t\t\targs.out[args.cpidx++] = args.argv[0];\n \t\t\tcontinue;\n \t\t}\n \n@@ -288,9 +298,9 @@ int parse_options(int argc, const char **argv, const struct option *options,\n \t\t\tusage_with_options(usagestr, options);\n \t}\n \n-\tmemmove(argv + j, args.argv, args.argc * sizeof(*argv));\n-\targv[j + args.argc] = NULL;\n-\treturn j + args.argc;\n+\tmemmove(args.out + args.cpidx, args.argv, args.argc * sizeof(*args.out));\n+\targs.out[args.cpidx + args.argc] = NULL;\n+\treturn args.cpidx + args.argc;\n }\n \n #define USAGE_OPTS_WIDTH 24\n@@ -330,6 +340,8 @@ void usage_with_options_internal(const char * const *usagestr,\n \t\t\tpos += fprintf(stderr, \"--%s\", opts->long_name);\n \n \t\tswitch (opts->type) {\n+\t\tcase OPTION_ARGUMENT:\n+\t\t\tbreak;\n \t\tcase OPTION_INTEGER:\n \t\t\tif (opts->flags & PARSE_OPT_OPTARG)\n \t\t\t\tpos += fprintf(stderr, \" [<n>]\");\ndiff --git a/parse-options.h b/parse-options.h\nindex 0d40cd2..1af62b0 100644\n--- a/parse-options.h\n+++ b/parse-options.h\n@@ -4,6 +4,7 @@\n enum parse_opt_type {\n \t/* special types */\n \tOPTION_END,\n+\tOPTION_ARGUMENT,\n \tOPTION_GROUP,\n \t/* options with no arguments */\n \tOPTION_BIT,\n@@ -85,6 +86,7 @@ struct option {\n };\n \n #define OPT_END()                   { OPTION_END }\n+#define OPT_ARGUMENT(l, h)          { OPTION_ARGUMENT, 0, (l), NULL, NULL, (h) }\n #define OPT_GROUP(h)                { OPTION_GROUP, 0, NULL, NULL, NULL, (h) }\n #define OPT_BIT(s, l, v, h, b)      { OPTION_BIT, (s), (l), (v), NULL, (h), 0, NULL, (b) }\n #define OPT_BOOLEAN(s, l, v, h)     { OPTION_BOOLEAN, (s), (l), (v), NULL, (h) }\ndiff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh\nindex 0e2933a..c23f0ac 100755\n--- a/t/t0040-parse-options.sh\n+++ b/t/t0040-parse-options.sh\n@@ -21,6 +21,9 @@ string options\n     --st <st>             get another string (pervert ordering)\n     -o <str>              get another string\n \n+magic arguments\n+    --quux                means --quux\n+\n EOF\n \n test_expect_success 'test help' '\n@@ -114,4 +117,17 @@ test_expect_success 'detect possible typos' '\n \tgit diff expect.err output.err\n '\n \n+cat > expect <<EOF\n+boolean: 0\n+integer: 0\n+string: (not set)\n+arg 00: --quux\n+EOF\n+\n+test_expect_success 'keep some options as arguments' '\n+\ttest-parse-options --quux > output 2> output.err &&\n+        test ! -s output.err &&\n+        git diff expect output\n+'\n+\n test_done\ndiff --git a/test-parse-options.c b/test-parse-options.c\nindex eed8a02..73360d7 100644\n--- a/test-parse-options.c\n+++ b/test-parse-options.c\n@@ -20,6 +20,8 @@ int main(int argc, const char **argv)\n \t\tOPT_STRING(0, \"string2\", &string, \"str\", \"get another string\"),\n \t\tOPT_STRING(0, \"st\", &string, \"st\", \"get another string (pervert ordering)\"),\n \t\tOPT_STRING('o', NULL, &string, \"str\", \"get another string\"),\n+\t\tOPT_GROUP(\"magic arguments\"),\n+\t\tOPT_ARGUMENT(\"quux\", \"means --quux\"),\n \t\tOPT_END(),\n \t};\n \tint i;\n-- \n1.5.4.3.471.ga96e8.dirty\n"}]}