From 9bab5b6061f1bc8ca54f8ac145f4f88c644e3bc4 Mon Sep 17 00:00:00 2001
From: Ilya Bobyr <ilya.bobyr@gmail.com>
Date: Sat, 22 Mar 2014 02:47:34 -0700
Subject: [PATCH 1/2] rev-parse --parseopt: option argument name hints

Built-in commands can specify names for option arguments when usage text
is generated for a command.  sh based commands should be able to do the
same.

Option argument name hint is any text that comes after [*=?!] after the
argument name up to the first whitespace.

Signed-off-by: Ilya Bobyr <ilya.bobyr@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/git-rev-parse.txt | 34 +++++++++++++++++++++++++++++++--
 builtin/rev-parse.c             | 13 ++++++++++++-
 t/t1502-rev-parse-parseopt.sh   | 20 +++++++++++++++++++
 3 files changed, 64 insertions(+), 3 deletions(-)

diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index 0d2cdcde556..e05e6b35939 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -284,13 +284,13 @@ Input Format
 
 'git rev-parse --parseopt' input format is fully text based. It has two parts,
 separated by a line that contains only `--`. The lines before the separator
-(should be more than one) are used for the usage.
+(should be one or more) are used for the usage.
 The lines after the separator describe the options.
 
 Each line of options has this format:
 
 ------------
-<opt_spec><flags>* SP+ help LF
+<opt_spec><flags>*<arg_hint>? SP+ help LF
 ------------
 
 `<opt_spec>`::
@@ -313,6 +313,12 @@ Each line of options has this format:
 
 	* Use `!` to not make the corresponding negated long option available.
 
+`<arg_hint>`::
+	`<arg_hint>`, if specified, is used as a name of the argument in the
+	help output, for options that take arguments. `<arg_hint>` is
+	terminated by the first whitespace. When you need to use space in the
+	argument hint use dash instead.
+
 The remainder of the line, after stripping the spaces, is used
 as the help associated to the option.
 
@@ -333,6 +339,8 @@ h,help    show the help
 
 foo       some nifty option --foo
 bar=      some cool option --bar with an argument
+baz=arg   another cool option --baz with a named argument
+qux?path  qux may take a path argument but has meaning by itself
 
   An option group Header
 C?        option C with an optional argument"
@@ -340,6 +348,28 @@ C?        option C with an optional argument"
 eval "$(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)"
 ------------
 
+
+Usage text
+~~~~~~~~~~
+
+When `"$@"` is `-h` or `--help` in the above example, the following
+usage text would be shown:
+
+------------
+usage: some-command [options] <args>...
+
+    some-command does foo and bar!
+
+    -h, --help            show the help
+    --foo                 some nifty option --foo
+    --bar ...             some cool option --bar with an argument
+    --bar <arg>           another cool option --baz with a named argument
+    --qux[=<path>]        qux may take a path argument but has meaning by itself
+
+An option group Header
+    -C[...]               option C with an optional argument
+------------
+
 SQ-QUOTE
 --------
 
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 45901df3710..1a6122d3ae2 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -395,9 +395,10 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
 		usage[unb++] = strbuf_detach(&sb, NULL);
 	}
 
