git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 1/2] parse-options: introduce OPT_SUBCOMMAND

From
Ramkumar Ramachandra <artagnon@gmail.com>
Date
Dec 8, 2011, 13:10 UTC
Message-ID
<1323349817-15737-2-git-send-email-artagnon@gmail.com>
In-Reply-To
<1323349817-15737-1-git-send-email-artagnon@gmail.com>

Several git programs take long dash-less options on the command-line to indicate different modes of operation like:

  git stash show
  git bundle verify test.bundle
  git bisect start

Currently, the parse-options framework forbids the use of opts->long_name and OPT_PARSE_NODASH, and the parsing has to be done by hand as a result. Lift this restriction, and create a new OPT_SUBCOMMAND; this is built on top of OPTION_BIT to allow for the detection of more than one subcommand.

Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
---
 parse-options.c          |    5 +++--
 parse-options.h          |    3 +++
 t/t0040-parse-options.sh |   31 +++++++++++++++++++++++++++++++
 test-parse-options.c     |    4 ++++
 4 files changed, 41 insertions(+), 2 deletions(-)
diff --git a/parse-options.c b/parse-options.c
index f0098eb..079616a 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -278,6 +278,8 @@ static int parse_nodash_opt(struct parse_opt_ctx_t *p, const char *arg,
 			continue;
 		if (options->short_name == arg[0] && arg[1] == '\0')
 			return get_value(p, options, OPT_SHORT);
+		if (options->long_name && !strcmp(options->long_name, arg))
+			return get_value(p, options, OPT_SHORT);
 	}
 	return -2;
 }
@@ -314,8 +316,7 @@ static void parse_options_check(const struct option *opts)
 		if (opts->flags & PARSE_OPT_NODASH &&
 		    ((opts->flags & PARSE_OPT_OPTARG) ||
 		     !(opts->flags & PARSE_OPT_NOARG) ||
-		     !(opts->flags & PARSE_OPT_NONEG) ||
-		     opts->long_name))
+		     !(opts->flags & PARSE_OPT_NONEG)))
 			err |= optbug(opts, "uses feature "
 					"not supported for dashless options");
 		switch (opts->type) {
diff --git a/parse-options.h b/parse-options.h
index 2e811dc..9267d46 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -123,6 +123,9 @@ struct option {
 #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), \
 				      PARSE_OPT_NOARG, NULL, (b) }
+#define OPT_SUBCOMMAND(l, v, h, i)  { OPTION_BIT, 0, (l), (v), NULL, (h), \
+				      PARSE_OPT_NONEG | PARSE_OPT_NOARG | \
+				      PARSE_OPT_NODASH | PARSE_OPT_HIDDEN, NULL, (i) }
 #define OPT_NEGBIT(s, l, v, h, b)   { OPTION_NEGBIT, (s), (l), (v), NULL, \
 				      (h), PARSE_OPT_NOARG, NULL, (b) }
 #define OPT_COUNTUP(s, l, v, h)     { OPTION_COUNTUP, (s), (l), (v), NULL, \
diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
index a1e4616..47a402e 100755
--- a/t/t0040-parse-options.sh
+++ b/t/t0040-parse-options.sh
@@ -55,6 +55,7 @@ mv expect expect.err
 
 cat > expect << EOF
 boolean: 2
+subcommand: 0
 integer: 1729
 timestamp: 0
 string: 123
@@ -74,6 +75,7 @@ test_expect_success 'short options' '
 
 cat > expect << EOF
 boolean: 2
+subcommand: 0
 integer: 1729
 timestamp: 0
 string: 321
@@ -103,6 +105,7 @@ test_expect_success 'missing required value' '
 
 cat > expect << EOF
 boolean: 1
+subcommand: 0
 integer: 13
 timestamp: 0
 string: 123
@@ -125,6 +128,7 @@ test_expect_success 'intermingled arguments' '
 
 cat > expect << EOF
 boolean: 0
+subcommand: 0
 integer: 2
 timestamp: 0
 string: (not set)
