{"thread":{"id":"36035","subject":"[PATCH] rev-parse --parseopt: option argument name hints","startedAt":"2014-03-03T10:32:20Z","lastAt":"2014-03-24T17:52:05Z","messageCount":23,"participants":["Ilya Bobyr","Junio C Hamano","Eric Sunshine"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"235866","messageId":"1393842740-4628-1-git-send-email-ilya.bobyr@gmail.com","threadId":"36035","inReplyTo":null,"subject":"[PATCH] rev-parse --parseopt: option argument name hints","fromName":"Ilya Bobyr","fromEmail":"ilya.bobyr@gmail.com","sentAt":"2014-03-03T10:32:20Z","receivedAt":"2014-03-03T10:32:20Z","isPatch":true,"sender":{"key":"ilya.bobyr@gmail.com","avatar":"https://avatars.githubusercontent.com/u/694419?v=4"},"body":"Built-in commands can specify names for option arguments, that are shown\nwhen usage text is generated for the command.  sh based commands should\nbe able to do the same.\n\nOption argument name hint is any text that comes after [*=?!] after the\nargument name up to the first whitespace.  Underscores are replaced with\nwhitespace.  It is unlikely that an underscore would be useful in the\nhint text.\n\nSigned-off-by: Ilya Bobyr <ilya.bobyr@gmail.com>\n---\n Documentation/git-rev-parse.txt |   11 +++++++++--\n builtin/rev-parse.c             |   17 ++++++++++++++++-\n t/t1502-rev-parse-parseopt.sh   |   20 ++++++++++++++++++++\n 3 files changed, 45 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt\nindex 0d2cdcd..4cb6e02 100644\n--- a/Documentation/git-rev-parse.txt\n+++ b/Documentation/git-rev-parse.txt\n@@ -284,13 +284,13 @@ Input Format\n \n 'git rev-parse --parseopt' input format is fully text based. It has two parts,\n separated by a line that contains only `--`. The lines before the separator\n-(should be more than one) are used for the usage.\n+(could be more than one) are used for the usage.\n The lines after the separator describe the options.\n \n Each line of options has this format:\n \n ------------\n-<opt_spec><flags>* SP+ help LF\n+<opt_spec><flags>*<argh>? SP+ help LF\n ------------\n \n `<opt_spec>`::\n@@ -313,6 +313,12 @@ Each line of options has this format:\n \n \t* Use `!` to not make the corresponding negated long option available.\n \n+`<argh>`::\n+\t`<argh>`, if specified, is used as a name of the argument, if the\n+\toption takes an argument. `<argh>` is terminated by the first\n+\twhitespace. Angle braces are added automatically.  Underscore symbols\n+\tare replaced with spaces.\n+\n The remainder of the line, after stripping the spaces, is used\n as the help associated to the option.\n \n@@ -333,6 +339,7 @@ h,help    show the help\n \n foo       some nifty option --foo\n bar=      some cool option --bar with an argument\n+baz=arg   another cool option --baz with an argument named <arg>\n \n   An option group Header\n C?        option C with an optional argument\"\ndiff --git a/builtin/rev-parse.c b/builtin/rev-parse.c\nindex aaeb611..83a769e 100644\n--- a/builtin/rev-parse.c\n+++ b/builtin/rev-parse.c\n@@ -395,9 +395,10 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)\n \t\tusage[unb++] = strbuf_detach(&sb, NULL);\n \t}\n \n-\t/* parse: (<short>|<short>,<long>|<long>)[=?]? SP+ <help> */\n+\t/* parse: (<short>|<short>,<long>|<long>)[*=?!]*<arghint>? SP+ <help> */\n \twhile (strbuf_getline(&sb, stdin, '\\n') != EOF) {\n \t\tconst char *s;\n+\t\tconst char *argh;\n \t\tstruct option *o;\n \n \t\tif (!sb.len)\n@@ -419,6 +420,20 @@ 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+\n+\t\t/* Possible argument name hint */\n+\t\targh = s;\n+\t\twhile (s > sb.buf && strchr(\"*=?!\", s[-1]) == NULL)\n+\t\t\t--s;\n+\t\tif (s != sb.buf && s != argh) {\n+\t\t\tchar *a;\n+\t\t\to->argh = a = xmemdupz(s, argh - s);\n+\t\t\twhile (a = strchr(a, '_'))\n+\t\t\t\t*a = ' ';\n+\t\t}\n+\t\tif (s == sb.buf)\n+\t\t\ts = argh;\n+\n \t\twhile (s > sb.buf && strchr(\"*=?!\", s[-1])) {\n \t\t\tswitch (*--s) {\n \t\t\tcase '=':\ndiff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh\nindex 83b1300..bf0db05 100755\n--- a/t/t1502-rev-parse-parseopt.sh\n+++ b/t/t1502-rev-parse-parseopt.sh\n@@ -18,6 +18,17 @@ An option group Header\n     -C[...]               option C with an optional argument\n     -d, --data[=...]      short and long option with an optional argument\n \n+Argument hints\n+    -b <arg>              short option required argument\n+    --bar2 <arg>          long option required argument\n+    -e, --fuz <with spaces>\n+                          short and long option required argument\n+    -s[<some>]            short option optional argument\n+    --long[=<data>]       long option optional argument\n+    -g, --fluf[=<path>]   short and long option optional argument\n+    --longest <a very long argument hint>\n+                          a very long argument hint\n+\n Extras\n     --extra1              line above used to cause a segfault but no longer does\n \n@@ -39,6 +50,15 @@ b,baz     a short and long option\n C?        option C with an optional argument\n d,data?   short and long option with an optional argument\n \n+ Argument hints\n+b=arg     short option required argument\n+bar2=arg  long option required argument\n+e,fuz=with_spaces  short and long option required argument\n+s?some    short option optional argument\n+long?data long option optional argument\n+g,fluf?path     short and long option optional argument\n+longest=a_very_long_argument_hint  a very long argument hint\n+\n Extras\n extra1    line above used to cause a segfault but no longer does\n EOF\n-- \n1.7.9\n"},{"id":"236022","messageId":"xmqqwqg9kbuk.fsf@gitster.dls.corp.google.com","threadId":"36035","inReplyTo":"1393842740-4628-1-git-send-email-ilya.bobyr@gmail.com","subject":"Re: [PATCH] rev-parse --parseopt: option argument name hints","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-03-04T19:22:43Z","receivedAt":"2014-03-04T19:22:43Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ilya Bobyr <ilya.bobyr@gmail.com> writes:\n\n> Built-in commands can specify names for option arguments, that are shown\n> when usage text is generated for the command.  sh based commands should\n> be able to do the same.\n>\n> Option argument name hint is any text that comes after [*=?!] after the\n> argument name up to the first whitespace.  Underscores are replaced with\n> whitespace.  It is unlikely that an underscore would be useful in the\n> hint text.\n>\n> Signed-off-by: Ilya Bobyr <ilya.bobyr@gmail.com>\n> ---\n>  Documentation/git-rev-parse.txt |   11 +++++++++--\n>  builtin/rev-parse.c             |   17 ++++++++++++++++-\n>  t/t1502-rev-parse-parseopt.sh   |   20 ++++++++++++++++++++\n>  3 files changed, 45 insertions(+), 3 deletions(-)\n>\n> diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt\n> index 0d2cdcd..4cb6e02 100644\n> --- a/Documentation/git-rev-parse.txt\n> +++ b/Documentation/git-rev-parse.txt\n> @@ -284,13 +284,13 @@ Input Format\n>  \n>  'git rev-parse --parseopt' input format is fully text based. It has two parts,\n>  separated by a line that contains only `--`. The lines before the separator\n> -(should be more than one) are used for the usage.\n> +(could be more than one) are used for the usage.\n\nGood spotting.  I think the original author meant to say there\nshould be at least one line to serve as the usage string, so\nupdating it to \"should be one or more\" may be more accurate, but\n\"could be more than one\" would also work.\n\n>  The lines after the separator describe the options.\n>  \n>  Each line of options has this format:\n>  \n>  ------------\n> -<opt_spec><flags>* SP+ help LF\n> +<opt_spec><flags>*<argh>? SP+ help LF\n>  ------------\n>  \n>  `<opt_spec>`::\n> @@ -313,6 +313,12 @@ Each line of options has this format:\n>  \n>  \t* Use `!` to not make the corresponding negated long option available.\n>  \n> +`<argh>`::\n> +\t`<argh>`, if specified, is used as a name of the argument, if the\n> +\toption takes an argument. `<argh>` is terminated by the first\n> +\twhitespace. Angle braces are added automatically.  Underscore symbols\n> +\tare replaced with spaces.\n\nI had a hard time understanding this \"Angle brackets are added\nautomatically\" one (obviously nobody wants extra angle brackets\nadded around option arguments given by the user), until I looked at\nthe addition of the test to realize that this description is only\nabout how it appears in the help output.  The description needs to\nbe clarified to avoid confusion.\n\n> @@ -333,6 +339,7 @@ h,help    show the help\n>  \n>  foo       some nifty option --foo\n>  bar=      some cool option --bar with an argument\n> +baz=arg   another cool option --baz with an argument named <arg>\n\nIt probably is better not to have \" named <arg>\" at the end here, as\nthat gives an apparent-but-false contradiction with the \"Angle\nbrackets are added *automatically*\" and confuse readers.  At least,\nit confused _this_ reader.\n\nAfter the \"eval\" in the existing example to parse the \"$@\" argument\nlist in this part of the documentation, it may be a good idea to say\nsomething like:\n\n\tThe above command, when \"$@\" is \"--help\", produces the\n\tfollowing help output:\n\n\t... sample output here ...\n\nto show the actual output.  That way, we can illustrate how input\n\"baz?arg description of baz\" is turned into \"--baz[=<arg>]\" output\nclearly (yes, I am suggesting to use '?' in the new example, not '='\nwhose usage is already shown in the existing example).\n\n> diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c\n> index aaeb611..83a769e 100644\n> --- a/builtin/rev-parse.c\n> +++ b/builtin/rev-parse.c\n> @@ -395,9 +395,10 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)\n>  \t\tusage[unb++] = strbuf_detach(&sb, NULL);\n>  \t}\n>  \n> -\t/* parse: (<short>|<short>,<long>|<long>)[=?]? SP+ <help> */\n> +\t/* parse: (<short>|<short>,<long>|<long>)[*=?!]*<arghint>? SP+ <help> */\n>  \twhile (strbuf_getline(&sb, stdin, '\\n') != EOF) {\n>  \t\tconst char *s;\n> +\t\tconst char *argh;\n\nLet's spell that variable name out, e.g. arg_hint or something.\n\n> diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh\n> index 83b1300..bf0db05 100755\n> --- a/t/t1502-rev-parse-parseopt.sh\n> +++ b/t/t1502-rev-parse-parseopt.sh\n> @@ -18,6 +18,17 @@ An option group Header\n>      -C[...]               option C with an optional argument\n>      -d, --data[=...]      short and long option with an optional argument\n>  \n> +Argument hints\n> +    -b <arg>              short option required argument\n> +    --bar2 <arg>          long option required argument\n> +    -e, --fuz <with spaces>\n> +                          short and long option required argument\n> +    -s[<some>]            short option optional argument\n> +    --long[=<data>]       long option optional argument\n> +    -g, --fluf[=<path>]   short and long option optional argument\n> +    --longest <a very long argument hint>\n> +                          a very long argument hint\n> +\n>  Extras\n>      --extra1              line above used to cause a segfault but no longer does\n>  \n> @@ -39,6 +50,15 @@ b,baz     a short and long option\n>  C?        option C with an optional argument\n>  d,data?   short and long option with an optional argument\n>  \n> + Argument hints\n> +b=arg     short option required argument\n> +bar2=arg  long option required argument\n> +e,fuz=with_spaces  short and long option required argument\n> +s?some    short option optional argument\n> +long?data long option optional argument\n> +g,fluf?path     short and long option optional argument\n> +longest=a_very_long_argument_hint  a very long argument hint\n> +\n\nNice.\n\nThanks.\n"},{"id":"236349","messageId":"531D51EC.6050503@gmail.com","threadId":"36035","inReplyTo":"xmqqwqg9kbuk.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH] rev-parse --parseopt: option argument name hints","fromName":"Ilya Bobyr","fromEmail":"ilya.bobyr@gmail.com","sentAt":"2014-03-10T05:47:24Z","receivedAt":"2014-03-10T05:47:24Z","isPatch":true,"sender":{"key":"ilya.bobyr@gmail.com","avatar":"https://avatars.githubusercontent.com/u/694419?v=4"},"body":"On 3/4/2014 11:22 AM, Junio C Hamano wrote:\n> Ilya Bobyr <ilya.bobyr@gmail.com> writes:\n>\n>> Built-in commands can specify names for option arguments, that are shown\n>> when usage text is generated for the command.  sh based commands should\n>> be able to do the same.\n>>\n>> Option argument name hint is any text that comes after [*=?!] after the\n>> argument name up to the first whitespace.  Underscores are replaced with\n>> whitespace.  It is unlikely that an underscore would be useful in the\n>> hint text.\n>>\n>> Signed-off-by: Ilya Bobyr <ilya.bobyr@gmail.com>\n>> ---\n>>   Documentation/git-rev-parse.txt |   11 +++++++++--\n>>   builtin/rev-parse.c             |   17 ++++++++++++++++-\n>>   t/t1502-rev-parse-parseopt.sh   |   20 ++++++++++++++++++++\n>>   3 files changed, 45 insertions(+), 3 deletions(-)\n>>\n>> diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt\n>> index 0d2cdcd..4cb6e02 100644\n>> --- a/Documentation/git-rev-parse.txt\n>> +++ b/Documentation/git-rev-parse.txt\n>> @@ -284,13 +284,13 @@ Input Format\n>>   \n>>   'git rev-parse --parseopt' input format is fully text based. It has two parts,\n>>   separated by a line that contains only `--`. The lines before the separator\n>> -(should be more than one) are used for the usage.\n>> +(could be more than one) are used for the usage.\n> Good spotting.  I think the original author meant to say there\n> should be at least one line to serve as the usage string, so\n> updating it to \"should be one or more\" may be more accurate, but\n> \"could be more than one\" would also work.\n\nChanged to \"should be one or more\".\n\n>>   The lines after the separator describe the options.\n>>   \n>>   Each line of options has this format:\n>>   \n>>   ------------\n>> -<opt_spec><flags>* SP+ help LF\n>> +<opt_spec><flags>*<argh>? SP+ help LF\n>>   ------------\n>>   \n>>   `<opt_spec>`::\n>> @@ -313,6 +313,12 @@ Each line of options has this format:\n>>   \n>>   \t* Use `!` to not make the corresponding negated long option available.\n>>   \n>> +`<argh>`::\n>> +\t`<argh>`, if specified, is used as a name of the argument, if the\n>> +\toption takes an argument. `<argh>` is terminated by the first\n>> +\twhitespace. Angle braces are added automatically.  Underscore symbols\n>> +\tare replaced with spaces.\n> I had a hard time understanding this \"Angle brackets are added\n> automatically\" one (obviously nobody wants extra angle brackets\n> added around option arguments given by the user), until I looked at\n> the addition of the test to realize that this description is only\n> about how it appears in the help output.  The description needs to\n> be clarified to avoid confusion.\n\nI've reworded some of the sentences.  I think it is better now.  Let me \nknow what you think.\n\n>> @@ -333,6 +339,7 @@ h,help    show the help\n>>   \n>>   foo       some nifty option --foo\n>>   bar=      some cool option --bar with an argument\n>> +baz=arg   another cool option --baz with an argument named <arg>\n> It probably is better not to have \" named <arg>\" at the end here, as\n> that gives an apparent-but-false contradiction with the \"Angle\n> brackets are added *automatically*\" and confuse readers.  At least,\n> it confused _this_ reader.\n\nI am not sure I understand what is confusing here.  But I removed the \" \nnamed <arg>\" part.\nIf there would be an example, I think, it is easy to understand how it \nworks.\n\n> After the \"eval\" in the existing example to parse the \"$@\" argument\n> list in this part of the documentation, it may be a good idea to say\n> something like:\n>\n> \tThe above command, when \"$@\" is \"--help\", produces the\n> \tfollowing help output:\n>\n> \t... sample output here ...\n>\n> to show the actual output.  That way, we can illustrate how input\n> \"baz?arg description of baz\" is turned into \"--baz[=<arg>]\" output\n> clearly (yes, I am suggesting to use '?' in the new example, not '='\n> whose usage is already shown in the existing example).\n\nDocumentation on the whole argument parsing is quite short, so, I \nthough, adding an example just to show how usage is generated would look \nlike I am trying to make this feature look important than it is :)\n\nI've added another section that shows usage text generated for the \nexample specification.\n\n>> diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c\n>> index aaeb611..83a769e 100644\n>> --- a/builtin/rev-parse.c\n>> +++ b/builtin/rev-parse.c\n>> @@ -395,9 +395,10 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)\n>>   \t\tusage[unb++] = strbuf_detach(&sb, NULL);\n>>   \t}\n>>   \n>> -\t/* parse: (<short>|<short>,<long>|<long>)[=?]? SP+ <help> */\n>> +\t/* parse: (<short>|<short>,<long>|<long>)[*=?!]*<arghint>? SP+ <help> */\n>>   \twhile (strbuf_getline(&sb, stdin, '\\n') != EOF) {\n>>   \t\tconst char *s;\n>> +\t\tconst char *argh;\n> Let's spell that variable name out, e.g. arg_hint or something.\n\nI was looking at the surrounding code for some style guidance, but most \nlocal variables have short names like \"s\", \"o\", \"onb\", \"osz\", \"sb\".\nThere are some that are longer.  So I was quite unsure here.\nAt the same time the target structure that holds the option description \ncalls this string \"argh\".\nAlso, this is not really an \"arg_hint\" but the end of it.  Argument name \nis actually between s and argh, if there is some.\nConsidering all that, \"argh\" seemed like an OK name.\n\nI've renamed it to \"end\".  It is used to remember possible end of the \nargument name in just one paragraph of code.\nComments above the paragraph clarifies what is been extracted.\nShould there be another \"parameter\" in the option specification, the \nsame variable could be used while parsing that one as well.\n\nLet me know if you what that to be \"arg_hint\", or \"arg_hint_end\", or \nanything else.\n\n>> diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh\n>> index 83b1300..bf0db05 100755\n>> --- a/t/t1502-rev-parse-parseopt.sh\n>> +++ b/t/t1502-rev-parse-parseopt.sh\n>> @@ -18,6 +18,17 @@ An option group Header\n>>       -C[...]               option C with an optional argument\n>>       -d, --data[=...]      short and long option with an optional argument\n>>   \n>> +Argument hints\n>> +    -b <arg>              short option required argument\n>> +    --bar2 <arg>          long option required argument\n>> +    -e, --fuz <with spaces>\n>> +                          short and long option required argument\n>> +    -s[<some>]            short option optional argument\n>> +    --long[=<data>]       long option optional argument\n>> +    -g, --fluf[=<path>]   short and long option optional argument\n>> +    --longest <a very long argument hint>\n>> +                          a very long argument hint\n>> +\n>>   Extras\n>>       --extra1              line above used to cause a segfault but no longer does\n>>   \n>> @@ -39,6 +50,15 @@ b,baz     a short and long option\n>>   C?        option C with an optional argument\n>>   d,data?   short and long option with an optional argument\n>>   \n>> + Argument hints\n>> +b=arg     short option required argument\n>> +bar2=arg  long option required argument\n>> +e,fuz=with_spaces  short and long option required argument\n>> +s?some    short option optional argument\n>> +long?data long option optional argument\n>> +g,fluf?path     short and long option optional argument\n>> +longest=a_very_long_argument_hint  a very long argument hint\n>> +\n> Nice.\n\nThanks :)\n\nP.S. Patch comes in the next message.\n"},{"id":"236350","messageId":"1394430907-6052-1-git-send-email-ilya.bobyr@gmail.com","threadId":"36035","inReplyTo":"531D51EC.6050503@gmail.com","subject":"[PATCH v2] rev-parse --parseopt: option argument name hints","fromName":"Ilya Bobyr","fromEmail":"ilya.bobyr@gmail.com","sentAt":"2014-03-10T05:55:07Z","receivedAt":"2014-03-10T05:55:07Z","isPatch":true,"sender":{"key":"ilya.bobyr@gmail.com","avatar":"https://avatars.githubusercontent.com/u/694419?v=4"},"body":"Built-in commands can specify names for option arguments when usage text\nis generated for a command.  sh based commands should be able to do the\nsame.\n\nOption argument name hint is any text that comes after [*=?!] after the\nargument name up to the first whitespace.  Underscores are replaced with\nwhitespace.  It is unlikely that an underscore would be useful in the\nhint text.\n\nSigned-off-by: Ilya Bobyr <ilya.bobyr@gmail.com>\n---\n Documentation/git-rev-parse.txt |   11 +++++++++--\n builtin/rev-parse.c             |   17 ++++++++++++++++-\n t/t1502-rev-parse-parseopt.sh   |   20 ++++++++++++++++++++\n 3 files changed, 45 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt\nindex 0d2cdcd..4cb6e02 100644\n--- a/Documentation/git-rev-parse.txt\n+++ b/Documentation/git-rev-parse.txt\n@@ -284,13 +284,13 @@ Input Format\n \n 'git rev-parse --parseopt' input format is fully text based. It has two parts,\n separated by a line that contains only `--`. The lines before the separator\n-(should be more than one) are used for the usage.\n+(could be more than one) are used for the usage.\n The lines after the separator describe the options.\n \n Each line of options has this format:\n \n ------------\n-<opt_spec><flags>* SP+ help LF\n+<opt_spec><flags>*<argh>? SP+ help LF\n ------------\n \n `<opt_spec>`::\n@@ -313,6 +313,12 @@ Each line of options has this format:\n \n \t* Use `!` to not make the corresponding negated long option available.\n \n+`<argh>`::\n+\t`<argh>`, if specified, is used as a name of the argument, if the\n+\toption takes an argument. `<argh>` is terminated by the first\n+\twhitespace. Angle braces are added automatically.  Underscore symbols\n+\tare replaced with spaces.\n+\n The remainder of the line, after stripping the spaces, is used\n as the help associated to the option.\n \n@@ -333,6 +339,7 @@ h,help    show the help\n \n foo       some nifty option --foo\n bar=      some cool option --bar with an argument\n+baz=arg   another cool option --baz with an argument named <arg>\n \n   An option group Header\n C?        option C with an optional argument\"\ndiff --git a/builtin/rev-parse.c b/builtin/rev-parse.c\nindex 45901df..7a58404 100644\n--- a/builtin/rev-parse.c\n+++ b/builtin/rev-parse.c\n@@ -395,9 +395,10 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)\n \t\tusage[unb++] = strbuf_detach(&sb, NULL);\n \t}\n \n-\t/* parse: (<short>|<short>,<long>|<long>)[=?]? SP+ <help> */\n+\t/* parse: (<short>|<short>,<long>|<long>)[*=?!]*<arghint>? SP+ <help> */\n \twhile (strbuf_getline(&sb, stdin, '\\n') != EOF) {\n \t\tconst char *s;\n+\t\tconst char *argh;\n \t\tstruct option *o;\n \n \t\tif (!sb.len)\n@@ -419,6 +420,20 @@ 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+\n+\t\t/* Possible argument name hint */\n+\t\targh = s;\n+\t\twhile (s > sb.buf && strchr(\"*=?!\", s[-1]) == NULL)\n+\t\t\t--s;\n+\t\tif (s != sb.buf && s != argh) {\n+\t\t\tchar *a;\n+\t\t\to->argh = a = xmemdupz(s, argh - s);\n+\t\t\twhile (a = strchr(a, '_'))\n+\t\t\t\t*a = ' ';\n+\t\t}\n+\t\tif (s == sb.buf)\n+\t\t\ts = argh;\n+\n \t\twhile (s > sb.buf && strchr(\"*=?!\", s[-1])) {\n \t\t\tswitch (*--s) {\n \t\t\tcase '=':\ndiff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh\nindex 83b1300..bf0db05 100755\n--- a/t/t1502-rev-parse-parseopt.sh\n+++ b/t/t1502-rev-parse-parseopt.sh\n@@ -18,6 +18,17 @@ An option group Header\n     -C[...]               option C with an optional argument\n     -d, --data[=...]      short and long option with an optional argument\n \n+Argument hints\n+    -b <arg>              short option required argument\n+    --bar2 <arg>          long option required argument\n+    -e, --fuz <with spaces>\n+                          short and long option required argument\n+    -s[<some>]            short option optional argument\n+    --long[=<data>]       long option optional argument\n+    -g, --fluf[=<path>]   short and long option optional argument\n+    --longest <a very long argument hint>\n+                          a very long argument hint\n+\n Extras\n     --extra1              line above used to cause a segfault but no longer does\n \n@@ -39,6 +50,15 @@ b,baz     a short and long option\n C?        option C with an optional argument\n d,data?   short and long option with an optional argument\n \n+ Argument hints\n+b=arg     short option required argument\n+bar2=arg  long option required argument\n+e,fuz=with_spaces  short and long option required argument\n+s?some    short option optional argument\n+long?data long option optional argument\n+g,fluf?path     short and long option optional argument\n+longest=a_very_long_argument_hint  a very long argument hint\n+\n Extras\n extra1    line above used to cause a segfault but no longer does\n EOF\n-- \n1.7.9\n"},{"id":"236446","messageId":"xmqqk3c1rfqj.fsf@gitster.dls.corp.google.com","threadId":"36035","inReplyTo":"531D51EC.6050503@gmail.com","subject":"Re: [PATCH] rev-parse --parseopt: option argument name hints","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-03-10T19:55:00Z","receivedAt":"2014-03-10T19:55:00Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ilya Bobyr <ilya.bobyr@gmail.com> writes:\n\n> On 3/4/2014 11:22 AM, Junio C Hamano wrote:\n>> Ilya Bobyr <ilya.bobyr@gmail.com> writes:\n>>> @@ -333,6 +339,7 @@ h,help    show the help\n>>>     foo       some nifty option --foo\n>>>   bar=      some cool option --bar with an argument\n>>> +baz=arg   another cool option --baz with an argument named <arg>\n>> It probably is better not to have \" named <arg>\" at the end here, as\n>> that gives an apparent-but-false contradiction with the \"Angle\n>> brackets are added *automatically*\" and confuse readers.  At least,\n>> it confused _this_ reader.\n>\n> I am not sure I understand what is confusing here.  But I removed the\n> \" named <arg>\" part.\n\nAfter reading \"Angle brackets are automatically given\", seeing that\nthe argument description has manually spelled \"<arg>\" gave me \"Huh?\".\n\nWithout \" named <arg>\" there is no such confusion.\n\n> If there would be an example, I think, it is easy to understand how it\n> works.\n\nOf course.  That is why I suggested to do without \" named <arg>\"\npart---I didn't mean to suggest not to add the example.  I also\nthink that you can demonstrate something other than '=' (whose usage\nis already shown with \"bar=\" above) here as well, but I think we can\ngo either way.\n\n>> After the \"eval\" in the existing example to parse the \"$@\" argument\n>> list in this part of the documentation, it may be a good idea to say\n>> something like:\n>>\n>> \tThe above command, when \"$@\" is \"--help\", produces the\n>> \tfollowing help output:\n>>\n>> \t... sample output here ...\n>>\n>> to show the actual output.  That way, we can illustrate how input\n>> \"baz?arg description of baz\" is turned into \"--baz[=<arg>]\" output\n>> clearly (yes, I am suggesting to use '?' in the new example, not '='\n>> whose usage is already shown in the existing example).\n>\n> Documentation on the whole argument parsing is quite short, so, I\n> though, adding an example just to show how usage is generated would\n> look like I am trying to make this feature look important than it is\n> :)\n\nYou already are by saying the \"Angle brackets are automatic\", aren't\nyou?\n\n> At the same time the target structure that holds the option\n> description calls this string \"argh\".\n\nOK, that is fine, then (I'd prefer a field name not to sound like\narrrgh, but that is an entirely different topic).\n\n> I've renamed it to \"end\".  It is used to remember possible end of the\n> argument name in just one paragraph of code.\n\nSounds good.\n"},{"id":"236519","messageId":"xmqq7g80r1pm.fsf@gitster.dls.corp.google.com","threadId":"36035","inReplyTo":"xmqqk3c1rfqj.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH] rev-parse --parseopt: option argument name hints","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-03-11T19:10:13Z","receivedAt":"2014-03-11T19:10:13Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n>> Documentation on the whole argument parsing is quite short, so, I\n>> though, adding an example just to show how usage is generated would\n>> look like I am trying to make this feature look important than it is\n>> :)\n>\n> You already are by saying the \"Angle brackets are automatic\", aren't\n> you?\n\nThat is, among the things --parseopt mode does, the above stresses\nwhat happens _only_ when it emits help text for items that use this\nfeature.\n"},{"id":"236563","messageId":"53200C1A.7070002@gmail.com","threadId":"36035","inReplyTo":"xmqq7g80r1pm.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH] rev-parse --parseopt: option argument name hints","fromName":"Ilya Bobyr","fromEmail":"ilya.bobyr@gmail.com","sentAt":"2014-03-12T07:26:18Z","receivedAt":"2014-03-12T07:26:18Z","isPatch":true,"sender":{"key":"ilya.bobyr@gmail.com","avatar":"https://avatars.githubusercontent.com/u/694419?v=4"},"body":"On 3/11/2014 12:10 PM, Junio C Hamano wrote:\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n>>> Documentation on the whole argument parsing is quite short, so, I\n>>> though, adding an example just to show how usage is generated would\n>>> look like I am trying to make this feature look important than it is\n>>> :)\n>> You already are by saying the \"Angle brackets are automatic\", aren't\n>> you?\n> That is, among the things --parseopt mode does, the above stresses\n> what happens _only_ when it emits help text for items that use this\n> feature.\n\n`argh' is used only while help text is generated.  So, there seems to be \nno way around it :)\nI was talking not about the automatic addition of angle brackets, but \nabout the documentation on `argh' in general.\nThe section where I've added a paragraph, is not specific to the help \noutput, but describes --parseopt.\nI though that an example just to describe `argh' while useful would look \na bit disproportional, compared to the amount of text on --parseopt.\n\nBut now that I've added a \"Usage text\" section to looks quite in place.\n\nI just realized that the second patch I sent did not contain the \nchanges.  Sorry about - I will resend it.\n\nI was also wondering about the possible next step(s).\nIf you like the patch will you just take it from the maillist and it \nwould appear in the next \"What's cooking in git.git\"?\nOr the process is different?\n"},{"id":"236584","messageId":"xmqq38innyjq.fsf@gitster.dls.corp.google.com","threadId":"36035","inReplyTo":"53200C1A.7070002@gmail.com","subject":"Re: [PATCH] rev-parse --parseopt: option argument name hints","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-03-12T16:59:05Z","receivedAt":"2014-03-12T16:59:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ilya Bobyr <ilya.bobyr@gmail.com> writes:\n\n> I though that an example just to describe `argh' while useful would\n> look a bit disproportional, compared to the amount of text on\n> --parseopt.\n>\n> But now that I've added a \"Usage text\" section to looks quite in place.\n\nGood thinking.\n\n> I was also wondering about the possible next step(s).  If you like\n> the patch will you just take it from the maillist and it would\n> appear in the next \"What's cooking in git.git\"?  Or the process is\n> different?\n\nIt goes more like this:\n\n - A topic that is in a good enough shape to be discussed and moved\n   forward is given its own topic branch and then merged to 'pu', so\n   that we do not forget.  The topic enters \"What's cooking\" at this\n   stage.\n\n - Discussion on the topic continues on the list, and the topic can\n   be replaced or built upon while it is still on 'pu' to polish it\n   further.\n\n   . We may see a grave issue with the change and may discard it\n     from 'pu'.  \n\n   . We may see a period of inaction after issues are pointed out\n     and/or improvements are suggested, which would cause the topic\n     marked as stalled; this may cause it to be eventually discarded\n     as \"abandoned\" if nobody cares deeply enough.\n\n - After a while, when it seems that we, collectively as the Git\n   development circle, agree that we would eventually want that\n   change in a released version in some future (not necessarily in\n   the upcoming release), the topic is merged to 'next', which is\n   the branch Git developers are expected to run in their daily\n   lives.\n\n    . We may see some updates that builds on the patches merged to\n      'next' so far to fix late issues discovered.\n\n    . We may see a grave issue with the change and may have to\n      revert & discard it from 'next'.\n\n - After a while, when the topic proves to be solid, it is merged to\n   'master', in preparation for the upcoming release.\n"},{"id":"237049","messageId":"53295D30.8090307@gmail.com","threadId":"36035","inReplyTo":"xmqq38innyjq.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH] rev-parse --parseopt: option argument name hints","fromName":"Ilya Bobyr","fromEmail":"ilya.bobyr@gmail.com","sentAt":"2014-03-19T09:02:40Z","receivedAt":"2014-03-19T09:02:40Z","isPatch":true,"sender":{"key":"ilya.bobyr@gmail.com","avatar":"https://avatars.githubusercontent.com/u/694419?v=4"},"body":"On 3/12/2014 9:59 AM, Junio C Hamano wrote:\n> Ilya Bobyr <ilya.bobyr@gmail.com> writes:\n>\n>> I though that an example just to describe `argh' while useful would\n>> look a bit disproportional, compared to the amount of text on\n>> --parseopt.\n>>\n>> But now that I've added a \"Usage text\" section to looks quite in place.\n> Good thinking.\n>\n>> I was also wondering about the possible next step(s).  If you like\n>> the patch will you just take it from the maillist and it would\n>> appear in the next \"What's cooking in git.git\"?  Or the process is\n>> different?\n> It goes more like this:\n\nThank you for all the details.\n\n>   - A topic that is in a good enough shape to be discussed and moved\n>     forward is given its own topic branch and then merged to 'pu', so\n>     that we do not forget.  The topic enters \"What's cooking\" at this\n>     stage.\n\nI can not find this particular patch in the latest \"What's cooking\" email.\nIs there something I can do?\nIt does not seems like there is a lot of interest, so I am not sure \nthere will be a lot of discussion.\nIt is a minor fix and considering the number of the emails on the list, \nI do not unexpected this kind of stuff to be very popular.\nBut it seems like a valid improvement to me.\nMaybe I am missing something?\n\nSame questions about this one:\n\n     [PATCH] gitk: replace SHA1 entry field on keyboard paste\n     http://www.mail-archive.com/git@vger.kernel.org/msg45040.html\n\nI think they are more or less similar, except that the second one is \njust trivial.\n\n>   - Discussion on the topic continues on the list, and the topic can\n>     be replaced or built upon while it is still on 'pu' to polish it\n>     further.\n>\n>     . We may see a grave issue with the change and may discard it\n>       from 'pu'.\n>\n>     . We may see a period of inaction after issues are pointed out\n>       and/or improvements are suggested, which would cause the topic\n>       marked as stalled; this may cause it to be eventually discarded\n>       as \"abandoned\" if nobody cares deeply enough.\n>\n>   - After a while, when it seems that we, collectively as the Git\n>     development circle, agree that we would eventually want that\n>     change in a released version in some future (not necessarily in\n>     the upcoming release), the topic is merged to 'next', which is\n>     the branch Git developers are expected to run in their daily\n>     lives.\n>\n>      . We may see some updates that builds on the patches merged to\n>        'next' so far to fix late issues discovered.\n>\n>      . We may see a grave issue with the change and may have to\n>        revert & discard it from 'next'.\n>\n>   - After a while, when the topic proves to be solid, it is merged to\n>     'master', in preparation for the upcoming release.\n>\n"},{"id":"237099","messageId":"xmqq61na3u2m.fsf@gitster.dls.corp.google.com","threadId":"36035","inReplyTo":"53295D30.8090307@gmail.com","subject":"Re: [PATCH] rev-parse --parseopt: option argument name hints","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-03-19T18:46:25Z","receivedAt":"2014-03-19T18:46:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ilya Bobyr <ilya.bobyr@gmail.com> writes:\n\n> I can not find this particular patch in the latest \"What's cooking\" email.\n> Is there something I can do?\n\nIIRC, I think I was waiting for the version with a new \"Usage text\"\nsection to the documentation you alluded to in this exchange\n($gmane/243924):\n\n    Ilya Bobyr <ilya.bobyr@gmail.com> writes:\n\n    > On 3/11/2014 12:10 PM, Junio C Hamano wrote:\n    >>\n    >>>> Documentation on the whole argument parsing is quite short, so,...\n    > ...\n    > I though that an example just to describe `argh' while useful would\n    > look a bit disproportional, compared to the amount of text on\n    > --parseopt.\n    >\n    > But now that I've added a \"Usage text\" section to looks quite in place.\n    >\n    > I just realized that the second patch I sent did not contain the\n    > changes.  Sorry about - I will resend it.\n\n> It does not seems like there is a lot of interest, so I am not sure\n> there will be a lot of discussion.\n> It is a minor fix and considering the number of the emails on the\n> list, I do not unexpected this kind of stuff to be very popular.\n> But it seems like a valid improvement to me.\n> Maybe I am missing something?\n\nYou did the right thing by sending a reminder message with a pointer\nto help others locate the original (like the one I am responding\nto), as nobody can keep up with a busy list traffic.\n\n> Same questions about this one:\n>\n>     [PATCH] gitk: replace SHA1 entry field on keyboard paste\n>     http://www.mail-archive.com/git@vger.kernel.org/msg45040.html\n>\n> I think they are more or less similar, except that the second one is\n> just trivial.\n\nI do not remember if I forwarded the patch to the area maintainer\nPaul Mackerras <paulus@samba.org>, but if I didn't please do so\nyourself.  The changes to gitk and git-gui come to me via their own\nproject repositories.\n"},{"id":"237147","messageId":"532AA923.6030409@gmail.com","threadId":"36035","inReplyTo":"xmqq61na3u2m.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH] rev-parse --parseopt: option argument name hints","fromName":"Ilya Bobyr","fromEmail":"ilya.bobyr@gmail.com","sentAt":"2014-03-20T08:38:59Z","receivedAt":"2014-03-20T08:38:59Z","isPatch":true,"sender":{"key":"ilya.bobyr@gmail.com","avatar":"https://avatars.githubusercontent.com/u/694419?v=4"},"body":"On 3/19/2014 11:46 AM, Junio C Hamano wrote:\n> Ilya Bobyr <ilya.bobyr@gmail.com> writes:\n>\n>> I can not find this particular patch in the latest \"What's cooking\" email.\n>> Is there something I can do?\n> IIRC, I think I was waiting for the version with a new \"Usage text\"\n> section to the documentation you alluded to in this exchange\n> ($gmane/243924):\n>\n>      Ilya Bobyr <ilya.bobyr@gmail.com> writes:\n>\n>      > On 3/11/2014 12:10 PM, Junio C Hamano wrote:\n>      >>\n>      >>>> Documentation on the whole argument parsing is quite short, so,...\n>      > ...\n>      > I though that an example just to describe `argh' while useful would\n>      > look a bit disproportional, compared to the amount of text on\n>      > --parseopt.\n>      >\n>      > But now that I've added a \"Usage text\" section to looks quite in place.\n>      >\n>      > I just realized that the second patch I sent did not contain the\n>      > changes.  Sorry about - I will resend it.\n\nOh %)\nI did sent it in the next minute.  And did receive a copy myself.\nBut it seems it never showed up in the list.\nI am still a bit new to the tools, maybe I did something wrong.\nWill try again :)\n\n>> It does not seems like there is a lot of interest, so I am not sure\n>> there will be a lot of discussion.\n>> It is a minor fix and considering the number of the emails on the\n>> list, I do not unexpected this kind of stuff to be very popular.\n>> But it seems like a valid improvement to me.\n>> Maybe I am missing something?\n> You did the right thing by sending a reminder message with a pointer\n> to help others locate the original (like the one I am responding\n> to), as nobody can keep up with a busy list traffic.\n\nThanks :)\n\n>> Same questions about this one:\n>>\n>>      [PATCH] gitk: replace SHA1 entry field on keyboard paste\n>>      http://www.mail-archive.com/git@vger.kernel.org/msg45040.html\n>>\n>> I think they are more or less similar, except that the second one is\n>> just trivial.\n> I do not remember if I forwarded the patch to the area maintainer\n> Paul Mackerras <paulus@samba.org>, but if I didn't please do so\n> yourself.  The changes to gitk and git-gui come to me via their own\n> project repositories.\n\nYou did and I even replied with additional details, that I should have \nincluded as a cover letter.\nI can see those messages in the web archive.\nIt seems that Paul Mackerras gitk repository is here: \ngit://ozlabs.org/~paulus/gitk.git\nAt least that is what is online.  I do not see the change in there.\nI will remind him about it.\n"},{"id":"237148","messageId":"1395305092-1928-1-git-send-email-ilya.bobyr@gmail.com","threadId":"36035","inReplyTo":"532AA923.6030409@gmail.com","subject":"[PATCH v3] rev-parse --parseopt: option argument name hints","fromName":"Ilya Bobyr","fromEmail":"ilya.bobyr@gmail.com","sentAt":"2014-03-20T08:44:52Z","receivedAt":"2014-03-20T08:44:52Z","isPatch":true,"sender":{"key":"ilya.bobyr@gmail.com","avatar":"https://avatars.githubusercontent.com/u/694419?v=4"},"body":"Built-in commands can specify names for option arguments when usage text\nis generated for a command.  sh based commands should be able to do the\nsame.\n\nOption argument name hint is any text that comes after [*=?!] after the\nargument name up to the first whitespace.  Underscores are replaced with\nwhitespace.  It is unlikely that an underscore would be useful in the\nhint text.\n\nSigned-off-by: Ilya Bobyr <ilya.bobyr@gmail.com>\n---\n Changed according to the last comments.  Added \"Usage text\" paragraph in the\n documentation and updated variable names.\n\n Documentation/git-rev-parse.txt |   34 ++++++++++++++++++++++++++++++++--\n builtin/rev-parse.c             |   17 ++++++++++++++++-\n t/t1502-rev-parse-parseopt.sh   |   20 ++++++++++++++++++++\n 3 files changed, 68 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt\nindex 0d2cdcd..b8aabc9 100644\n--- a/Documentation/git-rev-parse.txt\n+++ b/Documentation/git-rev-parse.txt\n@@ -284,13 +284,13 @@ Input Format\n \n 'git rev-parse --parseopt' input format is fully text based. It has two parts,\n separated by a line that contains only `--`. The lines before the separator\n-(should be more than one) are used for the usage.\n+(should be one or more) are used for the usage.\n The lines after the separator describe the options.\n \n Each line of options has this format:\n \n ------------\n-<opt_spec><flags>* SP+ help LF\n+<opt_spec><flags>*<arg_hint>? SP+ help LF\n ------------\n \n `<opt_spec>`::\n@@ -313,6 +313,12 @@ Each line of options has this format:\n \n \t* Use `!` to not make the corresponding negated long option available.\n \n+`<arg_hint>`::\n+\t`<arg_hing>`, if specified, is used as a name of the argument in the\n+\thelp output, for options that take arguments. `<arg_hint>` is\n+\tterminated by the first whitespace. When output the name is shown in\n+\tangle braces.  Underscore symbols are replaced with spaces.\n+\n The remainder of the line, after stripping the spaces, is used\n as the help associated to the option.\n \n@@ -333,6 +339,8 @@ h,help    show the help\n \n foo       some nifty option --foo\n bar=      some cool option --bar with an argument\n+baz=arg   another cool option --baz with a named argument\n+qux?path  qux may take a path argument but has meaning by itself\n \n   An option group Header\n C?        option C with an optional argument\"\n@@ -340,6 +348,28 @@ C?        option C with an optional argument\"\n eval \"$(echo \"$OPTS_SPEC\" | git rev-parse --parseopt -- \"$@\" || echo exit $?)\"\n ------------\n \n+\n+Usage text\n+~~~~~~~~~~\n+\n+When \"$@\" is \"-h\" or \"--help\" the above example would produce the following\n+usage text:\n+\n+------------\n+usage: some-command [options] <args>...\n+\n+    some-command does foo and bar!\n+\n+    -h, --help            show the help\n+    --foo                 some nifty option --foo\n+    --bar ...             some cool option --bar with an argument\n+    --bar <arg>           another cool option --baz with a named argument\n+    --qux[=<path>]        qux may take a path argument but has meaning by itself\n+\n+An option group Header\n+    -C[...]               option C with an optional argument\n+------------\n+\n SQ-QUOTE\n --------\n \ndiff --git a/builtin/rev-parse.c b/builtin/rev-parse.c\nindex 45901df..a4c9fdf 100644\n--- a/builtin/rev-parse.c\n+++ b/builtin/rev-parse.c\n@@ -395,9 +395,10 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)\n \t\tusage[unb++] = strbuf_detach(&sb, NULL);\n \t}\n \n-\t/* parse: (<short>|<short>,<long>|<long>)[=?]? SP+ <help> */\n+\t/* parse: (<short>|<short>,<long>|<long>)[*=?!]*<arghint>? SP+ <help> */\n \twhile (strbuf_getline(&sb, stdin, '\\n') != EOF) {\n \t\tconst char *s;\n+\t\tconst char *end;\n \t\tstruct option *o;\n \n \t\tif (!sb.len)\n@@ -419,6 +420,20 @@ 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+\n+\t\t/* Possible argument name hint */\n+\t\tend = s;\n+\t\twhile (s > sb.buf && strchr(\"*=?!\", s[-1]) == NULL)\n+\t\t\t--s;\n+\t\tif (s != sb.buf && s != end) {\n+\t\t\tchar *a;\n+\t\t\to->argh = a = xmemdupz(s, end - s);\n+\t\t\twhile (a = strchr(a, '_'))\n+\t\t\t\t*a = ' ';\n+\t\t}\n+\t\tif (s == sb.buf)\n+\t\t\ts = end;\n+\n \t\twhile (s > sb.buf && strchr(\"*=?!\", s[-1])) {\n \t\t\tswitch (*--s) {\n \t\t\tcase '=':\ndiff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh\nindex 83b1300..bf0db05 100755\n--- a/t/t1502-rev-parse-parseopt.sh\n+++ b/t/t1502-rev-parse-parseopt.sh\n@@ -18,6 +18,17 @@ An option group Header\n     -C[...]               option C with an optional argument\n     -d, --data[=...]      short and long option with an optional argument\n \n+Argument hints\n+    -b <arg>              short option required argument\n+    --bar2 <arg>          long option required argument\n+    -e, --fuz <with spaces>\n+                          short and long option required argument\n+    -s[<some>]            short option optional argument\n+    --long[=<data>]       long option optional argument\n+    -g, --fluf[=<path>]   short and long option optional argument\n+    --longest <a very long argument hint>\n+                          a very long argument hint\n+\n Extras\n     --extra1              line above used to cause a segfault but no longer does\n \n@@ -39,6 +50,15 @@ b,baz     a short and long option\n C?        option C with an optional argument\n d,data?   short and long option with an optional argument\n \n+ Argument hints\n+b=arg     short option required argument\n+bar2=arg  long option required argument\n+e,fuz=with_spaces  short and long option required argument\n+s?some    short option optional argument\n+long?data long option optional argument\n+g,fluf?path     short and long option optional argument\n+longest=a_very_long_argument_hint  a very long argument hint\n+\n Extras\n extra1    line above used to cause a segfault but no longer does\n EOF\n-- \n1.7.9\n"},{"id":"237192","messageId":"xmqqpplgyaud.fsf@gitster.dls.corp.google.com","threadId":"36035","inReplyTo":"1395305092-1928-1-git-send-email-ilya.bobyr@gmail.com","subject":"Re: [PATCH v3] rev-parse --parseopt: option argument name hints","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-03-20T18:38:17Z","receivedAt":"2014-03-20T18:38:17Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ilya Bobyr <ilya.bobyr@gmail.com> writes:\n\n> Built-in commands can specify names for option arguments when usage text\n> is generated for a command.  sh based commands should be able to do the\n> same.\n>\n> Option argument name hint is any text that comes after [*=?!] after the\n> argument name up to the first whitespace.  Underscores are replaced with\n> whitespace.  It is unlikely that an underscore would be useful in the\n> hint text.\n>\n> Signed-off-by: Ilya Bobyr <ilya.bobyr@gmail.com>\n> ---\n>  Changed according to the last comments.  Added \"Usage text\" paragraph in the\n>  documentation and updated variable names.\n>\n>  Documentation/git-rev-parse.txt |   34 ++++++++++++++++++++++++++++++++--\n>  builtin/rev-parse.c             |   17 ++++++++++++++++-\n>  t/t1502-rev-parse-parseopt.sh   |   20 ++++++++++++++++++++\n>  3 files changed, 68 insertions(+), 3 deletions(-)\n>\n> diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt\n> index 0d2cdcd..b8aabc9 100644\n> --- a/Documentation/git-rev-parse.txt\n> +++ b/Documentation/git-rev-parse.txt\n> @@ -284,13 +284,13 @@ Input Format\n>  \n>  'git rev-parse --parseopt' input format is fully text based. It has two parts,\n>  separated by a line that contains only `--`. The lines before the separator\n> -(should be more than one) are used for the usage.\n> +(should be one or more) are used for the usage.\n>  The lines after the separator describe the options.\n>  \n>  Each line of options has this format:\n>  \n>  ------------\n> -<opt_spec><flags>* SP+ help LF\n> +<opt_spec><flags>*<arg_hint>? SP+ help LF\n>  ------------\n>  \n>  `<opt_spec>`::\n> @@ -313,6 +313,12 @@ Each line of options has this format:\n>  \n>  \t* Use `!` to not make the corresponding negated long option available.\n>  \n> +`<arg_hint>`::\n> +\t`<arg_hing>`, if specified, is used as a name of the argument in the\n> +\thelp output, for options that take arguments. `<arg_hint>` is\n> +\tterminated by the first whitespace. When output the name is shown in\n> +\tangle braces.  Underscore symbols are replaced with spaces.\n\nThe last part is troubling (and sounds not very sane).  Do we do\nsuch a munging anywhere else, or is it just here?  If the latter I'd\nprefer not to see such a hack.\n\n> @@ -333,6 +339,8 @@ h,help    show the help\n>  \n>  foo       some nifty option --foo\n>  bar=      some cool option --bar with an argument\n> +baz=arg   another cool option --baz with a named argument\n> +qux?path  qux may take a path argument but has meaning by itself\n>  \n>    An option group Header\n>  C?        option C with an optional argument\"\n> @@ -340,6 +348,28 @@ C?        option C with an optional argument\"\n>  eval \"$(echo \"$OPTS_SPEC\" | git rev-parse --parseopt -- \"$@\" || echo exit $?)\"\n>  ------------\n>  \n> +\n> +Usage text\n> +~~~~~~~~~~\n> +\n> +When \"$@\" is \"-h\" or \"--help\" the above example would produce the following\n> +usage text:\n\nSounds like a good idea to add this; all the above arguments inside\ndouble quotes should be typeset `as-typed`, though.\n\n> @@ -419,6 +420,20 @@ 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> +\n> +\t\t/* Possible argument name hint */\n> +\t\tend = s;\n> +\t\twhile (s > sb.buf && strchr(\"*=?!\", s[-1]) == NULL)\n> +\t\t\t--s;\n> +\t\tif (s != sb.buf && s != end) {\n> +\t\t\tchar *a;\n> +\t\t\to->argh = a = xmemdupz(s, end - s);\n> +\t\t\twhile (a = strchr(a, '_'))\n> +\t\t\t\t*a = ' ';\n\n... and without the \"underscore\" munging, we do not have to allocate\na new piece of memory, either.\n"},{"id":"237203","messageId":"CAPig+cTGYufCtVJDxG8RUJgyMbb7c3ZdiYMuoAbhQQaitVWRnQ@mail.gmail.com","threadId":"36035","inReplyTo":"1395305092-1928-1-git-send-email-ilya.bobyr@gmail.com","subject":"Re: [PATCH v3] rev-parse --parseopt: option argument name hints","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2014-03-20T20:18:19Z","receivedAt":"2014-03-20T20:18:19Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Thu, Mar 20, 2014 at 4:44 AM, Ilya Bobyr <ilya.bobyr@gmail.com> wrote:\n> Built-in commands can specify names for option arguments when usage text\n> is generated for a command.  sh based commands should be able to do the\n> same.\n>\n> Option argument name hint is any text that comes after [*=?!] after the\n> argument name up to the first whitespace.  Underscores are replaced with\n> whitespace.  It is unlikely that an underscore would be useful in the\n> hint text.\n>\n> Signed-off-by: Ilya Bobyr <ilya.bobyr@gmail.com>\n> ---\n>  Changed according to the last comments.  Added \"Usage text\" paragraph in the\n>  documentation and updated variable names.\n\nAs this is a high-traffic list, it can be difficult for reviewers to\nremember all the comments regarding the previous version. It can help\na lot if you include a reference to the previous attempt, like this\n[1].\n\n[1]: http://thread.gmane.org/gmane.comp.version-control.git/243216/focus=243945\n\nOne more comment below...\n\n> diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt\n> index 0d2cdcd..b8aabc9 100644\n> --- a/Documentation/git-rev-parse.txt\n> +++ b/Documentation/git-rev-parse.txt\n> @@ -313,6 +313,12 @@ Each line of options has this format:\n>\n>         * Use `!` to not make the corresponding negated long option available.\n>\n> +`<arg_hint>`::\n> +       `<arg_hing>`, if specified, is used as a name of the argument in the\n\narg_hing?\n\n> +       help output, for options that take arguments. `<arg_hint>` is\n> +       terminated by the first whitespace. When output the name is shown in\n> +       angle braces.  Underscore symbols are replaced with spaces.\n> +\n>  The remainder of the line, after stripping the spaces, is used\n>  as the help associated to the option.\n"},{"id":"237235","messageId":"532B7774.30308@gmail.com","threadId":"36035","inReplyTo":"xmqqpplgyaud.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH v3] rev-parse --parseopt: option argument name hints","fromName":"Ilya Bobyr","fromEmail":"ilya.bobyr@gmail.com","sentAt":"2014-03-20T23:19:16Z","receivedAt":"2014-03-20T23:19:16Z","isPatch":true,"sender":{"key":"ilya.bobyr@gmail.com","avatar":"https://avatars.githubusercontent.com/u/694419?v=4"},"body":"On 3/20/2014 11:38 AM, Junio C Hamano wrote:\n> Ilya Bobyr <ilya.bobyr@gmail.com> writes:\n>\n>> Built-in commands can specify names for option arguments when usage text\n>> is generated for a command.  sh based commands should be able to do the\n>> same.\n>>\n>> Option argument name hint is any text that comes after [*=?!] after the\n>> argument name up to the first whitespace.  Underscores are replaced with\n>> whitespace.  It is unlikely that an underscore would be useful in the\n>> hint text.\n>>\n>> Signed-off-by: Ilya Bobyr <ilya.bobyr@gmail.com>\n>> ---\n>>   Changed according to the last comments.  Added \"Usage text\" paragraph in the\n>>   documentation and updated variable names.\n>>\n>>   Documentation/git-rev-parse.txt |   34 ++++++++++++++++++++++++++++++++--\n>>   builtin/rev-parse.c             |   17 ++++++++++++++++-\n>>   t/t1502-rev-parse-parseopt.sh   |   20 ++++++++++++++++++++\n>>   3 files changed, 68 insertions(+), 3 deletions(-)\n>>\n>> diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt\n>> index 0d2cdcd..b8aabc9 100644\n>> --- a/Documentation/git-rev-parse.txt\n>> +++ b/Documentation/git-rev-parse.txt\n>> @@ -284,13 +284,13 @@ Input Format\n>>   \n>>   'git rev-parse --parseopt' input format is fully text based. It has two parts,\n>>   separated by a line that contains only `--`. The lines before the separator\n>> -(should be more than one) are used for the usage.\n>> +(should be one or more) are used for the usage.\n>>   The lines after the separator describe the options.\n>>   \n>>   Each line of options has this format:\n>>   \n>>   ------------\n>> -<opt_spec><flags>* SP+ help LF\n>> +<opt_spec><flags>*<arg_hint>? SP+ help LF\n>>   ------------\n>>   \n>>   `<opt_spec>`::\n>> @@ -313,6 +313,12 @@ Each line of options has this format:\n>>   \n>>   \t* Use `!` to not make the corresponding negated long option available.\n>>   \n>> +`<arg_hint>`::\n>> +\t`<arg_hing>`, if specified, is used as a name of the argument in the\n>> +\thelp output, for options that take arguments. `<arg_hint>` is\n>> +\tterminated by the first whitespace. When output the name is shown in\n>> +\tangle braces.  Underscore symbols are replaced with spaces.\n> The last part is troubling (and sounds not very sane).  Do we do\n> such a munging anywhere else, or is it just here?  If the latter I'd\n> prefer not to see such a hack.\n\nThe following commands have spaces in argument names in the \"-h\" output \nfor one or two arguments:\n   * clone\n   * commit\n   * merge\n\nA number of commands use dashes to separate words in arguments names.\n\n\"git notes\" is the only command that uses an underscore in one argument \nname.\n\nAt the moment space is used to separate option specification from the \nhelp line.  As argument name hint is part of the option specification it \nends at the first space.\n\nIt seems a bit unfair if sh based commands would not be able to use \nspaces while the build-in ones can.\nAs underscores are not used in the UI (at least that was my impression \nso far), I thought that to be a good option.\n\nDo you think a different kind of escaping should be used? Backslashes?\nOr no spaces?\n\n>> @@ -333,6 +339,8 @@ h,help    show the help\n>>   \n>>   foo       some nifty option --foo\n>>   bar=      some cool option --bar with an argument\n>> +baz=arg   another cool option --baz with a named argument\n>> +qux?path  qux may take a path argument but has meaning by itself\n>>   \n>>     An option group Header\n>>   C?        option C with an optional argument\"\n>> @@ -340,6 +348,28 @@ C?        option C with an optional argument\"\n>>   eval \"$(echo \"$OPTS_SPEC\" | git rev-parse --parseopt -- \"$@\" || echo exit $?)\"\n>>   ------------\n>>   \n>> +\n>> +Usage text\n>> +~~~~~~~~~~\n>> +\n>> +When \"$@\" is \"-h\" or \"--help\" the above example would produce the following\n>> +usage text:\n> Sounds like a good idea to add this; all the above arguments inside\n> double quotes should be typeset `as-typed`, though.\n\nThanks, I will fix that.\n\n>> @@ -419,6 +420,20 @@ 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>> +\n>> +\t\t/* Possible argument name hint */\n>> +\t\tend = s;\n>> +\t\twhile (s > sb.buf && strchr(\"*=?!\", s[-1]) == NULL)\n>> +\t\t\t--s;\n>> +\t\tif (s != sb.buf && s != end) {\n>> +\t\t\tchar *a;\n>> +\t\t\to->argh = a = xmemdupz(s, end - s);\n>> +\t\t\twhile (a = strchr(a, '_'))\n>> +\t\t\t\t*a = ' ';\n> ... and without the \"underscore\" munging, we do not have to allocate\n> a new piece of memory, either.\n\nWe would have to do it any way to have the string zero terminated.\nThe list of arguments that holds the lines been parsed is \"const char *\".\n\nBut I do not think this is an argument to be considered when designing \nthe user interface :)\n\nNever the less if there is a way not to allocate extra memory that I am \nmissing - let me know, I would remove the allocation.\n"},{"id":"237255","messageId":"532BB42C.5020505@gmail.com","threadId":"36035","inReplyTo":"CAPig+cTGYufCtVJDxG8RUJgyMbb7c3ZdiYMuoAbhQQaitVWRnQ@mail.gmail.com","subject":"Re: [PATCH v3] rev-parse --parseopt: option argument name hints","fromName":"Ilya Bobyr","fromEmail":"ilya.bobyr@gmail.com","sentAt":"2014-03-21T03:38:20Z","receivedAt":"2014-03-21T03:38:20Z","isPatch":true,"sender":{"key":"ilya.bobyr@gmail.com","avatar":"https://avatars.githubusercontent.com/u/694419?v=4"},"body":"On 3/20/2014 1:18 PM, Eric Sunshine wrote:\n> On Thu, Mar 20, 2014 at 4:44 AM, Ilya Bobyr <ilya.bobyr@gmail.com> wrote:\n>> Built-in commands can specify names for option arguments when usage text\n>> is generated for a command.  sh based commands should be able to do the\n>> same.\n>>\n>> Option argument name hint is any text that comes after [*=?!] after the\n>> argument name up to the first whitespace.  Underscores are replaced with\n>> whitespace.  It is unlikely that an underscore would be useful in the\n>> hint text.\n>>\n>> Signed-off-by: Ilya Bobyr <ilya.bobyr@gmail.com>\n>> ---\n>>   Changed according to the last comments.  Added \"Usage text\" paragraph in the\n>>   documentation and updated variable names.\n> As this is a high-traffic list, it can be difficult for reviewers to\n> remember all the comments regarding the previous version. It can help\n> a lot if you include a reference to the previous attempt, like this\n> [1].\n\nGot it, thanks :)\n\n>> [...]\n>>\n>> +`<arg_hint>`::\n>> +       `<arg_hing>`, if specified, is used as a name of the argument in the\n> arg_hing?\n\nWill fix it in the next patch.\n"},{"id":"237299","messageId":"532BF05D.8070104@gmail.com","threadId":"36035","inReplyTo":"532B7774.30308@gmail.com","subject":"Re: [PATCH v3] rev-parse --parseopt: option argument name hints","fromName":"Ilya Bobyr","fromEmail":"ilya.bobyr@gmail.com","sentAt":"2014-03-21T07:55:09Z","receivedAt":"2014-03-21T07:55:09Z","isPatch":true,"sender":{"key":"ilya.bobyr@gmail.com","avatar":"https://avatars.githubusercontent.com/u/694419?v=4"},"body":"On 3/20/2014 4:19 PM, Ilya Bobyr wrote:\n> On 3/20/2014 11:38 AM, Junio C Hamano wrote:\n>> Ilya Bobyr <ilya.bobyr@gmail.com> writes:\n>>\n>>> [...]\n>>>     ------------\n>>> -<opt_spec><flags>* SP+ help LF\n>>> +<opt_spec><flags>*<arg_hint>? SP+ help LF\n>>>   ------------\n>>>     `<opt_spec>`::\n>>> @@ -313,6 +313,12 @@ Each line of options has this format:\n>>>         * Use `!` to not make the corresponding negated long option\n>>> available.\n>>>   +`<arg_hint>`::\n>>> +    `<arg_hing>`, if specified, is used as a name of the argument\n>>> in the\n>>> +    help output, for options that take arguments. `<arg_hint>` is\n>>> +    terminated by the first whitespace. When output the name is\n>>> shown in\n>>> +    angle braces.  Underscore symbols are replaced with spaces.\n>> The last part is troubling (and sounds not very sane).  Do we do\n>> such a munging anywhere else, or is it just here?  If the latter I'd\n>> prefer not to see such a hack.\n>\n> The following commands have spaces in argument names in the \"-h\"\n> output for one or two arguments:\n>   * clone\ns/clone/checkout/\n>   * commit\n>   * merge\n>\n> A number of commands use dashes to separate words in arguments names.\n>\n> \"git notes\" is the only command that uses an underscore in one\n> argument name.\n>\n> At the moment space is used to separate option specification from the\n> help line.  As argument name hint is part of the option specification\n> it ends at the first space.\n>\n> It seems a bit unfair if sh based commands would not be able to use\n> spaces while the build-in ones can.\n> As underscores are not used in the UI (at least that was my impression\n> so far), I thought that to be a good option.\n>\n> Do you think a different kind of escaping should be used? Backslashes?\n> Or no spaces?\n\n\"git merge\" also uses equals sign in one of the argument names.  That\nwould not be possible for sh based commands either.\n\nAs a lot of commands are using dashes instead of spaces, so not\nsupporting spaces is probably fine.\n\nAnother option I can think of is to use (or just allow) angle brackets\naround argument names.  That would look similar to the actual output.\n\"git shortlog\" has some punctuation in an argument name, which braces\nwould make a bit easier to read.\nThis is how an option description would look like then:\n\nOPTION_SPEC=\"\\\n...\nS,gpg-sign?<key id>     GPG sign commit from \"commit\"\nw?<w[,i1[,i2]]>         \"shortlog\" option with a complicated argument name\n...\n\"\n\nIf there is interest in this, I could code it up and post for discussion.\n\n> [...]\n"},{"id":"237325","messageId":"xmqqvbv7v5xh.fsf@gitster.dls.corp.google.com","threadId":"36035","inReplyTo":"532B7774.30308@gmail.com","subject":"Re: [PATCH v3] rev-parse --parseopt: option argument name hints","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-03-21T17:04:58Z","receivedAt":"2014-03-21T17:04:58Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ilya Bobyr <ilya.bobyr@gmail.com> writes:\n\n>>> +\t`<arg_hing>`, if specified, is used as a name of the argument in the\n>>> +\thelp output, for options that take arguments. `<arg_hint>` is\n>>> +\tterminated by the first whitespace. When output the name is shown in\n>>> +\tangle braces.  Underscore symbols are replaced with spaces.\n>> The last part is troubling (and sounds not very sane).  Do we do\n>> such a munging anywhere else, or is it just here?  If the latter I'd\n>> prefer not to see such a hack.\n>\n> The following commands have spaces in argument names in the \"-h\"\n> output for one or two arguments:\n>   * clone\n>   * commit\n>   * merge\n>\n> A number of commands use dashes to separate words in arguments names.\n\nThat was not what I asked.  I was asking if there is a precedent to\nuse \"you cannot have underscores in hint; they will be turned into\nspaces\" quoting convention.  I do not think of any (we either do a\nbackslash-quote, c-quote inside dq-pair, or %20, depending on the\ncontext).\n\nPersonally, because these \"hints\" are not even hints (they are more\nlike placeholders for value that makes it easier to refer to in the\ndescription of an option [*1*]), I wouldn't shed tears if scripted\nPorcelains cannot use a space in the argh.  In fact, it probably\nmakes the result harder to read and format more funnily if you had a\nspace in the argh string, be it in a subcommand implemented in C or\nin a scripted Porcelain.\n\n\"An optional argh is terminated by a whitespace\" is perfectly fine,\nand by doing so we do not have to worry about having to introduce a\nnew quoting convention like you did, which is a big plus.\n\n\n[Footnote]\n\n*1* Perhaps like this:\n\n\t--gpg-sign[=<key-id>]\n        \tSign (with the key specified with <key-id>)\n"},{"id":"237389","messageId":"1395481654-5920-1-git-send-email-ilya.bobyr@gmail.com","threadId":"36035","inReplyTo":"xmqqvbv7v5xh.fsf@gitster.dls.corp.google.com","subject":"[PATCH v4] rev-parse --parseopt: option argument name hints","fromName":"Ilya Bobyr","fromEmail":"ilya.bobyr@gmail.com","sentAt":"2014-03-22T09:47:34Z","receivedAt":"2014-03-22T09:47:34Z","isPatch":true,"sender":{"key":"ilya.bobyr@gmail.com","avatar":"https://avatars.githubusercontent.com/u/694419?v=4"},"body":"Built-in commands can specify names for option arguments when usage text\nis generated for a command.  sh based commands should be able to do the\nsame.\n\nOption argument name hint is any text that comes after [*=?!] after the\nargument name up to the first whitespace.\n\nSigned-off-by: Ilya Bobyr <ilya.bobyr@gmail.com>\n---\n Fixed \"arg_hing\" typo, decoration for `-h` and `--help` and removed\n underscore replacement for the hint text.\n\n Documentation/git-rev-parse.txt |   34 ++++++++++++++++++++++++++++++++--\n builtin/rev-parse.c             |   13 ++++++++++++-\n t/t1502-rev-parse-parseopt.sh   |   20 ++++++++++++++++++++\n 3 files changed, 64 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt\nindex 0d2cdcd..be85023 100644\n--- a/Documentation/git-rev-parse.txt\n+++ b/Documentation/git-rev-parse.txt\n@@ -284,13 +284,13 @@ Input Format\n \n 'git rev-parse --parseopt' input format is fully text based. It has two parts,\n separated by a line that contains only `--`. The lines before the separator\n-(should be more than one) are used for the usage.\n+(should be one or more) are used for the usage.\n The lines after the separator describe the options.\n \n Each line of options has this format:\n \n ------------\n-<opt_spec><flags>* SP+ help LF\n+<opt_spec><flags>*<arg_hint>? SP+ help LF\n ------------\n \n `<opt_spec>`::\n@@ -313,6 +313,12 @@ Each line of options has this format:\n \n \t* Use `!` to not make the corresponding negated long option available.\n \n+`<arg_hint>`::\n+\t`<arg_hint>`, if specified, is used as a name of the argument in the\n+\thelp output, for options that take arguments. `<arg_hint>` is\n+\tterminated by the first whitespace. When you need to use space in the\n+\targument hint use dash instead.\n+\n The remainder of the line, after stripping the spaces, is used\n as the help associated to the option.\n \n@@ -333,6 +339,8 @@ h,help    show the help\n \n foo       some nifty option --foo\n bar=      some cool option --bar with an argument\n+baz=arg   another cool option --baz with a named argument\n+qux?path  qux may take a path argument but has meaning by itself\n \n   An option group Header\n C?        option C with an optional argument\"\n@@ -340,6 +348,28 @@ C?        option C with an optional argument\"\n eval \"$(echo \"$OPTS_SPEC\" | git rev-parse --parseopt -- \"$@\" || echo exit $?)\"\n ------------\n \n+\n+Usage text\n+~~~~~~~~~~\n+\n+When \"$@\" is `-h` or `--help` the above example would produce the following\n+usage text:\n+\n+------------\n+usage: some-command [options] <args>...\n+\n+    some-command does foo and bar!\n+\n+    -h, --help            show the help\n+    --foo                 some nifty option --foo\n+    --bar ...             some cool option --bar with an argument\n+    --bar <arg>           another cool option --baz with a named argument\n+    --qux[=<path>]        qux may take a path argument but has meaning by itself\n+\n+An option group Header\n+    -C[...]               option C with an optional argument\n+------------\n+\n SQ-QUOTE\n --------\n \ndiff --git a/builtin/rev-parse.c b/builtin/rev-parse.c\nindex 45901df..1a6122d 100644\n--- a/builtin/rev-parse.c\n+++ b/builtin/rev-parse.c\n@@ -395,9 +395,10 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)\n \t\tusage[unb++] = strbuf_detach(&sb, NULL);\n \t}\n \n-\t/* parse: (<short>|<short>,<long>|<long>)[=?]? SP+ <help> */\n+\t/* parse: (<short>|<short>,<long>|<long>)[*=?!]*<arghint>? SP+ <help> */\n \twhile (strbuf_getline(&sb, stdin, '\\n') != EOF) {\n \t\tconst char *s;\n+\t\tconst char *end;\n \t\tstruct option *o;\n \n \t\tif (!sb.len)\n@@ -419,6 +420,16 @@ 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+\n+\t\t/* Possible argument name hint */\n+\t\tend = s;\n+\t\twhile (s > sb.buf && strchr(\"*=?!\", s[-1]) == NULL)\n+\t\t\t--s;\n+\t\tif (s != sb.buf && s != end)\n+\t\t\to->argh = xmemdupz(s, end - s);\n+\t\tif (s == sb.buf)\n+\t\t\ts = end;\n+\n \t\twhile (s > sb.buf && strchr(\"*=?!\", s[-1])) {\n \t\t\tswitch (*--s) {\n \t\t\tcase '=':\ndiff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh\nindex 83b1300..e3c6f02 100755\n--- a/t/t1502-rev-parse-parseopt.sh\n+++ b/t/t1502-rev-parse-parseopt.sh\n@@ -18,6 +18,17 @@ An option group Header\n     -C[...]               option C with an optional argument\n     -d, --data[=...]      short and long option with an optional argument\n \n+Argument hints\n+    -b <arg>              short option required argument\n+    --bar2 <arg>          long option required argument\n+    -e, --fuz <with-space>\n+                          short and long option required argument\n+    -s[<some>]            short option optional argument\n+    --long[=<data>]       long option optional argument\n+    -g, --fluf[=<path>]   short and long option optional argument\n+    --longest <very-long-argument-hint>\n+                          a very long argument hint\n+\n Extras\n     --extra1              line above used to cause a segfault but no longer does\n \n@@ -39,6 +50,15 @@ b,baz     a short and long option\n C?        option C with an optional argument\n d,data?   short and long option with an optional argument\n \n+ Argument hints\n+b=arg     short option required argument\n+bar2=arg  long option required argument\n+e,fuz=with-space  short and long option required argument\n+s?some    short option optional argument\n+long?data long option optional argument\n+g,fluf?path     short and long option optional argument\n+longest=very-long-argument-hint  a very long argument hint\n+\n Extras\n extra1    line above used to cause a segfault but no longer does\n EOF\n-- \n1.7.9\n"},{"id":"237450","messageId":"1395683525-2868-1-git-send-email-gitster@pobox.com","threadId":"36035","inReplyTo":"1395481654-5920-1-git-send-email-ilya.bobyr@gmail.com","subject":"[PATCH 0/3] Parse-options: spell multi-word placeholders with dashes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-03-24T17:52:02Z","receivedAt":"2014-03-24T17:52:02Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This is a follow-up to Ilya's 4th round of letting scripted\nporcelains to give argv-help to their users with their command line\noption parser based on \"rev-parse --parseopt\".\n\nWhile reviewing the patch, we found that a few options to the\nbuilt-in commands were described with an argv-help (the placeholder\nfor an option parameter, e.g. \"key-id\" in \"--gpg-sign <key-id>\")\nthat has multiple words to decribe a single entity, spelling these\nmultiple words separated in spaces.  It is more customary to spell a\nmulti-word parameter with dashes, and the first patch in series is\nabout making it so.\n\nDuring the course of the development of the first patch, I needed a\nmechanical way to catch existing offenders; the last patch teaches\nthe parse-options API implementation to find argv-help strings that\ncontain SP or underscore.\n\nThere is one glitch, though.  \"update-index --cacheinfo\" option\ntakes THREE parameters: mode, sha1, and path.  Because a command\nline option that takes multiple options is very unusual, the second\npatch introduces a new syntax to pass these three items as a single\nparameter to \"--cacheinfo\" option, which brings our command line\nargument convention more uniform and consistent.  We however cannot\ndeprecate or remove the traditional syntax, so it is still kept as\nan alternative \"backward compatibility\" syntax.\n\nJunio C Hamano (3):\n  parse-options: multi-word argh should use dash to separate words\n  update-index: teach --cacheinfo a new syntax \"mode,sha1,path\"\n  parse-options: make sure argh string does not have SP or _\n\n Documentation/git-cherry-pick.txt  |  6 +++---\n Documentation/git-commit.txt       |  2 +-\n Documentation/git-merge.txt        |  2 +-\n Documentation/git-notes.txt        |  2 +-\n Documentation/git-rev-parse.txt    | 16 ++++++++--------\n Documentation/git-revert.txt       |  6 +++---\n Documentation/git-update-index.txt |  8 ++++++--\n builtin/checkout.c                 |  2 +-\n builtin/commit.c                   |  2 +-\n builtin/merge.c                    |  2 +-\n builtin/notes.c                    |  2 +-\n builtin/revert.c                   |  2 +-\n builtin/tag.c                      |  2 +-\n builtin/update-index.c             | 34 +++++++++++++++++++++++++++++++---\n parse-options.c                    |  3 +++\n parse-options.h                    |  2 +-\n t/t2107-update-index-basic.sh      | 13 +++++++++++++\n 17 files changed, 77 insertions(+), 29 deletions(-)\n\n-- \n1.9.1-471-gcccbd8b\n"},{"id":"237451","messageId":"1395683525-2868-2-git-send-email-gitster@pobox.com","threadId":"36035","inReplyTo":"1395683525-2868-1-git-send-email-gitster@pobox.com","subject":"[PATCH 1/3] parse-options: multi-word argh should use dash to separate words","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-03-24T17:52:03Z","receivedAt":"2014-03-24T17:52:03Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"When you need to use space, use dash\" is a strange way to say that\nyou must not use a space.  Because it is more common for the command\nline descriptions to use dashed-multi-words, you do not even want to\nuse spaces in these places.  Rephrase the documentation to avoid\nthis strangeness.\n\nFix a few existing multi-word argument help strings, i.e.\n\n - GPG key-ids given to -S/--gpg-sign are \"key-id\";\n - Refs used for storing notes are \"notes-ref\"; and\n - Expiry timestamps given to --expire are \"expiry-date\".\n\nand update the corresponding documentation pages.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n Documentation/git-cherry-pick.txt |  6 +++---\n Documentation/git-commit.txt      |  2 +-\n Documentation/git-merge.txt       |  2 +-\n Documentation/git-notes.txt       |  2 +-\n Documentation/git-rev-parse.txt   | 16 ++++++++--------\n Documentation/git-revert.txt      |  6 +++---\n builtin/checkout.c                |  2 +-\n builtin/commit.c                  |  2 +-\n builtin/merge.c                   |  2 +-\n builtin/notes.c                   |  2 +-\n builtin/revert.c                  |  2 +-\n builtin/tag.c                     |  2 +-\n parse-options.h                   |  2 +-\n 13 files changed, 24 insertions(+), 24 deletions(-)\n\ndiff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt\nindex f1e6b2f..1c03c79 100644\n--- a/Documentation/git-cherry-pick.txt\n+++ b/Documentation/git-cherry-pick.txt\n@@ -9,7 +9,7 @@ SYNOPSIS\n --------\n [verse]\n 'git cherry-pick' [--edit] [-n] [-m parent-number] [-s] [-x] [--ff]\n-\t\t  [-S[<keyid>]] <commit>...\n+\t\t  [-S[<key-id>]] <commit>...\n 'git cherry-pick' --continue\n 'git cherry-pick' --quit\n 'git cherry-pick' --abort\n@@ -101,8 +101,8 @@ effect to your index in a row.\n --signoff::\n \tAdd Signed-off-by line at the end of the commit message.\n \n--S[<keyid>]::\n---gpg-sign[=<keyid>]::\n+-S[<key-id>]::\n+--gpg-sign[=<key-id>]::\n \tGPG-sign commits.\n \n --ff::\ndiff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt\nindex 7c42e9c..d58758f 100644\n--- a/Documentation/git-commit.txt\n+++ b/Documentation/git-commit.txt\n@@ -13,7 +13,7 @@ SYNOPSIS\n \t   [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n \t   [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n \t   [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n-\t   [-i | -o] [-S[<keyid>]] [--] [<file>...]\n+\t   [-i | -o] [-S[<key-id>]] [--] [<file>...]\n \n DESCRIPTION\n -----------\ndiff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt\nindex 4395459..a3c1fa3 100644\n--- a/Documentation/git-merge.txt\n+++ b/Documentation/git-merge.txt\n@@ -10,7 +10,7 @@ SYNOPSIS\n --------\n [verse]\n 'git merge' [-n] [--stat] [--no-commit] [--squash] [--[no-]edit]\n-\t[-s <strategy>] [-X <strategy-option>] [-S[<keyid>]]\n+\t[-s <strategy>] [-X <strategy-option>] [-S[<key-id>]]\n \t[--[no-]rerere-autoupdate] [-m <msg>] [<commit>...]\n 'git merge' <msg> HEAD <commit>...\n 'git merge' --abort\ndiff --git a/Documentation/git-notes.txt b/Documentation/git-notes.txt\nindex 84bb0fe..310f0a5 100644\n--- a/Documentation/git-notes.txt\n+++ b/Documentation/git-notes.txt\n@@ -14,7 +14,7 @@ SYNOPSIS\n 'git notes' append [-F <file> | -m <msg> | (-c | -C) <object>] [<object>]\n 'git notes' edit [<object>]\n 'git notes' show [<object>]\n-'git notes' merge [-v | -q] [-s <strategy> ] <notes_ref>\n+'git notes' merge [-v | -q] [-s <strategy> ] <notes-ref>\n 'git notes' merge --commit [-v | -q]\n 'git notes' merge --abort [-v | -q]\n 'git notes' remove [--ignore-missing] [--stdin] [<object>...]\ndiff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt\nindex e05e6b3..c452f33 100644\n--- a/Documentation/git-rev-parse.txt\n+++ b/Documentation/git-rev-parse.txt\n@@ -290,14 +290,14 @@ The lines after the separator describe the options.\n Each line of options has this format:\n \n ------------\n-<opt_spec><flags>*<arg_hint>? SP+ help LF\n+<opt-spec><flags>*<arg-hint>? SP+ help LF\n ------------\n \n-`<opt_spec>`::\n+`<opt-spec>`::\n \tits format is the short option character, then the long option name\n \tseparated by a comma. Both parts are not required, though at least one\n \tis necessary. `h,help`, `dry-run` and `f` are all three correct\n-\t`<opt_spec>`.\n+\t`<opt-spec>`.\n \n `<flags>`::\n \t`<flags>` are of `*`, `=`, `?` or `!`.\n@@ -313,11 +313,11 @@ Each line of options has this format:\n \n \t* Use `!` to not make the corresponding negated long option available.\n \n-`<arg_hint>`::\n-\t`<arg_hint>`, if specified, is used as a name of the argument in the\n-\thelp output, for options that take arguments. `<arg_hint>` is\n-\tterminated by the first whitespace. When you need to use space in the\n-\targument hint use dash instead.\n+`<arg-hint>`::\n+\t`<arg-hint>`, if specified, is used as a name of the argument in the\n+\thelp output, for options that take arguments. `<arg-hint>` is\n+\tterminated by the first whitespace.  It is customary to use a\n+\tdash to separate words in a multi-word argument hint.\n \n The remainder of the line, after stripping the spaces, is used\n as the help associated to the option.\ndiff --git a/Documentation/git-revert.txt b/Documentation/git-revert.txt\nindex 9eb83f0..cceb5f2 100644\n--- a/Documentation/git-revert.txt\n+++ b/Documentation/git-revert.txt\n@@ -8,7 +8,7 @@ git-revert - Revert some existing commits\n SYNOPSIS\n --------\n [verse]\n-'git revert' [--[no-]edit] [-n] [-m parent-number] [-s] [-S[<keyid>]] <commit>...\n+'git revert' [--[no-]edit] [-n] [-m parent-number] [-s] [-S[<key-id>]] <commit>...\n 'git revert' --continue\n 'git revert' --quit\n 'git revert' --abort\n@@ -80,8 +80,8 @@ more details.\n This is useful when reverting more than one commits'\n effect to your index in a row.\n \n--S[<keyid>]::\n---gpg-sign[=<keyid>]::\n+-S[<key-id>]::\n+--gpg-sign[=<key-id>]::\n \tGPG-sign commits.\n \n -s::\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex ada51fa..a0e72d2 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -1095,7 +1095,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"detach\", &opts.force_detach, N_(\"detach the HEAD at named commit\")),\n \t\tOPT_SET_INT('t', \"track\",  &opts.track, N_(\"set upstream info for new branch\"),\n \t\t\tBRANCH_TRACK_EXPLICIT),\n-\t\tOPT_STRING(0, \"orphan\", &opts.new_orphan_branch, N_(\"new branch\"), N_(\"new unparented branch\")),\n+\t\tOPT_STRING(0, \"orphan\", &opts.new_orphan_branch, N_(\"new-branch\"), N_(\"new unparented branch\")),\n \t\tOPT_SET_INT('2', \"ours\", &opts.writeout_stage, N_(\"checkout our version for unmerged files\"),\n \t\t\t    2),\n \t\tOPT_SET_INT('3', \"theirs\", &opts.writeout_stage, N_(\"checkout their version for unmerged files\"),\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex 3783bca..96bf762 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -1472,7 +1472,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL('e', \"edit\", &edit_flag, N_(\"force edit of commit\")),\n \t\tOPT_STRING(0, \"cleanup\", &cleanup_arg, N_(\"default\"), N_(\"how to strip spaces and #comments from message\")),\n \t\tOPT_BOOL(0, \"status\", &include_status, N_(\"include status in commit message template\")),\n-\t\t{ OPTION_STRING, 'S', \"gpg-sign\", &sign_commit, N_(\"key id\"),\n+\t\t{ OPTION_STRING, 'S', \"gpg-sign\", &sign_commit, N_(\"key-id\"),\n \t\t  N_(\"GPG sign commit\"), PARSE_OPT_OPTARG, NULL, (intptr_t) \"\" },\n \t\t/* end commit message options */\n \ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex f0cf120..2a144e1 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -220,7 +220,7 @@ static struct option builtin_merge_options[] = {\n \tOPT_BOOL(0, \"abort\", &abort_current_merge,\n \t\tN_(\"abort the current in-progress merge\")),\n \tOPT_SET_INT(0, \"progress\", &show_progress, N_(\"force progress reporting\"), 1),\n-\t{ OPTION_STRING, 'S', \"gpg-sign\", &sign_commit, N_(\"key id\"),\n+\t{ OPTION_STRING, 'S', \"gpg-sign\", &sign_commit, N_(\"key-id\"),\n \t  N_(\"GPG sign commit\"), PARSE_OPT_OPTARG, NULL, (intptr_t) \"\" },\n \tOPT_BOOL(0, \"overwrite-ignore\", &overwrite_ignore, N_(\"update ignored files (default)\")),\n \tOPT_END()\ndiff --git a/builtin/notes.c b/builtin/notes.c\nindex bb89930..39c8573 100644\n--- a/builtin/notes.c\n+++ b/builtin/notes.c\n@@ -939,7 +939,7 @@ int cmd_notes(int argc, const char **argv, const char *prefix)\n \tint result;\n \tconst char *override_notes_ref = NULL;\n \tstruct option options[] = {\n-\t\tOPT_STRING(0, \"ref\", &override_notes_ref, N_(\"notes_ref\"),\n+\t\tOPT_STRING(0, \"ref\", &override_notes_ref, N_(\"notes-ref\"),\n \t\t\t   N_(\"use notes from <notes_ref>\")),\n \t\tOPT_END()\n \t};\ndiff --git a/builtin/revert.c b/builtin/revert.c\nindex 065d88d..f9ed5bd 100644\n--- a/builtin/revert.c\n+++ b/builtin/revert.c\n@@ -89,7 +89,7 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)\n \t\tOPT_STRING(0, \"strategy\", &opts->strategy, N_(\"strategy\"), N_(\"merge strategy\")),\n \t\tOPT_CALLBACK('X', \"strategy-option\", &opts, N_(\"option\"),\n \t\t\tN_(\"option for merge strategy\"), option_parse_x),\n-\t\t{ OPTION_STRING, 'S', \"gpg-sign\", &opts->gpg_sign, N_(\"key id\"),\n+\t\t{ OPTION_STRING, 'S', \"gpg-sign\", &opts->gpg_sign, N_(\"key-id\"),\n \t\t  N_(\"GPG sign commit\"), PARSE_OPT_OPTARG, NULL, (intptr_t) \"\" },\n \t\tOPT_END(),\n \t\tOPT_END(),\ndiff --git a/builtin/tag.c b/builtin/tag.c\nindex 40356e3..6c7c6bd 100644\n--- a/builtin/tag.c\n+++ b/builtin/tag.c\n@@ -513,7 +513,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL('s', \"sign\", &opt.sign, N_(\"annotated and GPG-signed tag\")),\n \t\tOPT_STRING(0, \"cleanup\", &cleanup_arg, N_(\"mode\"),\n \t\t\tN_(\"how to strip spaces and #comments from message\")),\n-\t\tOPT_STRING('u', \"local-user\", &keyid, N_(\"key id\"),\n+\t\tOPT_STRING('u', \"local-user\", &keyid, N_(\"key-id\"),\n \t\t\t\t\tN_(\"use another key to sign the tag\")),\n \t\tOPT__FORCE(&force, N_(\"replace the tag if exists\")),\n \t\tOPT_COLUMN(0, \"column\", &colopts, N_(\"show tag list in columns\")),\ndiff --git a/parse-options.h b/parse-options.h\nindex d670cb9..8fa02dc 100644\n--- a/parse-options.h\n+++ b/parse-options.h\n@@ -143,7 +143,7 @@ struct option {\n \t{ OPTION_CALLBACK, (s), (l), (v), N_(\"time\"),(h), 0,\t\\\n \t  parse_opt_approxidate_cb }\n #define OPT_EXPIRY_DATE(s, l, v, h) \\\n-\t{ OPTION_CALLBACK, (s), (l), (v), N_(\"expiry date\"),(h), 0,\t\\\n+\t{ OPTION_CALLBACK, (s), (l), (v), N_(\"expiry-date\"),(h), 0,\t\\\n \t  parse_opt_expiry_date_cb }\n #define OPT_CALLBACK(s, l, v, a, h, f) \\\n \t{ OPTION_CALLBACK, (s), (l), (v), (a), (h), 0, (f) }\n-- \n1.9.1-471-gcccbd8b\n"},{"id":"237449","messageId":"1395683525-2868-3-git-send-email-gitster@pobox.com","threadId":"36035","inReplyTo":"1395683525-2868-1-git-send-email-gitster@pobox.com","subject":"[PATCH 2/3] update-index: teach --cacheinfo a new syntax \"mode,sha1,path\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-03-24T17:52:04Z","receivedAt":"2014-03-24T17:52:04Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"The \"--cacheinfo\" option is unusual in that it takes three option\nparameters.  An option with an optional parameter is bad enough.  An\noption with multiple parameters is simply insane.\n\nIntroduce a new syntax that takes these three things concatenated\ntogether with a comma, which makes the command line syntax more\nuniform across subcommands, while retaining the traditional syntax\nfor backward compatiblity.\n\nIf we were designing the \"update-index\" subcommand from scratch\ntoday, it may probably have made sense to make this option (and\npossibly others) a command mode option that does not take any option\nparameter (hence no need for arg-help).  But we do not live in such\nan ideal world, and as far as I can tell, the command still supports\n(and must support) mixed command modes in a single invocation, e.g.\n\n    $ git update-index path1 --add path2 \\\n        --cacheinfo 100644 $(git hash-object --stdin -w <path3) path3 \\\n\tpath4\n\nmust make sure path1 is already in the index and update all of these\nfour paths.  So this is probably as far as we can go to fix this issue\nwithout risking to break people's existing scripts.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n Documentation/git-update-index.txt |  8 ++++++--\n builtin/update-index.c             | 34 +++++++++++++++++++++++++++++++---\n t/t2107-update-index-basic.sh      | 13 +++++++++++++\n 3 files changed, 50 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt\nindex e0a8702..d6de4a0 100644\n--- a/Documentation/git-update-index.txt\n+++ b/Documentation/git-update-index.txt\n@@ -12,7 +12,7 @@ SYNOPSIS\n 'git update-index'\n \t     [--add] [--remove | --force-remove] [--replace]\n \t     [--refresh] [-q] [--unmerged] [--ignore-missing]\n-\t     [(--cacheinfo <mode> <object> <file>)...]\n+\t     [(--cacheinfo <mode>,<object>,<file>)...]\n \t     [--chmod=(+|-)x]\n \t     [--[no-]assume-unchanged]\n \t     [--[no-]skip-worktree]\n@@ -68,8 +68,12 @@ OPTIONS\n --ignore-missing::\n \tIgnores missing files during a --refresh\n \n+--cacheinfo <mode>,<object>,<path>::\n --cacheinfo <mode> <object> <path>::\n-\tDirectly insert the specified info into the index.\n+\tDirectly insert the specified info into the index.  For\n+\tbackward compatibility, you can also give these three\n+\targuments as three separate parameters, but new users are\n+\tencouraged to use a single-parameter form.\n \n --index-info::\n         Read index information from stdin.\ndiff --git a/builtin/update-index.c b/builtin/update-index.c\nindex d12ad95..ba54e19 100644\n--- a/builtin/update-index.c\n+++ b/builtin/update-index.c\n@@ -629,14 +629,42 @@ static int resolve_undo_clear_callback(const struct option *opt,\n \treturn 0;\n }\n \n+static int parse_new_style_cacheinfo(const char *arg,\n+\t\t\t\t     unsigned int *mode,\n+\t\t\t\t     unsigned char sha1[],\n+\t\t\t\t     const char **path)\n+{\n+\tunsigned long ul;\n+\tchar *endp;\n+\n+\terrno = 0;\n+\tul = strtoul(arg, &endp, 8);\n+\tif (errno || endp == arg || *endp != ',' || (unsigned int) ul != ul)\n+\t\treturn -1; /* not a new-style cacheinfo */\n+\t*mode = ul;\n+\tendp++;\n+\tif (get_sha1_hex(endp, sha1) || endp[40] != ',')\n+\t\treturn -1;\n+\t*path = endp + 41;\n+\treturn 0;\n+}\n+\n static int cacheinfo_callback(struct parse_opt_ctx_t *ctx,\n \t\t\t\tconst struct option *opt, int unset)\n {\n \tunsigned char sha1[20];\n \tunsigned int mode;\n+\tconst char *path;\n \n+\tif (!parse_new_style_cacheinfo(ctx->argv[1], &mode, sha1, &path)) {\n+\t\tif (add_cacheinfo(mode, sha1, path, 0))\n+\t\t\tdie(\"git update-index: --cacheinfo cannot add %s\", path);\n+\t\tctx->argv++;\n+\t\tctx->argc--;\n+\t\treturn 0;\n+\t}\n \tif (ctx->argc <= 3)\n-\t\treturn error(\"option 'cacheinfo' expects three arguments\");\n+\t\treturn error(\"option 'cacheinfo' expects <mode>,<sha1>,<path>\");\n \tif (strtoul_ui(*++ctx->argv, 8, &mode) ||\n \t    get_sha1_hex(*++ctx->argv, sha1) ||\n \t    add_cacheinfo(mode, sha1, *++ctx->argv, 0))\n@@ -740,9 +768,9 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)\n \t\t\tPARSE_OPT_NOARG | PARSE_OPT_NONEG,\n \t\t\treally_refresh_callback},\n \t\t{OPTION_LOWLEVEL_CALLBACK, 0, \"cacheinfo\", NULL,\n-\t\t\tN_(\"<mode> <object> <path>\"),\n+\t\t\tN_(\"<mode>,<object>,<path>\"),\n \t\t\tN_(\"add the specified entry to the index\"),\n-\t\t\tPARSE_OPT_NOARG |\t/* disallow --cacheinfo=<mode> form */\n+\t\t\tPARSE_OPT_NOARG | /* disallow --cacheinfo=<mode> form */\n \t\t\tPARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,\n \t\t\t(parse_opt_cb *) cacheinfo_callback},\n \t\t{OPTION_CALLBACK, 0, \"chmod\", &set_executable_bit, N_(\"(+/-)x\"),\ndiff --git a/t/t2107-update-index-basic.sh b/t/t2107-update-index-basic.sh\nindex a6405d3..fe2fb17 100755\n--- a/t/t2107-update-index-basic.sh\n+++ b/t/t2107-update-index-basic.sh\n@@ -48,4 +48,17 @@ test_expect_success '--cacheinfo does not accept gitlink null sha1' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success '--cacheinfo mode,sha1,path (new syntax)' '\n+\techo content >file &&\n+\tgit hash-object -w --stdin <file >expect &&\n+\n+\tgit update-index --add --cacheinfo 100644 \"$(cat expect)\" file &&\n+\tgit rev-parse :file >actual &&\n+\ttest_cmp expect actual &&\n+\n+\tgit update-index --add --cacheinfo \"100644,$(cat expect),elif\" &&\n+\tgit rev-parse :elif >actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\n-- \n1.9.1-471-gcccbd8b\n"},{"id":"237448","messageId":"1395683525-2868-4-git-send-email-gitster@pobox.com","threadId":"36035","inReplyTo":"1395683525-2868-1-git-send-email-gitster@pobox.com","subject":"[PATCH 3/3] parse-options: make sure argh string does not have SP or _","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-03-24T17:52:05Z","receivedAt":"2014-03-24T17:52:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"We encourage to spell an argument hint that consists of multiple\nwords as a single-token separated with dashes.  In order to help\ncatching violations added by new callers of parse-options, make sure\nargh does not contain SP or _ when the code validates the option\ndefinitions.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n parse-options.c | 3 +++\n 1 file changed, 3 insertions(+)\n\ndiff --git a/parse-options.c b/parse-options.c\nindex a5fa0b8..c81d3a0 100644\n--- a/parse-options.c\n+++ b/parse-options.c\n@@ -375,6 +375,9 @@ static void parse_options_check(const struct option *opts)\n \t\tdefault:\n \t\t\t; /* ok. (usually accepts an argument) */\n \t\t}\n+\t\tif (opts->argh &&\n+\t\t    strcspn(opts->argh, \" _\") != strlen(opts->argh))\n+\t\t\terr |= optbug(opts, \"multi-word argh should use dash to separate words\");\n \t}\n \tif (err)\n \t\texit(128);\n-- \n1.9.1-471-gcccbd8b\n"}]}