-	/* parse: (<short>|<short>,<long>|<long>)[=?]? SP+ <help> */
+	/* parse: (<short>|<short>,<long>|<long>)[*=?!]*<arghint>? SP+ <help> */
 	while (strbuf_getline(&sb, stdin, '\n') != EOF) {
 		const char *s;
+		const char *end;
 		struct option *o;
 
 		if (!sb.len)
@@ -419,6 +420,16 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
 		o->value = &parsed;
 		o->flags = PARSE_OPT_NOARG;
 		o->callback = &parseopt_dump;
+
+		/* Possible argument name hint */
+		end = s;
+		while (s > sb.buf && strchr("*=?!", s[-1]) == NULL)
+			--s;
+		if (s != sb.buf && s != end)
+			o->argh = xmemdupz(s, end - s);
+		if (s == sb.buf)
+			s = end;
+
 		while (s > sb.buf && strchr("*=?!", s[-1])) {
 			switch (*--s) {
 			case '=':
diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh
index 83b1300cef9..960adf56af0 100755
--- a/t/t1502-rev-parse-parseopt.sh
+++ b/t/t1502-rev-parse-parseopt.sh
@@ -18,6 +18,17 @@ An option group Header
     -C[...]               option C with an optional argument
     -d, --data[=...]      short and long option with an optional argument
 
+Argument hints
+    -b <arg>              short option required argument
+    --bar2 <arg>          long option required argument
+    -e, --fuz <with-space>
+			  short and long option required argument
+    -s[<some>]            short option optional argument
+    --long[=<data>]       long option optional argument
+    -g, --fluf[=<path>]   short and long option optional argument
+    --longest <very-long-argument-hint>
+			  a very long argument hint
+
 Extras
     --extra1              line above used to cause a segfault but no longer does
 
@@ -39,6 +50,15 @@ b,baz     a short and long option
 C?        option C with an optional argument
 d,data?   short and long option with an optional argument
 
+ Argument hints
+b=arg     short option required argument
+bar2=arg  long option required argument
+e,fuz=with-space  short and long option required argument
+s?some    short option optional argument
+long?data long option optional argument
+g,fluf?path     short and long option optional argument
+longest=very-long-argument-hint  a very long argument hint
+
 Extras
 extra1    line above used to cause a segfault but no longer does
 EOF

From ce7f8745aa773dfe2fc0a1b8c327b50c7ce4a31e Mon Sep 17 00:00:00 2001
From: Junio C Hamano <gitster@pobox.com>
Date: Sun, 23 Mar 2014 15:26:36 -0700
Subject: [PATCH 2/2] t1502: protect runs of SPs used in the indentation

The expected output from the argument help use runs of SPs to align
the description of each option; a careless use of --whitespace=fix
can turn leading parts of them into appropriate number of HTs.
Prevent such a breakage by prefixing all the expected lines with
leading vertical bars in the original and stripping them with a
small sed script.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 t/t1502-rev-parse-parseopt.sh | 112 +++++++++++++++++-----------------
 1 file changed, 56 insertions(+), 56 deletions(-)

diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh
index 960adf56af0..922423e7d01 100755
--- a/t/t1502-rev-parse-parseopt.sh
+++ b/t/t1502-rev-parse-parseopt.sh
@@ -3,64 +3,64 @@
 test_description='test git rev-parse --parseopt'
 . ./test-lib.sh
 
-cat > expect <<\END_EXPECT
-cat <<\EOF
-usage: some-command [options] <args>...
-
-    some-command does foo and bar!
-
-    -h, --help            show the help
-    --foo                 some nifty option --foo
-    --bar ...             some cool option --bar with an argument
-    -b, --baz             a short and long option
-
-An option group Header
-    -C[...]               option C with an optional argument
-    -d, --data[=...]      short and long option with an optional argument
-
-Argument hints
-    -b <arg>              short option required argument
-    --bar2 <arg>          long option required argument
-    -e, --fuz <with-space>
-			  short and long option required argument
-    -s[<some>]            short option optional argument
-    --long[=<data>]       long option optional argument
-    -g, --fluf[=<path>]   short and long option optional argument
-    --longest <very-long-argument-hint>
-			  a very long argument hint
-
-Extras
-    --extra1              line above used to cause a segfault but no longer does
-
-EOF
+sed -e 's/^|//' >expect <<\END_EXPECT
+|cat <<\EOF
+|usage: some-command [options] <args>...
+|
+|    some-command does foo and bar!
+|
+|    -h, --help            show the help
+|    --foo                 some nifty option --foo
+|    --bar ...             some cool option --bar with an argument
+|    -b, --baz             a short and long option
+|
+|An option group Header
+|    -C[...]               option C with an optional argument
+|    -d, --data[=...]      short and long option with an optional argument
+|
+|Argument hints
+|    -b <arg>              short option required argument
+|    --bar2 <arg>          long option required argument
+|    -e, --fuz <with-space>
+|                          short and long option required argument
+|    -s[<some>]            short option optional argument
+|    --long[=<data>]       long option optional argument
+|    -g, --fluf[=<path>]   short and long option optional argument
+|    --longest <very-long-argument-hint>
+|                          a very long argument hint
+|
+|Extras
+|    --extra1              line above used to cause a segfault but no longer does
+|
+|EOF
 END_EXPECT
 
-cat > optionspec << EOF
-some-command [options] <args>...
-
-some-command does foo and bar!
---
-h,help    show the help
-
-foo       some nifty option --foo
-bar=      some cool option --bar with an argument
-b,baz     a short and long option
-
- An option group Header
-C?        option C with an optional argument
-d,data?   short and long option with an optional argument
-
- Argument hints
-b=arg     short option required argument
-bar2=arg  long option required argument
-e,fuz=with-space  short and long option required argument
-s?some    short option optional argument
-long?data long option optional argument
-g,fluf?path     short and long option optional argument
-longest=very-long-argument-hint  a very long argument hint
-
-Extras
-extra1    line above used to cause a segfault but no longer does
+sed -e 's/^|//' >optionspec <<\EOF
+|some-command [options] <args>...
+|
+|some-command does foo and bar!
+|--
+|h,help    show the help
+|
+|foo       some nifty option --foo
+|bar=      some cool option --bar with an argument
+|b,baz     a short and long option
+|
+| An option group Header
+|C?        option C with an optional argument
+|d,data?   short and long option with an optional argument
+|
+| Argument hints
+|b=arg     short option required argument
+|bar2=arg  long option required argument
+|e,fuz=with-space  short and long option required argument
+|s?some    short option optional argument
+|long?data long option optional argument
+|g,fluf?path     short and long option optional argument
+|longest=very-long-argument-hint  a very long argument hint
+|
+|Extras
+|extra1    line above used to cause a segfault but no longer does
 EOF
 
 test_expect_success 'test --parseopt help output' '