@@ -154,6 +158,7 @@ test_expect_success 'ambiguously abbreviated option' '
 
 cat > expect << EOF
 boolean: 0
+subcommand: 0
 integer: 0
 timestamp: 0
 string: 123
@@ -182,6 +187,7 @@ test_expect_success 'detect possible typos' '
 
 cat > expect <<EOF
 boolean: 0
+subcommand: 0
 integer: 0
 timestamp: 0
 string: (not set)
@@ -201,6 +207,7 @@ test_expect_success 'keep some options as arguments' '
 
 cat > expect <<EOF
 boolean: 0
+subcommand: 0
 integer: 0
 timestamp: 1
 string: default
@@ -222,6 +229,7 @@ test_expect_success 'OPT_DATE() and OPT_SET_PTR() work' '
 cat > expect <<EOF
 Callback: "four", 0
 boolean: 5
+subcommand: 0
 integer: 4
 timestamp: 0
 string: (not set)
@@ -250,6 +258,7 @@ test_expect_success 'OPT_CALLBACK() and callback errors work' '
 
 cat > expect <<EOF
 boolean: 1
+subcommand: 0
 integer: 23
 timestamp: 0
 string: (not set)
@@ -274,6 +283,7 @@ test_expect_success 'OPT_NEGBIT() and OPT_SET_INT() work' '
 
 cat > expect <<EOF
 boolean: 6
+subcommand: 0
 integer: 0
 timestamp: 0
 string: (not set)
@@ -304,6 +314,26 @@ test_expect_success 'OPT_BOOLEAN() with PARSE_OPT_NODASH works' '
 
 cat > expect <<EOF
 boolean: 0
+subcommand: 4
+integer: 0
+timestamp: 0
+string: (not set)
+abbrev: 7
+verbose: 0
+quiet: no
+dry run: no
+file: (not set)
+EOF
+
+test_expect_success 'OPT_SUBCOMMAND() works' '
+	test-parse-options sub4 > output 2> output.err &&
+	test ! -s output.err &&
+	test_cmp expect output
+'
+
+cat > expect <<EOF
+boolean: 0
+subcommand: 0
 integer: 12345
 timestamp: 0
 string: (not set)
@@ -322,6 +352,7 @@ test_expect_success 'OPT_NUMBER_CALLBACK() works' '
 
 cat >expect <<EOF
 boolean: 0
+subcommand: 0
 integer: 0
 timestamp: 0
 string: (not set)
diff --git a/test-parse-options.c b/test-parse-options.c
index 36487c4..8d5fcd4 100644
--- a/test-parse-options.c
+++ b/test-parse-options.c
@@ -3,6 +3,7 @@
 #include "string-list.h"
 
 static int boolean = 0;
+static int subcommand = 0;
 static int integer = 0;
 static unsigned long timestamp;
 static int abbrev = 7;
@@ -40,6 +41,8 @@ int main(int argc, const char **argv)
 		OPT_BOOLEAN('b', "boolean", &boolean, "get a boolean"),
 		OPT_BIT('4', "or4", &boolean,
 			"bitwise-or boolean with ...0100", 4),
+		OPT_SUBCOMMAND("sub4", &subcommand,
+			"bitwise-or subcommand with ...0100", 4),
 		OPT_NEGBIT(0, "neg-or4", &boolean, "same as --no-or4", 4),
 		OPT_GROUP(""),
 		OPT_INTEGER('i', "integer", &integer, "get a integer"),
@@ -80,6 +83,7 @@ int main(int argc, const char **argv)
 	argc = parse_options(argc, argv, prefix, options, usage, 0);
 
 	printf("boolean: %d\n", boolean);
+	printf("subcommand: %d\n", subcommand);
 	printf("integer: %u\n", integer);
 	printf("timestamp: %lu\n", timestamp);
 	printf("string: %s\n", string ? string : "(not set)");
