Skip to content

Commit 24b9cb1

Browse files
committed
Merge branch 'ib/rev-parse-parseopt-argh'
Teaches the "rev-parse --parseopt" mechanism used by scripted Porcelains to parse command line options and give help text how to supply argv-help (the placeholder string for an option parameter, e.g. "key-id" in "--gpg-sign=<key-id>"). * ib/rev-parse-parseopt-argh: t1502: protect runs of SPs used in the indentation rev-parse --parseopt: option argument name hints
2 parents a79cbc1 + ce7f874 commit 24b9cb1

File tree

3 files changed

+100
-39
lines changed

3 files changed

+100
-39
lines changed

Documentation/git-rev-parse.txt

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,13 +284,13 @@ Input Format
284284

285285
'git rev-parse --parseopt' input format is fully text based. It has two parts,
286286
separated by a line that contains only `--`. The lines before the separator
287-
(should be more than one) are used for the usage.
287+
(should be one or more) are used for the usage.
288288
The lines after the separator describe the options.
289289

290290
Each line of options has this format:
291291

292292
------------
293-
<opt_spec><flags>* SP+ help LF
293+
<opt_spec><flags>*<arg_hint>? SP+ help LF
294294
------------
295295

296296
`<opt_spec>`::
@@ -313,6 +313,12 @@ Each line of options has this format:
313313

314314
* Use `!` to not make the corresponding negated long option available.
315315

316+
`<arg_hint>`::
317+
`<arg_hint>`, if specified, is used as a name of the argument in the
318+
help output, for options that take arguments. `<arg_hint>` is
319+
terminated by the first whitespace. When you need to use space in the
320+
argument hint use dash instead.
321+
316322
The remainder of the line, after stripping the spaces, is used
317323
as the help associated to the option.
318324

@@ -333,13 +339,37 @@ h,help show the help
333339

334340
foo some nifty option --foo
335341
bar= some cool option --bar with an argument
342+
baz=arg another cool option --baz with a named argument
343+
qux?path qux may take a path argument but has meaning by itself
336344

337345
An option group Header
338346
C? option C with an optional argument"
339347

340348
eval "$(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)"
341349
------------
342350

351+
352+
Usage text
353+
~~~~~~~~~~
354+
355+
When `"$@"` is `-h` or `--help` in the above example, the following
356+
usage text would be shown:
357+
358+
------------
359+
usage: some-command [options] <args>...
360+
361+
some-command does foo and bar!
362+
363+
-h, --help show the help
364+
--foo some nifty option --foo
365+
--bar ... some cool option --bar with an argument
366+
--bar <arg> another cool option --baz with a named argument
367+
--qux[=<path>] qux may take a path argument but has meaning by itself
368+
369+
An option group Header
370+
-C[...] option C with an optional argument
371+
------------
372+
343373
SQ-QUOTE
344374
--------
345375

builtin/rev-parse.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,9 +395,10 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
395395
usage[unb++] = strbuf_detach(&sb, NULL);
396396
}
397397

398-
/* parse: (<short>|<short>,<long>|<long>)[=?]? SP+ <help> */
398+
/* parse: (<short>|<short>,<long>|<long>)[*=?!]*<arghint>? SP+ <help> */
399399
while (strbuf_getline(&sb, stdin, '\n') != EOF) {
400400
const char *s;
401+
const char *end;
401402
struct option *o;
402403

403404
if (!sb.len)
@@ -419,6 +420,16 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
419420
o->value = &parsed;
420421
o->flags = PARSE_OPT_NOARG;
421422
o->callback = &parseopt_dump;
423+
424+
/* Possible argument name hint */
425+
end = s;
426+
while (s > sb.buf && strchr("*=?!", s[-1]) == NULL)
427+
--s;
428+
if (s != sb.buf && s != end)
429+
o->argh = xmemdupz(s, end - s);
430+
if (s == sb.buf)
431+
s = end;
432+
422433
while (s > sb.buf && strchr("*=?!", s[-1])) {
423434
switch (*--s) {
424435
case '=':

t/t1502-rev-parse-parseopt.sh

Lines changed: 56 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,44 +3,64 @@
33
test_description='test git rev-parse --parseopt'
44
. ./test-lib.sh
55

6-
cat > expect <<\END_EXPECT
7-
cat <<\EOF
8-
usage: some-command [options] <args>...
9-
10-
some-command does foo and bar!
11-
12-
-h, --help show the help
13-
--foo some nifty option --foo
14-
--bar ... some cool option --bar with an argument
15-
-b, --baz a short and long option
16-
17-
An option group Header
18-
-C[...] option C with an optional argument
19-
-d, --data[=...] short and long option with an optional argument
20-
21-
Extras
22-
--extra1 line above used to cause a segfault but no longer does
23-
24-
EOF
6+
sed -e 's/^|//' >expect <<\END_EXPECT
7+
|cat <<\EOF
8+
|usage: some-command [options] <args>...
9+
|
10+
| some-command does foo and bar!
11+
|
12+
| -h, --help show the help
13+
| --foo some nifty option --foo
14+
| --bar ... some cool option --bar with an argument
15+
| -b, --baz a short and long option
16+
|
17+
|An option group Header
18+
| -C[...] option C with an optional argument
19+
| -d, --data[=...] short and long option with an optional argument
20+
|
21+
|Argument hints
22+
| -b <arg> short option required argument
23+
| --bar2 <arg> long option required argument
24+
| -e, --fuz <with-space>
25+
| short and long option required argument
26+
| -s[<some>] short option optional argument
27+
| --long[=<data>] long option optional argument
28+
| -g, --fluf[=<path>] short and long option optional argument
29+
| --longest <very-long-argument-hint>
30+
| a very long argument hint
31+
|
32+
|Extras
33+
| --extra1 line above used to cause a segfault but no longer does
34+
|
35+
|EOF
2536
END_EXPECT
2637

27-
cat > optionspec << EOF
28-
some-command [options] <args>...
29-
30-
some-command does foo and bar!
31-
--
32-
h,help show the help
33-
34-
foo some nifty option --foo
35-
bar= some cool option --bar with an argument
36-
b,baz a short and long option
37-
38-
An option group Header
39-
C? option C with an optional argument
40-
d,data? short and long option with an optional argument
41-
42-
Extras
43-
extra1 line above used to cause a segfault but no longer does
38+
sed -e 's/^|//' >optionspec <<\EOF
39+
|some-command [options] <args>...
40+
|
41+
|some-command does foo and bar!
42+
|--
43+
|h,help show the help
44+
|
45+
|foo some nifty option --foo
46+
|bar= some cool option --bar with an argument
47+
|b,baz a short and long option
48+
|
49+
| An option group Header
50+
|C? option C with an optional argument
51+
|d,data? short and long option with an optional argument
52+
|
53+
| Argument hints
54+
|b=arg short option required argument
55+
|bar2=arg long option required argument
56+
|e,fuz=with-space short and long option required argument
57+
|s?some short option optional argument
58+
|long?data long option optional argument
59+
|g,fluf?path short and long option optional argument
60+
|longest=very-long-argument-hint a very long argument hint
61+
|
62+
|Extras
63+
|extra1 line above used to cause a segfault but no longer does
4464
EOF
4565

4666
test_expect_success 'test --parseopt help output' '

0 commit comments

Comments
 (0)