{"thread":{"id":"20995","subject":"[PATCH] git-log --format: Add %B tag with %B(x) option","startedAt":"2009-09-17T22:47:51Z","lastAt":"2009-10-10T00:57:20Z","messageCount":18,"participants":["Johannes Gilger","Junio C Hamano","Johannes Schindelin","Linus Torvalds"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"123471","messageId":"1253227671-20493-1-git-send-email-heipei@hackvalue.de","threadId":"20995","inReplyTo":null,"subject":"[PATCH] git-log --format: Add %B tag with %B(x) option","fromName":"Johannes Gilger","fromEmail":"heipei@hackvalue.de","sentAt":"2009-09-17T22:47:51Z","receivedAt":"2009-09-17T22:47:51Z","isPatch":true,"sender":{"key":"heipei@hackvalue.de","avatar":"https://avatars.githubusercontent.com/u/6072?v=4"},"body":"Since one can simply use spaces to indent any other --pretty field we\nshould have an option to do that with the body too.\n\nAlso the %B flag strips the trailing newlines, to enable more compact\ndisplay.\n\nSigned-off-by: Johannes Gilger <heipei@hackvalue.de>\n---\nHey list,\n\nin my never-ending quest to beautify my personal log output I just whipped this \nup. Maybe you like it too or at least can tell me what's wrong with it ;)\n\nPlease CC me as I'm not on the list anymore (but keep up through Gmane though).\n\n Documentation/pretty-formats.txt |    2 ++\n pretty.c                         |   13 +++++++++++++\n 2 files changed, 15 insertions(+), 0 deletions(-)\n\ndiff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt\nindex 2a845b1..c04f118 100644\n--- a/Documentation/pretty-formats.txt\n+++ b/Documentation/pretty-formats.txt\n@@ -123,6 +123,8 @@ The placeholders are:\n - '%s': subject\n - '%f': sanitized subject line, suitable for a filename\n - '%b': body\n+- '%B': body without trailing newline\n+- '%B(x)': body indented with x spaces\n - '%Cred': switch color to red\n - '%Cgreen': switch color to green\n - '%Cblue': switch color to blue\ndiff --git a/pretty.c b/pretty.c\nindex f5983f8..6d530e1 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -735,6 +735,19 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,\n \tcase 'b':\t/* body */\n \t\tstrbuf_addstr(sb, msg + c->body_off);\n \t\treturn 1;\n+\tcase 'B':\n+\t\tif (placeholder[1] == '(') {\n+\t\t\tconst char *body = msg + c->body_off;\n+\t\t\tconst char *end = strchr(placeholder + 2, ')');\n+\t\t\tif(!end)\n+\t\t\t\treturn 0;\n+\t\t\tpp_remainder(CMIT_FMT_MEDIUM, &body, sb, atoi(placeholder + 2));\n+\t\t\tstrbuf_rtrim(sb);\n+\t\t\treturn end - placeholder + 1;\n+\t\t}\n+\t\tstrbuf_addstr(sb, msg + c->body_off);\n+\t\tstrbuf_rtrim(sb);\n+\t\treturn 1;\n \t}\n \treturn 0;\t/* unknown placeholder */\n }\n-- \n1.6.5.rc1.20.geb7d9\n"},{"id":"123473","messageId":"7vk4zxgnim.fsf@alter.siamese.dyndns.org","threadId":"20995","inReplyTo":"1253227671-20493-1-git-send-email-heipei@hackvalue.de","subject":"Re: [PATCH] git-log --format: Add %B tag with %B(x) option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-17T23:27:45Z","receivedAt":"2009-09-17T23:27:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Gilger <heipei@hackvalue.de> writes:\n\n> diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt\n> index 2a845b1..c04f118 100644\n> --- a/Documentation/pretty-formats.txt\n> +++ b/Documentation/pretty-formats.txt\n> @@ -123,6 +123,8 @@ The placeholders are:\n>  - '%s': subject\n>  - '%f': sanitized subject line, suitable for a filename\n>  - '%b': body\n> +- '%B': body without trailing newline\n> +- '%B(x)': body indented with x spaces\n\nFirst the design issues.\n\nBecause this will set a precedent for possible future formatting features\nthat take optional parameters, we need to pick the syntax carefully not\nonly for this feature but for the later ones that we haven't invented yet.\n\nLet's say that pair of parentheses is a good choice and if later features\nwant to take more than one, it would be reasonable for them to use a\ncomma-separated list, e.g. %Q(1,2,3).\n\nI wonder if it is reasonable to invoke print_wrapped_text(), not just\nlimit this feature to indenting.\n\nNow, let's look at the implementation.\n\n> diff --git a/pretty.c b/pretty.c\n> index f5983f8..6d530e1 100644\n> --- a/pretty.c\n> +++ b/pretty.c\n> @@ -735,6 +735,19 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,\n>  \tcase 'b':\t/* body */\n>  \t\tstrbuf_addstr(sb, msg + c->body_off);\n>  \t\treturn 1;\n> +\tcase 'B':\n> +\t\tif (placeholder[1] == '(') {\n> +\t\t\tconst char *body = msg + c->body_off;\n> +\t\t\tconst char *end = strchr(placeholder + 2, ')');\n> +\t\t\tif(!end)\n> +\t\t\t\treturn 0;\n\nStyle: \"if (!end)\"\n\nI'd sleep better if the syntax checking is done as a separate phase way\nbefore this in the codepath.\n\n> +\t\t\tpp_remainder(CMIT_FMT_MEDIUM, &body, sb, atoi(placeholder + 2));\n\nWhat happens when atoi() fails, or %B(12Q) was given?\n\nWe tend to use strto[u]l when parsing integers and check for errors.\n"},{"id":"123496","messageId":"1253296845-17219-1-git-send-email-heipei@hackvalue.de","threadId":"20995","inReplyTo":"7vk4zxgnim.fsf@alter.siamese.dyndns.org","subject":"[PATCHv2] git-log --format: Add %B tag with %B(x) option","fromName":"Johannes Gilger","fromEmail":"heipei@hackvalue.de","sentAt":"2009-09-18T18:00:45Z","receivedAt":"2009-09-18T18:00:45Z","isPatch":false,"sender":{"key":"heipei@hackvalue.de","avatar":"https://avatars.githubusercontent.com/u/6072?v=4"},"body":"Since one can simply use spaces to indent any other --pretty field we\nshould have an option to do that with the body too.\n\nAlso the %B flag strips the trailing newlines, to enable more compact\ndisplay.\n\nSigned-off-by: Johannes Gilger <heipei@hackvalue.de>\n---\nHi again,\n\nI followed Junio's implementation-advice. Since we have two placeholders which \ntake () arguments I put the scanning for those at the top, to avoid repetition. \nI used strtol in place of atoi and I also had to to add a check for ident > 0 \nsince the indent determines the growth-size of the buffer, and negative values \nproduced nasty stuff (obviously).\n\nAs for general extendability: The current code deals with %B(42) as well as \n%B(42,23[,...]), so even old versions could be used with \"new\" pretty-formats.  \n%B(c5) is simply no ident, while %B(5c) is 5 spaces indent. Don't know if this \nis unwanted behaviour, but that's what strtol gives us.\n\nDscho sent me a pointer to a patch [1], which not only adds indent but also \nrewrapping. But since this is my second patch and Dscho's patch depended on two \nother patches I didn't want to get in over my head by making his patches a \nprerequisite.\n\nA last word on future formats: We can use (x,y,z) easily, another thing one \nmight think of (or at least I do) is using an %an[20] syntax, returning only \nthe first 20 chars of %an, so one can make onelined outputs nicely \ncolumn-aligned for fields like the author.\n\nGreetings,\nJojo\n\n[1] - http://repo.or.cz/w/git/dscho.git?a=commit;h=ad48dfca58169c35e227e135638b4970fe4dc9a5\n\n Documentation/pretty-formats.txt |    2 ++\n pretty.c                         |   25 ++++++++++++++++++++-----\n 2 files changed, 22 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt\nindex 2a845b1..533bc5e 100644\n--- a/Documentation/pretty-formats.txt\n+++ b/Documentation/pretty-formats.txt\n@@ -123,6 +123,8 @@ The placeholders are:\n - '%s': subject\n - '%f': sanitized subject line, suitable for a filename\n - '%b': body\n+- '%B': body without trailing newline\n+- '%B(x)': body indented by x spaces\n - '%Cred': switch color to red\n - '%Cgreen': switch color to green\n - '%Cblue': switch color to blue\ndiff --git a/pretty.c b/pretty.c\nindex f5983f8..7b88827 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -605,13 +605,17 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,\n \tint h1, h2;\n \n \t/* these are independent of the commit */\n+\n+\tconst char *body = msg + c->body_off;\n+\tconst char *end = NULL;\n+\t/* check if we have arguments to the placeholder */\n+\tif (placeholder[1] == '(')\n+\t\tend = strchr(placeholder + 2, ')');\n+\n \tswitch (placeholder[0]) {\n \tcase 'C':\n-\t\tif (placeholder[1] == '(') {\n-\t\t\tconst char *end = strchr(placeholder + 2, ')');\n+\t\tif (end) {\n \t\t\tchar color[COLOR_MAXLEN];\n-\t\t\tif (!end)\n-\t\t\t\treturn 0;\n \t\t\tcolor_parse_mem(placeholder + 2,\n \t\t\t\t\tend - (placeholder + 2),\n \t\t\t\t\t\"--pretty format\", color);\n@@ -733,7 +737,16 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,\n \t\tformat_sanitized_subject(sb, msg + c->subject_off);\n \t\treturn 1;\n \tcase 'b':\t/* body */\n-\t\tstrbuf_addstr(sb, msg + c->body_off);\n+\t\tstrbuf_addstr(sb, body);\n+\t\treturn 1;\n+\tcase 'B':\t/* body without trailing newline */\n+\t\tif (end) {\n+\t\t\tpp_remainder(CMIT_FMT_MEDIUM, &body, sb, strtol(placeholder + 2, NULL, 10));\n+\t\t\tstrbuf_rtrim(sb);\n+\t\t\treturn end - placeholder + 1;\n+\t\t}\n+\t\tstrbuf_addstr(sb, body);\n+\t\tstrbuf_rtrim(sb);\n \t\treturn 1;\n \t}\n \treturn 0;\t/* unknown placeholder */\n@@ -875,6 +888,8 @@ void pp_remainder(enum cmit_fmt fmt,\n \t\t}\n \t\tfirst = 0;\n \n+\t\tif (indent < 0)\n+\t\t\tindent = 0;\n \t\tstrbuf_grow(sb, linelen + indent + 20);\n \t\tif (indent) {\n \t\t\tmemset(sb->buf + sb->len, ' ', indent);\n-- \n1.6.5.rc1.20.geb7d9\n"},{"id":"123501","messageId":"7vtyz083tk.fsf@alter.siamese.dyndns.org","threadId":"20995","inReplyTo":"1253296845-17219-1-git-send-email-heipei@hackvalue.de","subject":"Re: [PATCHv2] git-log --format: Add %B tag with %B(x) option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-18T19:12:39Z","receivedAt":"2009-09-18T19:12:39Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Gilger <heipei@hackvalue.de> writes:\n\n> %B(c5) is simply no ident, while %B(5c) is 5 spaces indent. Don't know if this \n> is unwanted behaviour, but that's what strtol gives us.\n\nNot really.\n\n\"strto[u]l(arg, &endp, 10)\" parses arg as a decimal and moves \"char *endp\"\nto point at where the number ended, so you can tell things like:\n\n - return value of 0 with (arg == endp) being \"an empty input, the user\n   did not necessarily meant zero\"; or\n\n - (*endp != '\\0') being \"some garbage after the number\".\n"},{"id":"123518","messageId":"1253354304-13117-1-git-send-email-heipei@hackvalue.de","threadId":"20995","inReplyTo":"7vtyz083tk.fsf@alter.siamese.dyndns.org","subject":"[PATCHv3] git-log --format: Add %B tag with %B(x) option","fromName":"Johannes Gilger","fromEmail":"heipei@hackvalue.de","sentAt":"2009-09-19T09:58:24Z","receivedAt":"2009-09-19T09:58:24Z","isPatch":false,"sender":{"key":"heipei@hackvalue.de","avatar":"https://avatars.githubusercontent.com/u/6072?v=4"},"body":"Since one can simply use spaces to indent any other --pretty field we\nshould have an option to do that with the body too.\n\nAlso the %B flag strips the trailing newlines, to enable more compact\ndisplay.\n\nSigned-off-by: Johannes Gilger <heipei@hackvalue.de>\n---\nChanges to PATCHv2:\n- Make %B() strict: Only nonnegative integers are allowed between the brackets, \n  everything else yields the placemark itself as output to indicate a wrong \n  argument. This also goes for an empty argument.\n\n Documentation/pretty-formats.txt |    2 ++\n pretty.c                         |   29 ++++++++++++++++++++++++-----\n 2 files changed, 26 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt\nindex 2a845b1..533bc5e 100644\n--- a/Documentation/pretty-formats.txt\n+++ b/Documentation/pretty-formats.txt\n@@ -123,6 +123,8 @@ The placeholders are:\n - '%s': subject\n - '%f': sanitized subject line, suitable for a filename\n - '%b': body\n+- '%B': body without trailing newline\n+- '%B(x)': body indented by x spaces\n - '%Cred': switch color to red\n - '%Cgreen': switch color to green\n - '%Cblue': switch color to blue\ndiff --git a/pretty.c b/pretty.c\nindex f5983f8..8970378 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -605,13 +605,17 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,\n \tint h1, h2;\n \n \t/* these are independent of the commit */\n+\n+\tconst char *body = msg + c->body_off;\n+\tconst char *end = NULL;\n+\t/* check if we have arguments to the placeholder */\n+\tif (placeholder[1] == '(')\n+\t\tend = strchr(placeholder + 2, ')');\n+\n \tswitch (placeholder[0]) {\n \tcase 'C':\n-\t\tif (placeholder[1] == '(') {\n-\t\t\tconst char *end = strchr(placeholder + 2, ')');\n+\t\tif (end) {\n \t\t\tchar color[COLOR_MAXLEN];\n-\t\t\tif (!end)\n-\t\t\t\treturn 0;\n \t\t\tcolor_parse_mem(placeholder + 2,\n \t\t\t\t\tend - (placeholder + 2),\n \t\t\t\t\t\"--pretty format\", color);\n@@ -733,7 +737,20 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,\n \t\tformat_sanitized_subject(sb, msg + c->subject_off);\n \t\treturn 1;\n \tcase 'b':\t/* body */\n-\t\tstrbuf_addstr(sb, msg + c->body_off);\n+\t\tstrbuf_addstr(sb, body);\n+\t\treturn 1;\n+\tcase 'B':\t/* body without trailing newline */\n+\t\tif (end) {\n+\t\t\tchar *endp = NULL;\n+\t\t\tint indent = strtol(placeholder + 2, &endp, 10);\n+\t\t\tif (placeholder + 2 == endp || *endp != ')' || indent < 0)\n+\t\t\t\treturn 0;\n+\t\t\tpp_remainder(CMIT_FMT_MEDIUM, &body, sb, indent);\n+\t\t\tstrbuf_rtrim(sb);\n+\t\t\treturn end - placeholder + 1;\n+\t\t}\n+\t\tstrbuf_addstr(sb, body);\n+\t\tstrbuf_rtrim(sb);\n \t\treturn 1;\n \t}\n \treturn 0;\t/* unknown placeholder */\n@@ -875,6 +892,8 @@ void pp_remainder(enum cmit_fmt fmt,\n \t\t}\n \t\tfirst = 0;\n \n+\t\tif (indent < 0)\n+\t\t\tindent = 0;\n \t\tstrbuf_grow(sb, linelen + indent + 20);\n \t\tif (indent) {\n \t\t\tmemset(sb->buf + sb->len, ' ', indent);\n-- \n1.6.5.rc1.20.geb7d9\n"},{"id":"123646","messageId":"7vfxaercma.fsf@alter.siamese.dyndns.org","threadId":"20995","inReplyTo":"1253354304-13117-1-git-send-email-heipei@hackvalue.de","subject":"Re: [PATCHv3] git-log --format: Add %B tag with %B(x) option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-22T19:41:17Z","receivedAt":"2009-09-22T19:41:17Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Gilger <heipei@hackvalue.de> writes:\n\n> Since one can simply use spaces to indent any other --pretty field we\n> should have an option to do that with the body too.\n>\n> Also the %B flag strips the trailing newlines, to enable more compact\n> display.\n>\n> Signed-off-by: Johannes Gilger <heipei@hackvalue.de>\n> ---\n> Changes to PATCHv2:\n> - Make %B() strict: Only nonnegative integers are allowed between the brackets, \n>   everything else yields the placemark itself as output to indicate a wrong \n>   argument. This also goes for an empty argument.\n>\n>  Documentation/pretty-formats.txt |    2 ++\n>  pretty.c                         |   29 ++++++++++++++++++++++++-----\n>  2 files changed, 26 insertions(+), 5 deletions(-)\n>\n> diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt\n> index 2a845b1..533bc5e 100644\n> --- a/Documentation/pretty-formats.txt\n> +++ b/Documentation/pretty-formats.txt\n> @@ -733,7 +737,20 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,\n>  \t\tformat_sanitized_subject(sb, msg + c->subject_off);\n>  \t\treturn 1;\n>  \tcase 'b':\t/* body */\n> -\t\tstrbuf_addstr(sb, msg + c->body_off);\n> +\t\tstrbuf_addstr(sb, body);\n> +\t\treturn 1;\n> +\tcase 'B':\t/* body without trailing newline */\n> +\t\tif (end) {\n> +\t\t\tchar *endp = NULL;\n> +\t\t\tint indent = strtol(placeholder + 2, &endp, 10);\n> +\t\t\tif (placeholder + 2 == endp || *endp != ')' || indent < 0)\n> +\t\t\t\treturn 0;\n> +\t\t\tpp_remainder(CMIT_FMT_MEDIUM, &body, sb, indent);\n> +\t\t\tstrbuf_rtrim(sb);\n> +\t\t\treturn end - placeholder + 1;\n> +\t\t}\n> +\t\tstrbuf_addstr(sb, body);\n> +\t\tstrbuf_rtrim(sb);\n>  \t\treturn 1;\n>  \t}\n>  \treturn 0;\t/* unknown placeholder */\n> @@ -875,6 +892,8 @@ void pp_remainder(enum cmit_fmt fmt,\n>  \t\t}\n>  \t\tfirst = 0;\n>  \n> +\t\tif (indent < 0)\n> +\t\t\tindent = 0;\n\nI'd move this check to the caller; other than that and some other small\nstyle issues I think this round is Ok.\n\n>  \t\tstrbuf_grow(sb, linelen + indent + 20);\n>  \t\tif (indent) {\n>  \t\t\tmemset(sb->buf + sb->len, ' ', indent);\n> -- \n> 1.6.5.rc1.20.geb7d9\n"},{"id":"123651","messageId":"1253655038-20335-1-git-send-email-heipei@hackvalue.de","threadId":"20995","inReplyTo":"7vfxaercma.fsf@alter.siamese.dyndns.org","subject":"[PATCHv4] git-log --format: Add %B tag with %B(n) option","fromName":"Johannes Gilger","fromEmail":"heipei@hackvalue.de","sentAt":"2009-09-22T21:30:38Z","receivedAt":"2009-09-22T21:30:38Z","isPatch":false,"sender":{"key":"heipei@hackvalue.de","avatar":"https://avatars.githubusercontent.com/u/6072?v=4"},"body":"Since one can simply use spaces to indent any other --pretty field we\nshould have an option to do that with the body too.\n\nAlso the %B flag strips the trailing newlines, to enable more compact\ndisplay.\n\nSigned-off-by: Johannes Gilger <heipei@hackvalue.de>\n---\nHey,\n\nI moved the indent >= 0 check to the caller. Also changed the documentation, n \nshould indicate more strongly that n is supposed to be a natural number.\n\nYou mentioned small style issues but I'm not sure what you meant. One thing \nthat could be made more compact is calling \npp_remainder(CMIT_FMT_MEDIUM, &body, sb, indent < 0 ? 0 : indent);\nand thereby saving two extra lines. I saw this at a lot of other spaces in \ngit.git, but saw no specific guideline in CodingGuidelines.\n\nYet another option is aborting for negative indent values, issuing return 0;\n\nGreetings,\nJojo\n\n Documentation/pretty-formats.txt |    2 ++\n pretty.c                         |   29 ++++++++++++++++++++++++-----\n 2 files changed, 26 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt\nindex 2a845b1..ca694c9 100644\n--- a/Documentation/pretty-formats.txt\n+++ b/Documentation/pretty-formats.txt\n@@ -123,6 +123,8 @@ The placeholders are:\n - '%s': subject\n - '%f': sanitized subject line, suitable for a filename\n - '%b': body\n+- '%B': body without trailing newline\n+- '%B(n)': %B indented by n spaces\n - '%Cred': switch color to red\n - '%Cgreen': switch color to green\n - '%Cblue': switch color to blue\ndiff --git a/pretty.c b/pretty.c\nindex f5983f8..dafa8e0 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -605,13 +605,17 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,\n \tint h1, h2;\n \n \t/* these are independent of the commit */\n+\n+\tconst char *body = msg + c->body_off;\n+\tconst char *end = NULL;\n+\t/* check if we have arguments to the placeholder */\n+\tif (placeholder[1] == '(')\n+\t\tend = strchr(placeholder + 2, ')');\n+\n \tswitch (placeholder[0]) {\n \tcase 'C':\n-\t\tif (placeholder[1] == '(') {\n-\t\t\tconst char *end = strchr(placeholder + 2, ')');\n+\t\tif (end) {\n \t\t\tchar color[COLOR_MAXLEN];\n-\t\t\tif (!end)\n-\t\t\t\treturn 0;\n \t\t\tcolor_parse_mem(placeholder + 2,\n \t\t\t\t\tend - (placeholder + 2),\n \t\t\t\t\t\"--pretty format\", color);\n@@ -733,7 +737,22 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,\n \t\tformat_sanitized_subject(sb, msg + c->subject_off);\n \t\treturn 1;\n \tcase 'b':\t/* body */\n-\t\tstrbuf_addstr(sb, msg + c->body_off);\n+\t\tstrbuf_addstr(sb, body);\n+\t\treturn 1;\n+\tcase 'B':\t/* body without trailing newline */\n+\t\tif (end) {\n+\t\t\tchar *endp = NULL;\n+\t\t\tint indent = strtol(placeholder + 2, &endp, 10);\n+\t\t\tif (placeholder + 2 == endp || *endp != ')')\n+\t\t\t\treturn 0;\n+\t\t\tif (indent < 0)\n+\t\t\t\tindent = 0;\n+\t\t\tpp_remainder(CMIT_FMT_MEDIUM, &body, sb, indent);\n+\t\t\tstrbuf_rtrim(sb);\n+\t\t\treturn end - placeholder + 1;\n+\t\t}\n+\t\tstrbuf_addstr(sb, body);\n+\t\tstrbuf_rtrim(sb);\n \t\treturn 1;\n \t}\n \treturn 0;\t/* unknown placeholder */\n-- \n1.6.5.rc1.38.g1fbd3\n"},{"id":"123686","messageId":"alpine.DEB.1.00.0909232232050.4985@pacific.mpi-cbg.de","threadId":"20995","inReplyTo":"1253655038-20335-1-git-send-email-heipei@hackvalue.de","subject":"[PATCH 0/3] Add a pretty format to rewrapping/indenting commit messages","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-09-23T20:34:38Z","receivedAt":"2009-09-23T20:34:38Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nI needed that a long time ago, so I implemented it and let it rut in my\npersonal tree.\n\nMaybe somebody else wants to benefit from my work, too.\n\nJohannes Schindelin (3):\n  print_wrapped_text(): allow hard newlines\n  Add strbuf_add_wrapped_text() to utf8.[ch]\n  Add \"%w\" to pretty formats, which rewraps the commit message\n\n Documentation/pretty-formats.txt |    1 +\n pretty.c                         |   27 ++++++++++++++++++++++\n utf8.c                           |   45 ++++++++++++++++++++++++++++++-------\n utf8.h                           |    2 +\n 4 files changed, 66 insertions(+), 9 deletions(-)\n"},{"id":"123687","messageId":"alpine.DEB.1.00.0909232232560.4985@pacific.mpi-cbg.de","threadId":"20995","inReplyTo":"alpine.DEB.1.00.0909232232050.4985@pacific.mpi-cbg.de","subject":"[PATCH 1/3] print_wrapped_text(): allow hard newlines","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-09-23T20:34:45Z","receivedAt":"2009-09-23T20:34:45Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nprint_wrapped_text() will insert its own newlines. Up until now, if the\ntext passed to it contained newlines, they would not be handled properly\n(the wrapping got confused after that).\n\nThe strategy is to replace a single new-line with a space, but keep double\nnew-lines so that already-wrapped text with empty lines between paragraphs\nwill be handled properly.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n utf8.c |   16 ++++++++++++++--\n 1 files changed, 14 insertions(+), 2 deletions(-)\n\ndiff --git a/utf8.c b/utf8.c\nindex db706ac..589876b 100644\n--- a/utf8.c\n+++ b/utf8.c\n@@ -310,6 +310,8 @@ int print_wrapped_text(const char *text, int indent, int indent2, int width)\n \t\tif (!c || isspace(c)) {\n \t\t\tif (w < width || !space) {\n \t\t\t\tconst char *start = bol;\n+\t\t\t\tif (!c && text == start)\n+\t\t\t\t\treturn w;\n \t\t\t\tif (space)\n \t\t\t\t\tstart = space;\n \t\t\t\telse\n@@ -317,13 +319,23 @@ int print_wrapped_text(const char *text, int indent, int indent2, int width)\n \t\t\t\tfwrite(start, text - start, 1, stdout);\n \t\t\t\tif (!c)\n \t\t\t\t\treturn w;\n-\t\t\t\telse if (c == '\\t')\n-\t\t\t\t\tw |= 0x07;\n \t\t\t\tspace = text;\n+\t\t\t\tif (c == '\\t')\n+\t\t\t\t\tw |= 0x07;\n+\t\t\t\telse if (c == '\\n') {\n+\t\t\t\t\tspace++;\n+\t\t\t\t\tif (*space == '\\n') {\n+\t\t\t\t\t\tputchar('\\n');\n+\t\t\t\t\t\tgoto new_line;\n+\t\t\t\t\t}\n+\t\t\t\t\telse\n+\t\t\t\t\t\tputchar(' ');\n+\t\t\t\t}\n \t\t\t\tw++;\n \t\t\t\ttext++;\n \t\t\t}\n \t\t\telse {\n+new_line:\n \t\t\t\tputchar('\\n');\n \t\t\t\ttext = bol = space + isspace(*space);\n \t\t\t\tspace = NULL;\n-- \n1.6.4.297.gcb4cc\n"},{"id":"123688","messageId":"alpine.DEB.1.00.0909232233330.4985@pacific.mpi-cbg.de","threadId":"20995","inReplyTo":"alpine.DEB.1.00.0909232232560.4985@pacific.mpi-cbg.de","subject":"[PATCH 2/3] Add strbuf_add_wrapped_text() to utf8.[ch]","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-09-23T20:34:51Z","receivedAt":"2009-09-23T20:34:51Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nThe newly added function can rewrap text according to a given first-line\nindent, other-indent and text width.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n utf8.c |   33 ++++++++++++++++++++++++---------\n utf8.h |    2 ++\n 2 files changed, 26 insertions(+), 9 deletions(-)\n\ndiff --git a/utf8.c b/utf8.c\nindex 589876b..7383a70 100644\n--- a/utf8.c\n+++ b/utf8.c\n@@ -1,4 +1,5 @@\n #include \"git-compat-util.h\"\n+#include \"strbuf.h\"\n #include \"utf8.h\"\n \n /* This code is originally from http://www.cl.cam.ac.uk/~mgk25/ucs/ */\n@@ -279,14 +280,22 @@ int is_utf8(const char *text)\n \treturn 1;\n }\n \n-static void print_spaces(int count)\n+static inline void strbuf_write(struct strbuf *sb, const char *buf, int len)\n+{\n+\tif (sb)\n+\t\tstrbuf_insert(sb, sb->len, buf, len);\n+\telse\n+\t\tfwrite(buf, len, 1, stdout);\n+}\n+\n+static void print_spaces(struct strbuf *buf, int count)\n {\n \tstatic const char s[] = \"                    \";\n \twhile (count >= sizeof(s)) {\n-\t\tfwrite(s, sizeof(s) - 1, 1, stdout);\n+\t\tstrbuf_write(buf, s, sizeof(s) - 1);\n \t\tcount -= sizeof(s) - 1;\n \t}\n-\tfwrite(s, count, 1, stdout);\n+\tstrbuf_write(buf, s, count);\n }\n \n /*\n@@ -295,7 +304,8 @@ static void print_spaces(int count)\n  * If indent is negative, assume that already -indent columns have been\n  * consumed (and no extra indent is necessary for the first line).\n  */\n-int print_wrapped_text(const char *text, int indent, int indent2, int width)\n+int strbuf_add_wrapped_text(struct strbuf *buf,\n+\t\tconst char *text, int indent, int indent2, int width)\n {\n \tint w = indent, assume_utf8 = is_utf8(text);\n \tconst char *bol = text, *space = NULL;\n@@ -315,8 +325,8 @@ int print_wrapped_text(const char *text, int indent, int indent2, int width)\n \t\t\t\tif (space)\n \t\t\t\t\tstart = space;\n \t\t\t\telse\n-\t\t\t\t\tprint_spaces(indent);\n-\t\t\t\tfwrite(start, text - start, 1, stdout);\n+\t\t\t\t\tprint_spaces(buf, indent);\n+\t\t\t\tstrbuf_write(buf, start, text - start);\n \t\t\t\tif (!c)\n \t\t\t\t\treturn w;\n \t\t\t\tspace = text;\n@@ -325,18 +335,18 @@ int print_wrapped_text(const char *text, int indent, int indent2, int width)\n \t\t\t\telse if (c == '\\n') {\n \t\t\t\t\tspace++;\n \t\t\t\t\tif (*space == '\\n') {\n-\t\t\t\t\t\tputchar('\\n');\n+\t\t\t\t\t\tstrbuf_write(buf, \"\\n\", 1);\n \t\t\t\t\t\tgoto new_line;\n \t\t\t\t\t}\n \t\t\t\t\telse\n-\t\t\t\t\t\tputchar(' ');\n+\t\t\t\t\t\tstrbuf_write(buf, \" \", 1);\n \t\t\t\t}\n \t\t\t\tw++;\n \t\t\t\ttext++;\n \t\t\t}\n \t\t\telse {\n new_line:\n-\t\t\t\tputchar('\\n');\n+\t\t\t\tstrbuf_write(buf, \"\\n\", 1);\n \t\t\t\ttext = bol = space + isspace(*space);\n \t\t\t\tspace = NULL;\n \t\t\t\tw = indent = indent2;\n@@ -352,6 +362,11 @@ new_line:\n \t}\n }\n \n+int print_wrapped_text(const char *text, int indent, int indent2, int width)\n+{\n+\treturn strbuf_add_wrapped_text(NULL, text, indent, indent2, width);\n+}\n+\n int is_encoding_utf8(const char *name)\n {\n \tif (!name)\ndiff --git a/utf8.h b/utf8.h\nindex 2f1b14f..ae30ae4 100644\n--- a/utf8.h\n+++ b/utf8.h\n@@ -10,6 +10,8 @@ int is_utf8(const char *text);\n int is_encoding_utf8(const char *name);\n \n int print_wrapped_text(const char *text, int indent, int indent2, int len);\n+int strbuf_add_wrapped_text(struct strbuf *buf,\n+\t\tconst char *text, int indent, int indent2, int width);\n \n #ifndef NO_ICONV\n char *reencode_string(const char *in, const char *out_encoding, const char *in_encoding);\n-- \n1.6.4.297.gcb4cc\n"},{"id":"123689","messageId":"alpine.DEB.1.00.0909232233590.4985@pacific.mpi-cbg.de","threadId":"20995","inReplyTo":"alpine.DEB.1.00.0909232233330.4985@pacific.mpi-cbg.de","subject":"[PATCH 3/3] Add \"%w\" to pretty formats, which rewraps the commit message","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-09-23T20:34:57Z","receivedAt":"2009-09-23T20:34:57Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nSome repositories contain commit messages that are insanely long.\nAnd not always is it an option to rewrite the commits with rewrapped\ncommit messages; just think of cvsimports or some such.\n\nNow here is a remedy.\n\nWith \"--pretty=format:%w(8,6,70)\" you will get the commit messages\nreformatted to width 70 where the first line has indent 8 and the\nsubsequent lines have indent 6.\n\nThe following command will output something similar to plain \"git log\n--color\", except that the commit bodies will be rewrapped to fit inside\n80 columns:\n\n\tgit log --pretty=format:'%C(yellow)commit %H%C(reset)\n\tAuthor: %an <%ae>\n\tDate: %ad\n\n\t%w(4,4,80)'\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n Documentation/pretty-formats.txt |    1 +\n pretty.c                         |   27 +++++++++++++++++++++++++++\n 2 files changed, 28 insertions(+), 0 deletions(-)\n\ndiff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt\nindex 2a845b1..d727995 100644\n--- a/Documentation/pretty-formats.txt\n+++ b/Documentation/pretty-formats.txt\n@@ -123,6 +123,7 @@ The placeholders are:\n - '%s': subject\n - '%f': sanitized subject line, suitable for a filename\n - '%b': body\n+- '%w(indent,indent2,width)': rewrapped subject and body\n - '%Cred': switch color to red\n - '%Cgreen': switch color to green\n - '%Cblue': switch color to blue\ndiff --git a/pretty.c b/pretty.c\nindex f5983f8..639469e 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -595,6 +595,30 @@ static void format_decoration(struct strbuf *sb, const struct commit *commit)\n \t\tstrbuf_addch(sb, ')');\n }\n \n+static int rewrap_text(struct strbuf *sb, const char *params, const char *text)\n+{\n+\tint indent = 4, indent2 = 4, width = 80, pacmanned = 1;\n+\n+\tif (params[0] == '(') {\n+\t\tchar *p;\n+\n+\t\tindent = strtoul(params + 1, &p, 0);\n+\t\tif (*p == ',') {\n+\t\t\tindent2 = strtoul(p + 1, &p, 0);\n+\t\t\tif (*p == ',')\n+\t\t\t\twidth = strtoul(p + 1, &p, 0);\n+\t\t}\n+\t\tif (*p != ')') {\n+\t\t\terror (\"Invalid parameters: %.*s\",\n+\t\t\t\t\t(int)(p - params), params);\n+\t\t\treturn 0;\n+\t\t}\n+\t\tpacmanned = p + 1 - params;\n+\t}\n+\tstrbuf_add_wrapped_text(sb, text, indent, indent2, width);\n+\treturn pacmanned;\n+}\n+\n static size_t format_commit_item(struct strbuf *sb, const char *placeholder,\n                                void *context)\n {\n@@ -735,6 +759,9 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,\n \tcase 'b':\t/* body */\n \t\tstrbuf_addstr(sb, msg + c->body_off);\n \t\treturn 1;\n+\tcase 'w':\t/* re-wrapped body */\n+\t\treturn rewrap_text(sb, placeholder + 1,\n+\t\t\t\tmsg + c->subject_off) + 1;\n \t}\n \treturn 0;\t/* unknown placeholder */\n }\n-- \n1.6.4.297.gcb4cc\n"},{"id":"123691","messageId":"20090923210055.GA25197@dualtron.vpn.rwth-aachen.de","threadId":"20995","inReplyTo":"alpine.DEB.1.00.0909232233590.4985@pacific.mpi-cbg.de","subject":"Re: [PATCH 3/3] Add \"%w\" to pretty formats, which rewraps the commit message","fromName":"Johannes Gilger","fromEmail":"heipei@hackvalue.de","sentAt":"2009-09-23T21:00:56Z","receivedAt":"2009-09-23T21:00:56Z","isPatch":true,"sender":{"key":"heipei@hackvalue.de","avatar":"https://avatars.githubusercontent.com/u/6072?v=4"},"body":"On 23/09/09 22:34, Johannes Schindelin wrote:\n> With \"--pretty=format:%w(8,6,70)\" you will get the commit messages\n> reformatted to width 70 where the first line has indent 8 and the\n> subsequent lines have indent 6.\n\nHey Johannes,\n\nyou sent me your patches earlier (and I really liked the idea and could \nuse it too, especially with svn-mindset people). One thing that bothers \nme about the %w flag is that is includes subject and body, when we \nalready have atoms for both of these flags. So having a subject(x,y) and \nbody(x,y) tag (where x is indent and y is textwidth to be rewrapped) \nwould be nicer and more in the spirit of the existing format options \nimho.\n\nHaving said that I also have to acknowledge a clear advantage of your \npatch, which is that one doesn't need to clear trailing newlines when \nthe subject is < wrapwidth and the body is empty (and one used \n%s(x,y)%n%n%b(x,y) as a format-tag). With my %B, %B(n) patch which is on \npu (and which you should probably consider in case it gets into next ;) \nI do this by calling strbuf_rtrim after adding the body.\n\nGreetings,\nJojo\n\n-- \nJohannes Gilger <heipei@hackvalue.de>\nhttp://heipei.net\nGPG-Key: 0x42F6DE81\nGPG-Fingerprint: BB49 F967 775E BB52 3A81  882C 58EE B178 42F6 DE81\n"},{"id":"123703","messageId":"7v63b9gsg1.fsf@alter.siamese.dyndns.org","threadId":"20995","inReplyTo":"20090923210055.GA25197@dualtron.vpn.rwth-aachen.de","subject":"Re: [PATCH 3/3] Add \"%w\" to pretty formats, which rewraps the commit message","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-23T23:19:26Z","receivedAt":"2009-09-23T23:19:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Gilger <heipei@hackvalue.de> writes:\n\n> ... One thing that bothers \n> me about the %w flag is that is includes subject and body, when we \n> already have atoms for both of these flags. So having a subject(x,y) and \n> body(x,y) tag (where x is indent and y is textwidth to be rewrapped) \n> would be nicer and more in the spirit of the existing format options \n> imho.\n\nI do not particularly like this %w() either, and would prefer to see an\nequivalent solution using combination of %S(i,j,w) and %B(i,j,w).  Your\n%B(n) can be extended to do the same as Johannes's wrapping variant when\ngiven three parameters and you can trivially do the same for %s to produce\n%S(n) and %S(i,j,w).\n\nOne issue %w() sidesteps is handing of single liner commit log messages\n(this is not a new issue your %B(n) introduces).  \"%s%n%b\" will give us\nthe original message only when the log has some contents in addition to\nthe single-line summary.  Otherwise we will get an extra blank line.\n\nPerhaps we could extend the pretty-printer so that it understands %+x\nnotation, which expands to %n%x when %x expands to a non-empty result, and\notherwise it expands to empty, as a generic extension applicable to any\nformat specifier 'x'.  If we have such a notation, \"%s%+b\", would be a\nreasonable way to say \"give us the original commit log message here\", and\nwe won't need %w(i,j,w) -- we can instead say %S(i,j,w)%+B(i,j,w), or\n%s%+B(i,j,w) depending on what you want.\n"},{"id":"123706","messageId":"alpine.LFD.2.01.0909231659010.3303@localhost.localdomain","threadId":"20995","inReplyTo":"alpine.DEB.1.00.0909232232560.4985@pacific.mpi-cbg.de","subject":"Re: [PATCH 1/3] print_wrapped_text(): allow hard newlines","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2009-09-24T00:00:58Z","receivedAt":"2009-09-24T00:00:58Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Wed, 23 Sep 2009, Johannes Schindelin wrote:\n> \n> print_wrapped_text() will insert its own newlines. Up until now, if the\n> text passed to it contained newlines, they would not be handled properly\n> (the wrapping got confused after that).\n> \n> The strategy is to replace a single new-line with a space, but keep double\n> new-lines so that already-wrapped text with empty lines between paragraphs\n> will be handled properly.\n\nMay I suggest doing this _only_ if the newline is followed by an \nalphanumeric characer?\n\nIf the thing is indented (\"newline + space\") or quoted (\"newline + \">\" or \nwhatever) then reflowing it is likely wrong and will result in an unholy \nmess.\n\n\t\t\tLinus\n"},{"id":"123707","messageId":"alpine.DEB.1.00.0909240214550.4985@pacific.mpi-cbg.de","threadId":"20995","inReplyTo":"alpine.LFD.2.01.0909231659010.3303@localhost.localdomain","subject":"Re: [PATCH 1/3] print_wrapped_text(): allow hard newlines","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-09-24T00:19:40Z","receivedAt":"2009-09-24T00:19:40Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 23 Sep 2009, Linus Torvalds wrote:\n\n> On Wed, 23 Sep 2009, Johannes Schindelin wrote:\n> > \n> > print_wrapped_text() will insert its own newlines. Up until now, if the\n> > text passed to it contained newlines, they would not be handled properly\n> > (the wrapping got confused after that).\n> > \n> > The strategy is to replace a single new-line with a space, but keep double\n> > new-lines so that already-wrapped text with empty lines between paragraphs\n> > will be handled properly.\n> \n> May I suggest doing this _only_ if the newline is followed by an \n> alphanumeric characer?\n> \n> If the thing is indented (\"newline + space\") or quoted (\"newline + \">\" or \n> whatever) then reflowing it is likely wrong and will result in an unholy \n> mess.\n\nIt seems Junio is dead-set on ignoring my patches, so I will probably just \nkeep the patch as-is in my tree for the time being.  The other Johannes' \npatch is too limited for me to use, so I _will_ keep my patch, but I have \nway too little time to fight an uphill battle to get my patch in.  And \nsince it stays a private patch (just like my strbuf_vaddf() patch) I will \nhave to refrain from putting more work and time into it than I already \nhave.\n\nSorry,\nDscho\n"},{"id":"123759","messageId":"alpine.DEB.1.00.0909251018200.4985@pacific.mpi-cbg.de","threadId":"20995","inReplyTo":"alpine.LFD.2.01.0909231659010.3303@localhost.localdomain","subject":"Re: [PATCH 1/3] print_wrapped_text(): allow hard newlines","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-09-25T08:21:02Z","receivedAt":"2009-09-25T08:21:02Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 23 Sep 2009, Linus Torvalds wrote:\n\n> On Wed, 23 Sep 2009, Johannes Schindelin wrote:\n> > \n> > print_wrapped_text() will insert its own newlines. Up until now, if \n> > the text passed to it contained newlines, they would not be handled \n> > properly (the wrapping got confused after that).\n> > \n> > The strategy is to replace a single new-line with a space, but keep \n> > double new-lines so that already-wrapped text with empty lines between \n> > paragraphs will be handled properly.\n> \n> May I suggest doing this _only_ if the newline is followed by an \n> alphanumeric characer?\n> \n> If the thing is indented (\"newline + space\") or quoted (\"newline + \">\" \n> or whatever) then reflowing it is likely wrong and will result in an \n> unholy mess.\n\nAfter further consideration, I decided to heed your advice; it is an \nobvious improvement when comparing the output with and without the \nisalnum().\n\nSo I updated my log-rewrap branch:\n\nhttp://repo.or.cz/w/git/dscho.git?a=shortlog;h=refs/heads/log-rewrap\n\nThanks,\nDscho\n"},{"id":"124221","messageId":"7v63augxx8.fsf@alter.siamese.dyndns.org","threadId":"20995","inReplyTo":"7v63b9gsg1.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 3/3] Add \"%w\" to pretty formats, which rewraps the commit message","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-10-05T06:25:07Z","receivedAt":"2009-10-05T06:25:07Z","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> One issue %w() sidesteps is handing of single liner commit log messages\n> (this is not a new issue your %B(n) introduces).  \"%s%n%b\" will give us\n> the original message only when the log has some contents in addition to\n> the single-line summary.  Otherwise we will get an extra blank line.\n>\n> Perhaps we could extend the pretty-printer so that it understands %+x\n> notation, which expands to %n%x when %x expands to a non-empty result, and\n> otherwise it expands to empty, as a generic extension applicable to any\n> format specifier 'x'.  If we have such a notation, \"%s%+b\", would be a\n> reasonable way to say \"give us the original commit log message here\", and\n> we won't need %w(i,j,w) -- we can instead say %S(i,j,w)%+B(i,j,w), or\n> %s%+B(i,j,w) depending on what you want.\n\nThis teaches the machinery to add a separator LF before any non-empty\nexpansion of '%x' if you ask '%+x', and also removes LF if '%x' expands to\nan empty string if you ask '%-x', for any supported expansion placeholder\n'x' it supports.\n\nWith the first two patches Dscho posted (and then polished in his tree),\nit shouldn't be too hard to update your %B(n) to %B(i,j,w) and also add\n%S(i,j,w) in a similar way, to allow people to say %S(i,j,w)%+B(i,j,w)\ninstead of (or in addition to) his %w(i,j,w).\n\n\n\n pretty.c                   |   42 ++++++++++++++++++++++++++++++++++++++++--\n t/t6006-rev-list-format.sh |   22 ++++++++++++++++++++++\n 2 files changed, 62 insertions(+), 2 deletions(-)\n\ndiff --git a/pretty.c b/pretty.c\nindex f5983f8..081feb6 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -595,8 +595,8 @@ static void format_decoration(struct strbuf *sb, const struct commit *commit)\n \t\tstrbuf_addch(sb, ')');\n }\n \n-static size_t format_commit_item(struct strbuf *sb, const char *placeholder,\n-                               void *context)\n+static size_t format_commit_one(struct strbuf *sb, const char *placeholder,\n+\t\t\t\tvoid *context)\n {\n \tstruct format_commit_context *c = context;\n \tconst struct commit *commit = c->commit;\n@@ -739,6 +739,44 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,\n \treturn 0;\t/* unknown placeholder */\n }\n \n+static size_t format_commit_item(struct strbuf *sb, const char *placeholder,\n+\t\t\t\t void *context)\n+{\n+\tint consumed;\n+\tsize_t orig_len;\n+\tenum {\n+\t\tNO_MAGIC,\n+\t\tADD_LF_BEFORE_NON_EMPTY,\n+\t\tDEL_LF_BEFORE_EMPTY,\n+\t} magic = NO_MAGIC;\n+\n+\tswitch (placeholder[0]) {\n+\tcase '-':\n+\t\tmagic = DEL_LF_BEFORE_EMPTY;\n+\t\tbreak;\n+\tcase '+':\n+\t\tmagic = ADD_LF_BEFORE_NON_EMPTY;\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\tif (magic != NO_MAGIC)\n+\t\tplaceholder++;\n+\n+\torig_len = sb->len;\n+\tconsumed = format_commit_one(sb, placeholder, context);\n+\tif (magic == NO_MAGIC)\n+\t\treturn consumed;\n+\n+\tif ((orig_len == sb->len) && magic == DEL_LF_BEFORE_EMPTY) {\n+\t\twhile (sb->len && sb->buf[sb->len - 1] == '\\n')\n+\t\t\tstrbuf_setlen(sb, sb->len - 1);\n+\t} else if ((orig_len != sb->len) && magic == ADD_LF_BEFORE_NON_EMPTY) {\n+\t\tstrbuf_insert(sb, orig_len, \"\\n\", 1);\n+\t}\n+\treturn consumed + 1;\n+}\n+\n void format_commit_message(const struct commit *commit,\n \t\t\t   const void *format, struct strbuf *sb,\n \t\t\t   enum date_mode dmode)\ndiff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh\nindex 59d1f62..18a77a7 100755\n--- a/t/t6006-rev-list-format.sh\n+++ b/t/t6006-rev-list-format.sh\n@@ -162,4 +162,26 @@ test_expect_success 'empty email' '\n \t}\n '\n \n+test_expect_success 'del LF before empty (1)' '\n+\tgit show -s --pretty=format:\"%s%n%-b%nThanks%n\" HEAD^^ >actual &&\n+\ttest $(wc -l <actual) = 2\n+'\n+\n+test_expect_success 'del LF before empty (2)' '\n+\tgit show -s --pretty=format:\"%s%n%-b%nThanks%n\" HEAD >actual &&\n+\ttest $(wc -l <actual) = 6 &&\n+\tgrep \"^$\" actual\n+'\n+\n+test_expect_success 'add LF before non-empty (1)' '\n+\tgit show -s --pretty=format:\"%s%+b%nThanks%n\" HEAD^^ >actual &&\n+\ttest $(wc -l <actual) = 2\n+'\n+\n+test_expect_success 'add LF before non-empty (2)' '\n+\tgit show -s --pretty=format:\"%s%+b%nThanks%n\" HEAD >actual &&\n+\ttest $(wc -l <actual) = 6 &&\n+\tgrep \"^$\" actual\n+'\n+\n test_done\n.\n"},{"id":"124548","messageId":"7vzl80dq1b.fsf@alter.siamese.dyndns.org","threadId":"20995","inReplyTo":"1253655038-20335-1-git-send-email-heipei@hackvalue.de","subject":"Re: [PATCHv4] git-log --format: Add %B tag with %B(n) option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-10-10T00:57:20Z","receivedAt":"2009-10-10T00:57:20Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Gilger <heipei@hackvalue.de> writes:\n\n> diff --git a/pretty.c b/pretty.c\n> index f5983f8..dafa8e0 100644\n> --- a/pretty.c\n> +++ b/pretty.c\n> @@ -605,13 +605,17 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,\n>  \tint h1, h2;\n>  \n>  \t/* these are independent of the commit */\n> +\n> +\tconst char *body = msg + c->body_off;\n> +\tconst char *end = NULL;\n\nUnfortunately, c->body_off is not valid until you make a call to\nparse_commit_message().  Obviously, body is used only after such a call is\nmade in the original, so I fixed this initialization into an explicit\nassignment after the call.\n"}]}