-- 
1.7.7.3
Previous: Ramkumar RamachandraNext: Jonathan Nieder
Message 2 of 50 in “Fix '&&' chaining in tests”
  1. 0/6 Fix '&&' chaining in testsRamkumar Ramachandra, Dec 8, 2011
  2. 1/2 parse-options: introduce OPT_SUBCOMMANDRamkumar Ramachandra, Dec 8, 2011
  3. Jonathan NiederDec 8, 2011
  4. Ramkumar RamachandraDec 8, 2011
  5. 1/6 t3040 (subprojects-basic): modernize styleRamkumar Ramachandra, Dec 8, 2011
  6. Jonathan NiederDec 8, 2011
  7. Ramkumar RamachandraDec 9, 2011
  8. Junio C HamanoDec 9, 2011
  9. Ramkumar RamachandraDec 9, 2011
  10. 2/2 bundle: rewrite builtin to use parse-optionsRamkumar Ramachandra, Dec 8, 2011
  11. Jonathan NiederDec 8, 2011
  12. Ramkumar RamachandraDec 8, 2011
  13. Jonathan NiederDec 8, 2011
  14. Ramkumar RamachandraDec 8, 2011
  15. Jonathan NiederDec 8, 2011
  16. Ramkumar RamachandraDec 8, 2011
  17. Junio C HamanoDec 8, 2011
  18. Jakub NarebskiDec 9, 2011
  19. Junio C HamanoDec 9, 2011
  20. 0/2 Improve git-bundle builtinRamkumar Ramachandra, Dec 15, 2011
  21. 1/2 t5704 (bundle): rewrite for larger coverageRamkumar Ramachandra, Dec 15, 2011
  22. Jonathan NiederDec 15, 2011
  23. 2/2 bundle: rewrite builtin to use parse-optionsRamkumar Ramachandra, Dec 15, 2011
  24. Jonathan NiederDec 15, 2011
  25. Jonathan NiederDec 15, 2011
  26. Junio C HamanoDec 15, 2011
  27. 2/6 t3030 (merge-recursive): use test_expect_codeRamkumar Ramachandra, Dec 8, 2011
  28. 3/6 t1006 (cat-file): use test_cmpRamkumar Ramachandra, Dec 8, 2011
  29. Matthieu MoyDec 8, 2011
  30. Ramkumar RamachandraDec 8, 2011
  31. Matthieu MoyDec 8, 2011
  32. Jonathan NiederDec 8, 2011
  33. 4/6 t3200 (branch): fix '&&' chainingRamkumar Ramachandra, Dec 8, 2011
  34. Jonathan NiederDec 8, 2011
  35. 5/6 t1510 (worktree): fix '&&' chainingRamkumar Ramachandra, Dec 8, 2011
  36. Jonathan NiederDec 8, 2011
  37. Junio C HamanoDec 9, 2011
  38. 6/6 test: fix '&&' chainingRamkumar Ramachandra, Dec 8, 2011
  39. Jonathan NiederDec 8, 2011
  40. Junio C HamanoDec 8, 2011
  41. Ramkumar RamachandraDec 9, 2011
  42. 0/6 Fix '&&' chaining in testsRamkumar Ramachandra, Dec 9, 2011
  43. 1/6 t3040 (subprojects-basic): fix '&&' chaining, modernize styleRamkumar Ramachandra, Dec 9, 2011
  44. 2/6 t3030 (merge-recursive): use test_expect_codeRamkumar Ramachandra, Dec 9, 2011
  45. 3/6 t1006 (cat-file): use test_cmpRamkumar Ramachandra, Dec 9, 2011
  46. Junio C HamanoDec 9, 2011
  47. Ramkumar RamachandraDec 9, 2011
  48. 4/6 t3200 (branch): fix '&&' chainingRamkumar Ramachandra, Dec 9, 2011
  49. 5/6 t1510 (worktree): fix '&&' chainingRamkumar Ramachandra, Dec 9, 2011
  50. 6/6 tests: fix '&&' chainingRamkumar Ramachandra, Dec 9, 2011

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.