{"thread":{"id":"41709","subject":"[PATCH] pretty-print: de-tabify indented logs to make things line up properly","startedAt":"2016-03-16T16:29:35Z","lastAt":"2016-04-05T07:13:52Z","messageCount":57,"participants":["Linus Torvalds","Junio C Hamano","Jeff King","Torsten Bögershausen","Eric Sunshine","Perry Hutchison"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"280914","messageId":"alpine.LFD.2.20.1603160926060.13030@i7","threadId":"41709","inReplyTo":null,"subject":"[PATCH] pretty-print: de-tabify indented logs to make things line up properly","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2016-03-16T16:29:35Z","receivedAt":"2016-03-16T16:29:35Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\nFrom: Linus Torvalds <torvalds@linux-foundation.org>\nDate: Wed, 16 Mar 2016 09:15:53 -0700\nSubject: [PATCH] pretty-print: de-tabify indented logs to make things line up properly\n\nThis should all line up:\n\n  Column 1\tColumn 2\n  --------\t--------\n  A\t\tB\n  ABCD\t\tEFGH\n  SPACES        Instead of Tabs\n\nEven with multi-byte UTF8 characters:\n\n  Column 1\tColumn 2\n  --------\t--------\n  Ä\t\tB\n  åäö\t\t100\n  A Møøse\tonce bit my sister..\n\nSigned-off-by: Linus Torvalds <torvalds@linux-foundation.org>\n---\n\nThis seems to work for me, and while there is some cost, it's minimal. \nDoing a \"git log > /dev/null\" of the current git tree is about 1% slower \nbecause of the tab-finding. A tree with a lot of tabs in the commit \nmessages would be more noticeable, because then you actually end up \nhitting the whole \"how wide is this\" issue.\n\n(But if the tabs are all at the beginning of a line, you'd still be ok \nand avoid the utf8 width calculations).\n\nComments?\n\n pretty.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--\n 1 file changed, 74 insertions(+), 2 deletions(-)\n\ndiff --git a/pretty.c b/pretty.c\nindex 92b2870a7eab..0b40457f99f0 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -1629,6 +1629,76 @@ void pp_title_line(struct pretty_print_context *pp,\n \tstrbuf_release(&title);\n }\n \n+static int pp_utf8_width(const char *start, const char *end)\n+{\n+\tint width = 0;\n+\tsize_t remain = end - start;\n+\n+\twhile (remain) {\n+\t\tint n = utf8_width(&start, &remain);\n+\t\tif (n < 0 || !start)\n+\t\t\treturn -1;\n+\t\twidth += n;\n+\t}\n+\treturn width;\n+}\n+\n+/*\n+ * pp_handle_indent() prints out the intendation, and\n+ * perhaps the whole line (without the final newline)\n+ *\n+ * Why \"perhaps\"? If there are tabs in the indented line\n+ * it will print it out in order to de-tabify the line.\n+ *\n+ * But if there are no tabs, we just fall back on the\n+ * normal \"print the whole line\".\n+ */\n+static int pp_handle_indent(struct strbuf *sb, int indent,\n+\t\t\t     const char *line, int linelen)\n+{\n+\tconst char *tab;\n+\n+\tstrbuf_addchars(sb, ' ', indent);\n+\n+\ttab = memchr(line, '\\t', linelen);\n+\tif (!tab)\n+\t\treturn 0;\n+\n+\tdo {\n+\t\tint width = pp_utf8_width(line, tab);\n+\n+\t\t/*\n+\t\t * If it wasn't well-formed utf8, or it\n+\t\t * had characters with badly defined\n+\t\t * width (control characters etc), just\n+\t\t * give up on trying to align things.\n+\t\t */\n+\t\tif (width < 0)\n+\t\t\tbreak;\n+\n+\t\t/* Output the data .. */\n+\t\tstrbuf_add(sb, line, tab - line);\n+\n+\t\t/* .. and the de-tabified tab */\n+\t\tstrbuf_addchars(sb, ' ', 8-(width & 7));\n+\n+\t\t/* Skip over the printed part .. */\n+\t\tlinelen -= 1+tab-line;\n+\t\tline = tab + 1;\n+\n+\t\t/* .. and look for the next tab */\n+\t\ttab = memchr(line, '\\t', linelen);\n+\t} while (tab);\n+\n+\t/*\n+\t * Print out everything after the last tab without\n+\t * worrying about width - there's nothing more to\n+\t * align.\n+\t */\n+\tstrbuf_add(sb, line, linelen);\n+\treturn 1;\n+}\n+\n void pp_remainder(struct pretty_print_context *pp,\n \t\t  const char **msg_p,\n \t\t  struct strbuf *sb,\n@@ -1652,8 +1722,10 @@ void pp_remainder(struct pretty_print_context *pp,\n \t\tfirst = 0;\n \n \t\tstrbuf_grow(sb, linelen + indent + 20);\n-\t\tif (indent)\n-\t\t\tstrbuf_addchars(sb, ' ', indent);\n+\t\tif (indent) {\n+\t\t\tif (pp_handle_indent(sb, indent, line, linelen))\n+\t\t\t\tlinelen = 0;\n+\t\t}\n \t\tstrbuf_add(sb, line, linelen);\n \t\tstrbuf_addch(sb, '\\n');\n \t}\n-- \n2.8.0.rc2\n"},{"id":"280919","messageId":"CA+55aFx2Yv6=zu_5cXOjeMEKTq1yeqDidRr820HzOSAj3xFb-g@mail.gmail.com","threadId":"41709","inReplyTo":"alpine.LFD.2.20.1603160926060.13030@i7","subject":"Re: [PATCH] pretty-print: de-tabify indented logs to make things line up properly","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2016-03-16T16:52:00Z","receivedAt":"2016-03-16T16:52:00Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"On Wed, Mar 16, 2016 at 9:29 AM, Linus Torvalds\n<torvalds@linux-foundation.org> wrote:\n>\n> This should all line up:\n>\n>   Column 1      Column 2\n>   --------      --------\n>   A             B\n>   ABCD          EFGH\n>   SPACES        Instead of Tabs\n>\n> Even with multi-byte UTF8 characters:\n>\n>   Column 1      Column 2\n>   --------      --------\n>   Ä             B\n>   åäö           100\n>   A Møøse       once bit my sister..\n\nSo with current git, it looks like this for me:\n\n      Column 1  Column 2\n      --------  --------\n      A         B\n      ABCD              EFGH\n      SPACES        Instead of Tabs\n\n    Even with multi-byte UTF8 characters:\n\n      Column 1  Column 2\n      --------  --------\n      Ä         B\n      åäö               100\n      A Møøse   once bit my sister..\n\nand with that patch it looks much better:\n\n      Column 1      Column 2\n      --------      --------\n      A             B\n      ABCD          EFGH\n      SPACES        Instead of Tabs\n\n    Even with multi-byte UTF8 characters:\n\n      Column 1      Column 2\n      --------      --------\n      Ä             B\n      åäö           100\n      A Møøse       once bit my sister..\n\n(of course, to see that assumes that you have a fixed-sized font in\nyour mail viewer, and that the spacing didn't get screwed up by my\ncut-and-paste).\n\n             Linus\n"},{"id":"280933","messageId":"xmqq7fh25mkc.fsf@gitster.mtv.corp.google.com","threadId":"41709","inReplyTo":"alpine.LFD.2.20.1603160926060.13030@i7","subject":"Re: [PATCH] pretty-print: de-tabify indented logs to make things line up properly","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-16T18:01:39Z","receivedAt":"2016-03-16T18:01:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@linux-foundation.org> writes:\n\n> From: Linus Torvalds <torvalds@linux-foundation.org>\n> Date: Wed, 16 Mar 2016 09:15:53 -0700\n> Subject: [PATCH] pretty-print: de-tabify indented logs to make things line up properly\n>\n> This should all line up:\n>\n>   Column 1\tColumn 2\n>   --------\t--------\n>   A\t\tB\n>   ABCD\t\tEFGH\n>   SPACES        Instead of Tabs\n>\n> Even with multi-byte UTF8 characters:\n>\n>   Column 1\tColumn 2\n>   --------\t--------\n>   Ä\t\tB\n>   åäö\t\t100\n>   A Møøse\tonce bit my sister..\n>\n> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>\n> ---\n>\n> This seems to work for me, and while there is some cost, it's minimal. \n> Doing a \"git log > /dev/null\" of the current git tree is about 1% slower \n> because of the tab-finding. A tree with a lot of tabs in the commit \n> messages would be more noticeable, because then you actually end up \n> hitting the whole \"how wide is this\" issue.\n>\n> (But if the tabs are all at the beginning of a line, you'd still be ok \n> and avoid the utf8 width calculations).\n>\n> Comments?\n\nI stared at it for a while, and didn't spot anything wrong with it.\n\nI did wonder about two things, though:\n\n (1) if turning your \"preparation; do { ... } while()\" into\n     \"while () { }\" would make the result a bit easier to read;\n\n (2) if we can somehow eliminate duplication of \"tab + 1\" (spelled\n     differently on the previous line as \"1+tab\"), the end result\n     may get easier to follow.\n\nbut both are minor.\n\n>  pretty.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--\n>  1 file changed, 74 insertions(+), 2 deletions(-)\n>\n> diff --git a/pretty.c b/pretty.c\n> index 92b2870a7eab..0b40457f99f0 100644\n> --- a/pretty.c\n> +++ b/pretty.c\n> @@ -1629,6 +1629,76 @@ void pp_title_line(struct pretty_print_context *pp,\n>  \tstrbuf_release(&title);\n>  }\n>  \n> +static int pp_utf8_width(const char *start, const char *end)\n> +{\n> +\tint width = 0;\n> +\tsize_t remain = end - start;\n> +\n> +\twhile (remain) {\n> +\t\tint n = utf8_width(&start, &remain);\n> +\t\tif (n < 0 || !start)\n> +\t\t\treturn -1;\n> +\t\twidth += n;\n> +\t}\n> +\treturn width;\n> +}\n> +\n> +/*\n> + * pp_handle_indent() prints out the intendation, and\n> + * perhaps the whole line (without the final newline)\n> + *\n> + * Why \"perhaps\"? If there are tabs in the indented line\n> + * it will print it out in order to de-tabify the line.\n> + *\n> + * But if there are no tabs, we just fall back on the\n> + * normal \"print the whole line\".\n> + */\n> +static int pp_handle_indent(struct strbuf *sb, int indent,\n> +\t\t\t     const char *line, int linelen)\n> +{\n> +\tconst char *tab;\n> +\n> +\tstrbuf_addchars(sb, ' ', indent);\n> +\n> +\ttab = memchr(line, '\\t', linelen);\n> +\tif (!tab)\n> +\t\treturn 0;\n> +\n> +\tdo {\n> +\t\tint width = pp_utf8_width(line, tab);\n> +\n> +\t\t/*\n> +\t\t * If it wasn't well-formed utf8, or it\n> +\t\t * had characters with badly defined\n> +\t\t * width (control characters etc), just\n> +\t\t * give up on trying to align things.\n> +\t\t */\n> +\t\tif (width < 0)\n> +\t\t\tbreak;\n> +\n> +\t\t/* Output the data .. */\n> +\t\tstrbuf_add(sb, line, tab - line);\n> +\n> +\t\t/* .. and the de-tabified tab */\n> +\t\tstrbuf_addchars(sb, ' ', 8-(width & 7));\n> +\n> +\t\t/* Skip over the printed part .. */\n> +\t\tlinelen -= 1+tab-line;\n> +\t\tline = tab + 1;\n> +\n> +\t\t/* .. and look for the next tab */\n> +\t\ttab = memchr(line, '\\t', linelen);\n> +\t} while (tab);\n> +\n> +\t/*\n> +\t * Print out everything after the last tab without\n> +\t * worrying about width - there's nothing more to\n> +\t * align.\n> +\t */\n> +\tstrbuf_add(sb, line, linelen);\n> +\treturn 1;\n> +}\n> +\n>  void pp_remainder(struct pretty_print_context *pp,\n>  \t\t  const char **msg_p,\n>  \t\t  struct strbuf *sb,\n> @@ -1652,8 +1722,10 @@ void pp_remainder(struct pretty_print_context *pp,\n>  \t\tfirst = 0;\n>  \n>  \t\tstrbuf_grow(sb, linelen + indent + 20);\n> -\t\tif (indent)\n> -\t\t\tstrbuf_addchars(sb, ' ', indent);\n> +\t\tif (indent) {\n> +\t\t\tif (pp_handle_indent(sb, indent, line, linelen))\n> +\t\t\t\tlinelen = 0;\n> +\t\t}\n>  \t\tstrbuf_add(sb, line, linelen);\n>  \t\tstrbuf_addch(sb, '\\n');\n>  \t}\n"},{"id":"280940","messageId":"CA+55aFxV5PWdSn9Gj=zV464TtJo=QvciZrhc5Pwe+Qfyqt8sXw@mail.gmail.com","threadId":"41709","inReplyTo":"xmqq7fh25mkc.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH] pretty-print: de-tabify indented logs to make things line up properly","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2016-03-16T18:21:48Z","receivedAt":"2016-03-16T18:21:48Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"On Wed, Mar 16, 2016 at 11:01 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>\n>  (1) if turning your \"preparation; do { ... } while()\" into\n>      \"while () { }\" would make the result a bit easier to read;\n\nSo it's probably partly taste, but I will also disagree with your\n\"easier to read\", because of the way the code is logically structured.\n\nIn particular, the \"no TAB\" case is actually *fundamentally* different\nfrom the \"no TAB at the end\" case. The return value is different, and\nthe caller does very different things - the code tries to make it very\nclear that that \"no TAB\" situation is very different from \"we found a\nTAB\".\n\nSo it's not \"preparation + do-while\".\n\nIt's \"preparation + handle the no-TAB case differently\", and then the\n\"do-while\" is very natural because by the time we get to the \"ok, we\nare now going to need to do something about the line\" stage, we\nalready know we have a tab.\n\nBut the code *could* be made to just always do the whole\n\"strbuf_add()\", and not return a return value at all, and the no-tab\ncase wouldn't be explicitly written to be different.\n\nLet me know if you'd prefer that variant, and I'll send a new version.\n\n>  (2) if we can somehow eliminate duplication of \"tab + 1\" (spelled\n>      differently on the previous line as \"1+tab\"), the end result\n>      may get easier to follow.\n\nYeah, I considered that. Either by just doing \"tab++\" before (so the\n+1\" would come from that in both cases), or by introducing a new\nvariable like\n\n    ptrdiff_t bytes_used;\n    ...\n    bytes_used = 1 + tab - line;\n\nand then just doing\n\n    line += bytes_used;\n    linelen -= bytes_used;\n\nand the code I wrote just didn't do any of those temporary updates,\nand instead just did the \"+1\" by hand in both cases.\n\nAgain, I can redo the patch, just tell me which model you prefer.\n\n                 Linus\n"},{"id":"280947","messageId":"xmqqwpp243sb.fsf@gitster.mtv.corp.google.com","threadId":"41709","inReplyTo":"CA+55aFxV5PWdSn9Gj=zV464TtJo=QvciZrhc5Pwe+Qfyqt8sXw@mail.gmail.com","subject":"Re: [PATCH] pretty-print: de-tabify indented logs to make things line up properly","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-16T19:32:36Z","receivedAt":"2016-03-16T19:32:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@linux-foundation.org> writes:\n\n> On Wed, Mar 16, 2016 at 11:01 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>>\n>>  (1) if turning your \"preparation; do { ... } while()\" into\n>>      \"while () { }\" would make the result a bit easier to read;\n>\n> So it's probably partly taste, but I will also disagree with your\n> \"easier to read\", because of the way the code is logically structured.\n>\n> In particular, the \"no TAB\" case is actually *fundamentally* different\n> from the \"no TAB at the end\" case. The return value is different, and\n> the caller does very different things - the code tries to make it very\n> clear that that \"no TAB\" situation is very different from \"we found a\n> TAB\".\n>\n> So it's not \"preparation + do-while\".\n>\n> It's \"preparation + handle the no-TAB case differently\", and then the\n> \"do-while\" is very natural because by the time we get to the \"ok, we\n> are now going to need to do something about the line\" stage, we\n> already know we have a tab.\n\nOK, I agree with that viewpoint; retracted.\n\n>>  (2) if we can somehow eliminate duplication of \"tab + 1\" (spelled\n>>      differently on the previous line as \"1+tab\"), the end result\n>>      may get easier to follow.\n>\n> Yeah, I considered that. Either by just doing \"tab++\" before (so the\n> +1\" would come from that in both cases), or by introducing a new\n> variable like\n>\n>     ptrdiff_t bytes_used;\n>     ...\n>     bytes_used = 1 + tab - line;\n>\n> and then just doing\n>\n>     line += bytes_used;\n>     linelen -= bytes_used;\n>\n> and the code I wrote just didn't do any of those temporary updates,\n> and instead just did the \"+1\" by hand in both cases.\n\nThe above is most likely what I would have written if I were doing\nthis patch.  I could squash it to save a round-trip, but let me run\nthe testsuite first to see if we need adjustments to existing tests.\n\nAlso your idea:\n\n> But the code *could* be made to just always do the whole\n> \"strbuf_add()\", and not return a return value at all, and the no-tab\n> case wouldn't be explicitly written to be different.\n\nmay give us a better structure if we are going to give users a knob\nto disable this tab expansion, i.e. move the addition of 4 spaces to\nthe caller, name the body of such a function strbuf_expand_add(),\nand then make the caller do something like this perhaps?\n\n@@ -1723,10 +1711,14 @@ void pp_remainder(struct pretty_print_context *pp,\n \n \t\tstrbuf_grow(sb, linelen + indent + 20);\n \t\tif (indent) {\n-\t\t\tif (pp_handle_indent(sb, indent, line, linelen))\n-\t\t\t\tlinelen = 0;\n+\t\t\tstrbuf_addchars(sb, ' ', indent);\n+\t\t\tif (pp->fmt == CMIT_FMT_EXPAND_TABS)\n+\t\t\t\tstrbuf_expand_add(sb, line, linelen);\n+\t\t\telse\n+\t\t\t\tstrbuf_add(sb, line, linelen);\n+\t\t} else {\n+\t\t\tstrbuf_add(sb, line, linelen);\n \t\t}\n-\t\tstrbuf_add(sb, line, linelen);\n \t\tstrbuf_addch(sb, '\\n');\n \t}\n }\n"},{"id":"280952","messageId":"xmqqoaae4340.fsf@gitster.mtv.corp.google.com","threadId":"41709","inReplyTo":"xmqqwpp243sb.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH] pretty-print: de-tabify indented logs to make things line up properly","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-16T19:47:11Z","receivedAt":"2016-03-16T19:47:11Z","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> The above is most likely what I would have written if I were doing\n> this patch.  I could squash it to save a round-trip, but let me run\n> the testsuite first to see if we need adjustments to existing tests.\n\nStrangely running t4201 with your patch (without any squashing)\nseems to show a breakage in shortlog.  I won't be able to come back\nto this topic for at least a few hours, so this is just a single bit\n\"breaks\" report, without \"how and why\" analysis, sorry.\n\n>\n> Also your idea:\n>\n>> But the code *could* be made to just always do the whole\n>> \"strbuf_add()\", and not return a return value at all, and the no-tab\n>> case wouldn't be explicitly written to be different.\n>\n> may give us a better structure if we are going to give users a knob\n> to disable this tab expansion, i.e. move the addition of 4 spaces to\n> the caller, name the body of such a function strbuf_expand_add(),\n> and then make the caller do something like this perhaps?\n>\n> @@ -1723,10 +1711,14 @@ void pp_remainder(struct pretty_print_context *pp,\n>  \n>  \t\tstrbuf_grow(sb, linelen + indent + 20);\n>  \t\tif (indent) {\n> -\t\t\tif (pp_handle_indent(sb, indent, line, linelen))\n> -\t\t\t\tlinelen = 0;\n> +\t\t\tstrbuf_addchars(sb, ' ', indent);\n> +\t\t\tif (pp->fmt == CMIT_FMT_EXPAND_TABS)\n> +\t\t\t\tstrbuf_expand_add(sb, line, linelen);\n> +\t\t\telse\n> +\t\t\t\tstrbuf_add(sb, line, linelen);\n> +\t\t} else {\n> +\t\t\tstrbuf_add(sb, line, linelen);\n>  \t\t}\n> -\t\tstrbuf_add(sb, line, linelen);\n>  \t\tstrbuf_addch(sb, '\\n');\n>  \t}\n>  }\n"},{"id":"280953","messageId":"CA+55aFxLyMaur8Kd_uyewEeehPeuZXu=Hn11SSbTYd9O6FdDBA@mail.gmail.com","threadId":"41709","inReplyTo":"xmqqwpp243sb.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH] pretty-print: de-tabify indented logs to make things line up properly","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2016-03-16T19:50:20Z","receivedAt":"2016-03-16T19:50:20Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"On Wed, Mar 16, 2016 at 12:32 PM, Junio C Hamano <gitster@pobox.com> wrote:\n>\n> may give us a better structure if we are going to give users a knob\n> to disable this tab expansion, i.e. move the addition of 4 spaces to\n> the caller, name the body of such a function strbuf_expand_add(),\n> and then make the caller do something like this perhaps?\n\nI'd suggest just putting that knob into the \"pp_handle_indent()\"\nfunction, and passing it the \"pp\" pointer.\n\nIn fact, maybe it should just be renamed as \"pp_add_line()\", and\nhandle every case, and keep \"pp_remainder()\" as just the \"loop over\neach line and handle the empty line and PP_SHORT special case\" thing.\n\nThat makes it easty to add that CMIT_FMT_EXPAND_TABS kind of code later.\n\nHere's an incremental patch that could be just smushed into my\nprevious one. It doesn't change the behavior of \"pp_handle_indent()\",\nbut I think it clarifies the code and makes future changes much easier\n(partly because now nobody has to worry about the continue case and\nthe newline at the end of the line, so you can just print whatever you\nwant and then return).\n\nWhat do you think?\n\n                 Linus\n\n\n pretty.c | 19 +++++++++++++------\n 1 file changed, 13 insertions(+), 6 deletions(-)\n\ndiff --git a/pretty.c b/pretty.c\nindex 0b40457f99f0..b9374a1708d1 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -1699,6 +1699,18 @@ static int pp_handle_indent(struct strbuf *sb, int indent,\n \treturn 1;\n }\n \n+static void pp_add_line(struct pretty_print_context *pp,\n+\t\t\tstruct strbuf *sb, int indent,\n+\t\t\tconst char *line, int linelen)\n+{\n+\tstrbuf_grow(sb, linelen + indent + 20);\n+\tif (indent) {\n+\t\tif (pp_handle_indent(sb, indent, line, linelen))\n+\t\t\treturn;\n+\t}\n+\tstrbuf_add(sb, line, linelen);\n+}\n+\n void pp_remainder(struct pretty_print_context *pp,\n \t\t  const char **msg_p,\n \t\t  struct strbuf *sb,\n@@ -1721,12 +1733,7 @@ void pp_remainder(struct pretty_print_context *pp,\n \t\t}\n \t\tfirst = 0;\n \n-\t\tstrbuf_grow(sb, linelen + indent + 20);\n-\t\tif (indent) {\n-\t\t\tif (pp_handle_indent(sb, indent, line, linelen))\n-\t\t\t\tlinelen = 0;\n-\t\t}\n-\t\tstrbuf_add(sb, line, linelen);\n+\t\tpp_add_line(pp, sb, indent, line, linelen);\n \t\tstrbuf_addch(sb, '\\n');\n \t}\n }\n"},{"id":"280955","messageId":"CA+55aFwbNXJnwEYrKE5dDRk_6eZeGT6Z11uSQS8RmCSq43PkdA@mail.gmail.com","threadId":"41709","inReplyTo":"xmqqoaae4340.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH] pretty-print: de-tabify indented logs to make things line up properly","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2016-03-16T19:59:34Z","receivedAt":"2016-03-16T19:59:34Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"On Wed, Mar 16, 2016 at 12:47 PM, Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Strangely running t4201 with your patch (without any squashing)\n> seems to show a breakage in shortlog.  I won't be able to come back\n> to this topic for at least a few hours, so this is just a single bit\n> \"breaks\" report, without \"how and why\" analysis, sorry.\n\nIt's because those things have tabs in their first line, so the output\nnow differs from the expected one exactly because of the tab-vs-space\nexpansion.\n\nThe wrapping logic is then also different, because the .wrapping code\ndoes the tabs as \"align to 8 chars\" while the new code does tabs as\n\"align to 8 chars modulo the indent offset\".\n\nI only looked at the first case, but I assume the others are just more\nof the same. We'd just adjust the expected output, I assume.\n\n               Linus\n"},{"id":"280973","messageId":"xmqqk2l23xzc.fsf@gitster.mtv.corp.google.com","threadId":"41709","inReplyTo":"CA+55aFwbNXJnwEYrKE5dDRk_6eZeGT6Z11uSQS8RmCSq43PkdA@mail.gmail.com","subject":"Re: [PATCH] pretty-print: de-tabify indented logs to make things line up properly","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-16T21:37:59Z","receivedAt":"2016-03-16T21:37:59Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@linux-foundation.org> writes:\n\n> On Wed, Mar 16, 2016 at 12:47 PM, Junio C Hamano <gitster@pobox.com> wrote:\n>>\n>> Strangely running t4201 with your patch (without any squashing)\n>> seems to show a breakage in shortlog.  I won't be able to come back\n>> to this topic for at least a few hours, so this is just a single bit\n>> \"breaks\" report, without \"how and why\" analysis, sorry.\n>\n> It's because those things have tabs in their first line, so the output\n> now differs from the expected one exactly because of the tab-vs-space\n> expansion.\n\nWhat surprised me was that this new expand logic triggered for\nshortlog, actually.  I somehow assumed the caller that called\nde-tabify helper was only called for --pretty=medium.\n"},{"id":"280978","messageId":"xmqq37rq3x5t.fsf@gitster.mtv.corp.google.com","threadId":"41709","inReplyTo":"CA+55aFxLyMaur8Kd_uyewEeehPeuZXu=Hn11SSbTYd9O6FdDBA@mail.gmail.com","subject":"Re: [PATCH] pretty-print: de-tabify indented logs to make things line up properly","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-16T21:55:42Z","receivedAt":"2016-03-16T21:55:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@linux-foundation.org> writes:\n\n> Here's an incremental patch that could be just smushed into my\n> previous one. It doesn't change the behavior of \"pp_handle_indent()\",\n> but I think it clarifies the code and makes future changes much easier\n> (partly because now nobody has to worry about the continue case and\n> the newline at the end of the line, so you can just print whatever you\n> want and then return).\n>\n> What do you think?\n\nI actually was hoping that strbuf_tabexpand_add() would be an\nindependently useful addition to strbuf_add*() family that does not\nhave to know the indentation and pretty-print-context, so burying\nthat new logic deep in the callchain like the patch below, while\nletting it still be aware of \"indent\" value (and adding the leading\nindent) does not look like a good abstraction from that point of\nview.\n\nThe change to pp_remainder() looks like a nice cleanup for people\nwho read that function.  I still think pp_add_line() should add the\nindentation to sb in \"if (indent)\" block itself, and the called\nhelper should be a \"I know how to tab-expand a string and add the\nresult to a strbuf\" that we can eventually move to strbuf.[ch].\n\nThings like adding CMIT_FMT_EXPAND_TABS can still then be done with\nsomething like this:\n\n\tstrbuf_grow();\n\tif (indent) {\n\t\tstrbuf_addchars(sb, ' ', indent);\n-        \tstrbuf_tabexpand_add();\n+\t\tif (pp->format == EXPAND_TABS)\n+\t        \tstrbuf_tabexpand_add();\n+\t\telse\n+\t        \tstrbuf_add();\n\t} else {\n        \tstrbuf_add();\n\t}\n\nin pp_add_line(), so there is no difference between the ease of\nfuture changes, I'd think.\n\n>                  Linus\n>\n>  pretty.c | 19 +++++++++++++------\n>  1 file changed, 13 insertions(+), 6 deletions(-)\n>\n> diff --git a/pretty.c b/pretty.c\n> index 0b40457f99f0..b9374a1708d1 100644\n> --- a/pretty.c\n> +++ b/pretty.c\n> @@ -1699,6 +1699,18 @@ static int pp_handle_indent(struct strbuf *sb, int indent,\n>  \treturn 1;\n>  }\n>  \n> +static void pp_add_line(struct pretty_print_context *pp,\n> +\t\t\tstruct strbuf *sb, int indent,\n> +\t\t\tconst char *line, int linelen)\n> +{\n> +\tstrbuf_grow(sb, linelen + indent + 20);\n> +\tif (indent) {\n> +\t\tif (pp_handle_indent(sb, indent, line, linelen))\n> +\t\t\treturn;\n> +\t}\n> +\tstrbuf_add(sb, line, linelen);\n> +}\n> +\n>  void pp_remainder(struct pretty_print_context *pp,\n>  \t\t  const char **msg_p,\n>  \t\t  struct strbuf *sb,\n> @@ -1721,12 +1733,7 @@ void pp_remainder(struct pretty_print_context *pp,\n>  \t\t}\n>  \t\tfirst = 0;\n>  \n> -\t\tstrbuf_grow(sb, linelen + indent + 20);\n> -\t\tif (indent) {\n> -\t\t\tif (pp_handle_indent(sb, indent, line, linelen))\n> -\t\t\t\tlinelen = 0;\n> -\t\t}\n> -\t\tstrbuf_add(sb, line, linelen);\n> +\t\tpp_add_line(pp, sb, indent, line, linelen);\n>  \t\tstrbuf_addch(sb, '\\n');\n>  \t}\n>  }\n"},{"id":"280979","messageId":"CA+55aFwbev52kTV1wNMTsxR3kWvhXxTkjVy-KQOEO_2jX3RrAQ@mail.gmail.com","threadId":"41709","inReplyTo":"xmqqk2l23xzc.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH] pretty-print: de-tabify indented logs to make things line up properly","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2016-03-16T22:04:45Z","receivedAt":"2016-03-16T22:04:45Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"On Wed, Mar 16, 2016 at 2:37 PM, Junio C Hamano <gitster@pobox.com> wrote:\n>\n> What surprised me was that this new expand logic triggered for\n> shortlog, actually.  I somehow assumed the caller that called\n> de-tabify helper was only called for --pretty=medium.\n\nI guess that would be ok, since shortlog by definition can't have any\nissues with multiple lines lining up with each other.\n\nAt the same time, it might be a bit odd to show tabs in that first\nline differently for the one-line vs multi-line log version. But maybe\nit isn't - I think shortlog is the only thing that does that wrapping\nanyway, so shortlog is already special.\n\nI think the reason shortlog output gets both the de-tab and the\nwrapping is that shortlog_add_commit() just calls pretty_print_commit\nwith CMIT_FMT_USERFORMAT.\n\n            Linus\n"},{"id":"281092","messageId":"xmqq37rozoic.fsf_-_@gitster.mtv.corp.google.com","threadId":"41709","inReplyTo":"CA+55aFwbev52kTV1wNMTsxR3kWvhXxTkjVy-KQOEO_2jX3RrAQ@mail.gmail.com","subject":"[PATCH v2 1/4] pretty-print: de-tabify indented logs to make things line up properly","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-17T23:13:47Z","receivedAt":"2016-03-17T23:13:47Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"From: Linus Torvalds <torvalds@linux-foundation.org>\nDate: Wed, 16 Mar 2016 09:15:53 -0700\n\nA commit log message sometimes tries to line things up using tabs,\nassuming fixed-width font with the standard 8-place tab settings.\nViewing such a commit however does not work well in \"git log\", as we\nindent the lines by prefixing 4 spaces in front of them.\n\nThis should all line up:\n\n  Column 1\tColumn 2\n  --------\t--------\n  A\t\tB\n  ABCD\t\tEFGH\n  SPACES        Instead of Tabs\n\nEven with multi-byte UTF8 characters:\n\n  Column 1\tColumn 2\n  --------\t--------\n  Ä\t\tB\n  åäö\t\t100\n  A Møøse\tonce bit my sister..\n\nTab-expand the lines in \"git log --pretty=medium\" output (which is\nthe default), before prefixing 4 spaces.\n\nThis breaks a few tests in t4201, that tests \"git shortlog\".\n\n - One passes \"git log\" output to \"git shortlog\" to use the latter\n   as a filter and does not expect the output of the former to be\n   de-tabified.\n\n - The other expects that \"git shortlog\", when it reads the first\n   line of the commit and produces the output itself, does not\n   de-tabify it.\n\nMark them as expecting failure for now.\n\nSigned-off-by: Linus Torvalds <torvalds@linux-foundation.org>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n pretty.c            | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++--\n t/t4201-shortlog.sh |  4 +--\n 2 files changed, 76 insertions(+), 4 deletions(-)\n\ndiff --git a/pretty.c b/pretty.c\nindex 92b2870..0b40457 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -1629,6 +1629,76 @@ void pp_title_line(struct pretty_print_context *pp,\n \tstrbuf_release(&title);\n }\n \n+static int pp_utf8_width(const char *start, const char *end)\n+{\n+\tint width = 0;\n+\tsize_t remain = end - start;\n+\n+\twhile (remain) {\n+\t\tint n = utf8_width(&start, &remain);\n+\t\tif (n < 0 || !start)\n+\t\t\treturn -1;\n+\t\twidth += n;\n+\t}\n+\treturn width;\n+}\n+\n+/*\n+ * pp_handle_indent() prints out the intendation, and\n+ * perhaps the whole line (without the final newline)\n+ *\n+ * Why \"perhaps\"? If there are tabs in the indented line\n+ * it will print it out in order to de-tabify the line.\n+ *\n+ * But if there are no tabs, we just fall back on the\n+ * normal \"print the whole line\".\n+ */\n+static int pp_handle_indent(struct strbuf *sb, int indent,\n+\t\t\t     const char *line, int linelen)\n+{\n+\tconst char *tab;\n+\n+\tstrbuf_addchars(sb, ' ', indent);\n+\n+\ttab = memchr(line, '\\t', linelen);\n+\tif (!tab)\n+\t\treturn 0;\n+\n+\tdo {\n+\t\tint width = pp_utf8_width(line, tab);\n+\n+\t\t/*\n+\t\t * If it wasn't well-formed utf8, or it\n+\t\t * had characters with badly defined\n+\t\t * width (control characters etc), just\n+\t\t * give up on trying to align things.\n+\t\t */\n+\t\tif (width < 0)\n+\t\t\tbreak;\n+\n+\t\t/* Output the data .. */\n+\t\tstrbuf_add(sb, line, tab - line);\n+\n+\t\t/* .. and the de-tabified tab */\n+\t\tstrbuf_addchars(sb, ' ', 8-(width & 7));\n+\n+\t\t/* Skip over the printed part .. */\n+\t\tlinelen -= 1+tab-line;\n+\t\tline = tab + 1;\n+\n+\t\t/* .. and look for the next tab */\n+\t\ttab = memchr(line, '\\t', linelen);\n+\t} while (tab);\n+\n+\t/*\n+\t * Print out everything after the last tab without\n+\t * worrying about width - there's nothing more to\n+\t * align.\n+\t */\n+\tstrbuf_add(sb, line, linelen);\n+\treturn 1;\n+}\n+\n void pp_remainder(struct pretty_print_context *pp,\n \t\t  const char **msg_p,\n \t\t  struct strbuf *sb,\n@@ -1652,8 +1722,10 @@ void pp_remainder(struct pretty_print_context *pp,\n \t\tfirst = 0;\n \n \t\tstrbuf_grow(sb, linelen + indent + 20);\n-\t\tif (indent)\n-\t\t\tstrbuf_addchars(sb, ' ', indent);\n+\t\tif (indent) {\n+\t\t\tif (pp_handle_indent(sb, indent, line, linelen))\n+\t\t\t\tlinelen = 0;\n+\t\t}\n \t\tstrbuf_add(sb, line, linelen);\n \t\tstrbuf_addch(sb, '\\n');\n \t}\ndiff --git a/t/t4201-shortlog.sh b/t/t4201-shortlog.sh\nindex 7600a3e..987b708 100755\n--- a/t/t4201-shortlog.sh\n+++ b/t/t4201-shortlog.sh\n@@ -93,7 +93,7 @@ test_expect_success 'output from user-defined format is re-wrapped' '\n \ttest_cmp expect log.predictable\n '\n \n-test_expect_success !MINGW 'shortlog wrapping' '\n+test_expect_failure !MINGW 'shortlog wrapping' '\n \tcat >expect <<\\EOF &&\n A U Thor (5):\n       Test\n@@ -114,7 +114,7 @@ EOF\n \ttest_cmp expect out\n '\n \n-test_expect_success !MINGW 'shortlog from non-git directory' '\n+test_expect_failure !MINGW 'shortlog from non-git directory' '\n \tgit log HEAD >log &&\n \tGIT_DIR=non-existing git shortlog -w <log >out &&\n \ttest_cmp expect out\n-- \n2.8.0-rc3-175-g64dcf62\n"},{"id":"281093","messageId":"xmqqwpp0y9v1.fsf_-_@gitster.mtv.corp.google.com","threadId":"41709","inReplyTo":"xmqq37rozoic.fsf_-_@gitster.mtv.corp.google.com","subject":"[PATCH v2 2/4] pretty-print: simplify the interaction between pp_handle_indent() and its caller","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-17T23:15:30Z","receivedAt":"2016-03-17T23:15:30Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Instead of\tsometimes handling the output itself and some other\ntimes forcing   the caller handle the output, make pp_handle_indent()\nresponsible to  handle the output for all cases.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n\n * This and the other two patches that follow show what I meant\n   during the discussion.\n\n pretty.c | 32 +++++++++-----------------------\n 1 file changed, 9 insertions(+), 23 deletions(-)\n\ndiff --git a/pretty.c b/pretty.c\nindex 0b40457..6d657fc 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -1645,26 +1645,17 @@ static int pp_utf8_width(const char *start, const char *end)\n \n /*\n  * pp_handle_indent() prints out the intendation, and\n- * perhaps the whole line (without the final newline)\n- *\n- * Why \"perhaps\"? If there are tabs in the indented line\n- * it will print it out in order to de-tabify the line.\n- *\n- * But if there are no tabs, we just fall back on the\n- * normal \"print the whole line\".\n+ * the whole line (without the final newline), after\n+ * de-tabifying.\n  */\n-static int pp_handle_indent(struct strbuf *sb, int indent,\n+static void pp_handle_indent(struct strbuf *sb, int indent,\n \t\t\t     const char *line, int linelen)\n {\n \tconst char *tab;\n \n \tstrbuf_addchars(sb, ' ', indent);\n \n-\ttab = memchr(line, '\\t', linelen);\n-\tif (!tab)\n-\t\treturn 0;\n-\n-\tdo {\n+\twhile ((tab = memchr(line, '\\t', linelen)) != NULL) {\n \t\tint width = pp_utf8_width(line, tab);\n \n \t\t/*\n@@ -1685,10 +1676,7 @@ static int pp_handle_indent(struct strbuf *sb, int indent,\n \t\t/* Skip over the printed part .. */\n \t\tlinelen -= 1+tab-line;\n \t\tline = tab + 1;\n-\n-\t\t/* .. and look for the next tab */\n-\t\ttab = memchr(line, '\\t', linelen);\n-\t} while (tab);\n+\t}\n \n \t/*\n \t * Print out everything after the last tab without\n@@ -1696,7 +1684,6 @@ static int pp_handle_indent(struct strbuf *sb, int indent,\n \t * align.\n \t */\n \tstrbuf_add(sb, line, linelen);\n-\treturn 1;\n }\n \n void pp_remainder(struct pretty_print_context *pp,\n@@ -1722,11 +1709,10 @@ void pp_remainder(struct pretty_print_context *pp,\n \t\tfirst = 0;\n \n \t\tstrbuf_grow(sb, linelen + indent + 20);\n-\t\tif (indent) {\n-\t\t\tif (pp_handle_indent(sb, indent, line, linelen))\n-\t\t\t\tlinelen = 0;\n-\t\t}\n-\t\tstrbuf_add(sb, line, linelen);\n+\t\tif (indent)\n+\t\t\tpp_handle_indent(sb, indent, line, linelen);\n+\t\telse\n+\t\t\tstrbuf_add(sb, line, linelen);\n \t\tstrbuf_addch(sb, '\\n');\n \t}\n }\n-- \n2.8.0-rc3-175-g64dcf62\n"},{"id":"281094","messageId":"xmqqshzoy9uh.fsf_-_@gitster.mtv.corp.google.com","threadId":"41709","inReplyTo":"xmqq37rozoic.fsf_-_@gitster.mtv.corp.google.com","subject":"[PATCH v2 3/4] pretty-print: further abstract out pp_handle_indent()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-17T23:15:50Z","receivedAt":"2016-03-17T23:15:50Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Separate the call to add 4-space indent, and a new helper to add a\nline after de-tabifying.\n\nThe new helper function strbuf_add_tabexpand() could later be moved\nto strbuf.[ch] if other callers need to.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n pretty.c | 24 +++++++++++++++---------\n 1 file changed, 15 insertions(+), 9 deletions(-)\n\ndiff --git a/pretty.c b/pretty.c\nindex 6d657fc..717ceed 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -1643,18 +1643,12 @@ static int pp_utf8_width(const char *start, const char *end)\n \treturn width;\n }\n \n-/*\n- * pp_handle_indent() prints out the intendation, and\n- * the whole line (without the final newline), after\n- * de-tabifying.\n- */\n-static void pp_handle_indent(struct strbuf *sb, int indent,\n-\t\t\t     const char *line, int linelen)\n+\n+static void strbuf_add_tabexpand(struct strbuf *sb,\n+\t\t\t\t const char *line, int linelen)\n {\n \tconst char *tab;\n \n-\tstrbuf_addchars(sb, ' ', indent);\n-\n \twhile ((tab = memchr(line, '\\t', linelen)) != NULL) {\n \t\tint width = pp_utf8_width(line, tab);\n \n@@ -1686,6 +1680,18 @@ static void pp_handle_indent(struct strbuf *sb, int indent,\n \tstrbuf_add(sb, line, linelen);\n }\n \n+/*\n+ * pp_handle_indent() prints out the intendation, and\n+ * the whole line (without the final newline), after\n+ * de-tabifying.\n+ */\n+static void pp_handle_indent(struct strbuf *sb, int indent,\n+\t\t\t     const char *line, int linelen)\n+{\n+\tstrbuf_addchars(sb, ' ', indent);\n+\tstrbuf_add_tabexpand(sb, line, linelen);\n+}\n+\n void pp_remainder(struct pretty_print_context *pp,\n \t\t  const char **msg_p,\n \t\t  struct strbuf *sb,\n-- \n2.8.0-rc3-175-g64dcf62\n"},{"id":"281095","messageId":"xmqqoaacy9tm.fsf_-_@gitster.mtv.corp.google.com","threadId":"41709","inReplyTo":"xmqq37rozoic.fsf_-_@gitster.mtv.corp.google.com","subject":"[PATCH 4/4] pretty-print: add --pretty=noexpand","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-17T23:16:21Z","receivedAt":"2016-03-17T23:16:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"It is reasonable for tweak the default output mode for \"git log\" to\nuntabify the commit log message, it sometimes may be necessary to\nsee the output without tab expansion.\n\nInvent a new --pretty option to do this.  Use this to unbreak the\ntest breakages, where \"git shortlog\" and output are tested.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n Documentation/pretty-formats.txt | 10 ++++++++++\n Documentation/pretty-options.txt |  2 +-\n commit.h                         |  1 +\n pretty.c                         | 12 +++++++++---\n t/t4201-shortlog.sh              |  6 +++---\n 5 files changed, 24 insertions(+), 7 deletions(-)\n\ndiff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt\nindex 671cebd..173b932 100644\n--- a/Documentation/pretty-formats.txt\n+++ b/Documentation/pretty-formats.txt\n@@ -39,6 +39,16 @@ This is designed to be as compact as possible.\n \n \t      <title line>\n \n+\t      <full commit message, tab-expanded>\n+\n+* 'noexpand'\n+\n+\t  commit <sha1>\n+\t  Author: <author>\n+\t  Date:   <author date>\n+\n+\t      <title line>\n+\n \t      <full commit message>\n \n * 'full'\ndiff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt\nindex 4b659ac..7032b1a 100644\n--- a/Documentation/pretty-options.txt\n+++ b/Documentation/pretty-options.txt\n@@ -3,7 +3,7 @@\n \n \tPretty-print the contents of the commit logs in a given format,\n \twhere '<format>' can be one of 'oneline', 'short', 'medium',\n-\t'full', 'fuller', 'email', 'raw', 'format:<string>'\n+\t'full', 'fuller', 'email', 'raw', 'noexpand', 'format:<string>'\n \tand 'tformat:<string>'.  When '<format>' is none of the above,\n \tand has '%placeholder' in it, it acts as if\n \t'--pretty=tformat:<format>' were given.\ndiff --git a/commit.h b/commit.h\nindex 5d58be0..d511c61 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -126,6 +126,7 @@ enum cmit_fmt {\n \tCMIT_FMT_RAW,\n \tCMIT_FMT_MEDIUM,\n \tCMIT_FMT_DEFAULT = CMIT_FMT_MEDIUM,\n+\tCMIT_FMT_NOEXPAND,\n \tCMIT_FMT_SHORT,\n \tCMIT_FMT_FULL,\n \tCMIT_FMT_FULLER,\ndiff --git a/pretty.c b/pretty.c\nindex 717ceed..8b533dc 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -89,6 +89,7 @@ static void setup_commit_formats(void)\n \tstruct cmt_fmt_map builtin_formats[] = {\n \t\t{ \"raw\",\tCMIT_FMT_RAW,\t\t0 },\n \t\t{ \"medium\",\tCMIT_FMT_MEDIUM,\t0 },\n+\t\t{ \"noexpand\",\tCMIT_FMT_NOEXPAND,\t0 },\n \t\t{ \"short\",\tCMIT_FMT_SHORT,\t\t0 },\n \t\t{ \"email\",\tCMIT_FMT_EMAIL,\t\t0 },\n \t\t{ \"fuller\",\tCMIT_FMT_FULLER,\t0 },\n@@ -1685,11 +1686,16 @@ static void strbuf_add_tabexpand(struct strbuf *sb,\n  * the whole line (without the final newline), after\n  * de-tabifying.\n  */\n-static void pp_handle_indent(struct strbuf *sb, int indent,\n+static void pp_handle_indent(struct pretty_print_context *pp,\n+\t\t\t     struct strbuf *sb,\n+\t\t\t     int indent,\n \t\t\t     const char *line, int linelen)\n {\n \tstrbuf_addchars(sb, ' ', indent);\n-\tstrbuf_add_tabexpand(sb, line, linelen);\n+\tif (pp->fmt == CMIT_FMT_MEDIUM)\n+\t\tstrbuf_add_tabexpand(sb, line, linelen);\n+\telse\n+\t\tstrbuf_add(sb, line, linelen);\n }\n \n void pp_remainder(struct pretty_print_context *pp,\n@@ -1716,7 +1722,7 @@ void pp_remainder(struct pretty_print_context *pp,\n \n \t\tstrbuf_grow(sb, linelen + indent + 20);\n \t\tif (indent)\n-\t\t\tpp_handle_indent(sb, indent, line, linelen);\n+\t\t\tpp_handle_indent(pp, sb, indent, line, linelen);\n \t\telse\n \t\t\tstrbuf_add(sb, line, linelen);\n \t\tstrbuf_addch(sb, '\\n');\ndiff --git a/t/t4201-shortlog.sh b/t/t4201-shortlog.sh\nindex 987b708..34a9fed 100755\n--- a/t/t4201-shortlog.sh\n+++ b/t/t4201-shortlog.sh\n@@ -93,7 +93,7 @@ test_expect_success 'output from user-defined format is re-wrapped' '\n \ttest_cmp expect log.predictable\n '\n \n-test_expect_failure !MINGW 'shortlog wrapping' '\n+test_expect_success !MINGW 'shortlog wrapping' '\n \tcat >expect <<\\EOF &&\n A U Thor (5):\n       Test\n@@ -114,8 +114,8 @@ EOF\n \ttest_cmp expect out\n '\n \n-test_expect_failure !MINGW 'shortlog from non-git directory' '\n-\tgit log HEAD >log &&\n+test_expect_success !MINGW 'shortlog from non-git directory' '\n+\tgit log --pretty=noexpand HEAD >log &&\n \tGIT_DIR=non-existing git shortlog -w <log >out &&\n \ttest_cmp expect out\n '\n-- \n2.8.0-rc3-175-g64dcf62\n"},{"id":"281096","messageId":"CA+55aFzeobjmhEmZzMYnvY-sit38S2j32gOXu5STLvbKfz-JAg@mail.gmail.com","threadId":"41709","inReplyTo":"xmqqoaacy9tm.fsf_-_@gitster.mtv.corp.google.com","subject":"Re: [PATCH 4/4] pretty-print: add --pretty=noexpand","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2016-03-17T23:23:08Z","receivedAt":"2016-03-17T23:23:08Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"On Thu, Mar 17, 2016 at 4:16 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> It is reasonable for tweak the default output mode for \"git log\" to\n> untabify the commit log message, it sometimes may be necessary to\n> see the output without tab expansion.\n\nThanks, these all look good to me.\n\nSorry for not following up, it's just that I'm in the middle of the\nkernel merge window and haven't had the time to worry about it.\n\n            Linus\n"},{"id":"281097","messageId":"xmqqk2l0y8q1.fsf@gitster.mtv.corp.google.com","threadId":"41709","inReplyTo":"CA+55aFzeobjmhEmZzMYnvY-sit38S2j32gOXu5STLvbKfz-JAg@mail.gmail.com","subject":"Re: [PATCH 4/4] pretty-print: add --pretty=noexpand","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-17T23:40:06Z","receivedAt":"2016-03-17T23:40:06Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@linux-foundation.org> writes:\n\n> On Thu, Mar 17, 2016 at 4:16 PM, Junio C Hamano <gitster@pobox.com> wrote:\n>> It is reasonable for tweak the default output mode for \"git log\" to\n>> untabify the commit log message, it sometimes may be necessary to\n>> see the output without tab expansion.\n>\n> Thanks, these all look good to me.\n>\n> Sorry for not following up, it's just that I'm in the middle of the\n> kernel merge window and haven't had the time to worry about it.\n\nSorry is mutual; I would have done this much earlier if I didn't\nhave the four-maintenance-tracks-at-the-same-time release today ;-)\n"},{"id":"281114","messageId":"20160318050807.GC22327@sigill.intra.peff.net","threadId":"41709","inReplyTo":"xmqqoaacy9tm.fsf_-_@gitster.mtv.corp.google.com","subject":"Re: [PATCH 4/4] pretty-print: add --pretty=noexpand","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2016-03-18T05:08:07Z","receivedAt":"2016-03-18T05:08:07Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Mar 17, 2016 at 04:16:21PM -0700, Junio C Hamano wrote:\n\n> It is reasonable for tweak the default output mode for \"git log\" to\n> untabify the commit log message, it sometimes may be necessary to\n> see the output without tab expansion.\n> \n> Invent a new --pretty option to do this.  Use this to unbreak the\n> test breakages, where \"git shortlog\" and output are tested.\n\nHmm. Isn't \"expand tabs\" orthogonal to the rest of the pretty format?\nThat is, couldn't one want \"--pretty=fuller, but with tabs expanded\"?\n\nI don't personally care much myself, and certainly we don't need to\nsupport \"--expand-tabs\" for every format until somebody actually wants\nthem enough to implement it. I just don't want to see us painted into a\ncorner where we have to support an awkward interface forever (e.g., the\nway we had to retrofit the orthogonal \"local\" concept onto the --date\ncode).\n\nE.g., start with:\n\n  - only CMIT_FMT_MEDIUM expands tabs (and does so by default)\n\n  - passing --no-expand-tabs suppresses this behavior\n\n  - passing --expand-tabs is an error for now; if people care later,\n    they can add support for other formats (naively this is trivial, but\n    I suspect there are some corner cases around things like\n    --pretty=raw, so unless somebody wants to work on it now, I don't\n    think we need to).\n\n-Peff\n"},{"id":"281118","messageId":"CA+55aFw=obdDSTS98GQi6ER3RgAxD61xDmXYVeEX=a3GKM6SOg@mail.gmail.com","threadId":"41709","inReplyTo":"20160318050807.GC22327@sigill.intra.peff.net","subject":"Re: [PATCH 4/4] pretty-print: add --pretty=noexpand","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2016-03-18T05:36:16Z","receivedAt":"2016-03-18T05:36:16Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"On Thu, Mar 17, 2016 at 10:08 PM, Jeff King <peff@peff.net> wrote:\n>\n> Hmm. Isn't \"expand tabs\" orthogonal to the rest of the pretty format?\n> That is, couldn't one want \"--pretty=fuller, but with tabs expanded\"?\n\nYeah, you are right, one easily could. And in fact I end up doing\n\"fuller\" myself occasionally, because I check peoples commit\ntimestamps (some people have a nasty habit of rebasing when they\nshouldn't).\n\nSo it's not just the medium format that would want detab by default,\nit's \"full\" and \"fuller\" too (but probably not \"raw\": that indents the\nmessage too, but the only real reason to use \"raw\" is for scripting).\n\nSo it would probably be better to make it a separate flag, and not tie\nit to a particular log format (and just make the log format set the\ndefault).\n\n               Linus\n"},{"id":"281121","messageId":"xmqq7fh0s5l7.fsf@gitster.mtv.corp.google.com","threadId":"41709","inReplyTo":"20160318050807.GC22327@sigill.intra.peff.net","subject":"Re: [PATCH 4/4] pretty-print: add --pretty=noexpand","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-18T05:44:20Z","receivedAt":"2016-03-18T05:44:20Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> E.g., start with:\n>\n>   - only CMIT_FMT_MEDIUM expands tabs (and does so by default)\n>\n>   - passing --no-expand-tabs suppresses this behavior\n>\n>   - passing --expand-tabs is an error for now; if people care later,\n>     they can add support for other formats (naively this is trivial, but\n>     I suspect there are some corner cases around things like\n>     --pretty=raw, so unless somebody wants to work on it now, I don't\n>     think we need to).\n\nYup, I like that better, but it is now past my work hours, so I\nwon't be looking at it right now.\n"},{"id":"281126","messageId":"20160318055500.GA27875@sigill.intra.peff.net","threadId":"41709","inReplyTo":"CA+55aFw=obdDSTS98GQi6ER3RgAxD61xDmXYVeEX=a3GKM6SOg@mail.gmail.com","subject":"Re: [PATCH 4/4] pretty-print: add --pretty=noexpand","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2016-03-18T05:55:00Z","receivedAt":"2016-03-18T05:55:00Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Mar 17, 2016 at 10:36:16PM -0700, Linus Torvalds wrote:\n\n> On Thu, Mar 17, 2016 at 10:08 PM, Jeff King <peff@peff.net> wrote:\n> >\n> > Hmm. Isn't \"expand tabs\" orthogonal to the rest of the pretty format?\n> > That is, couldn't one want \"--pretty=fuller, but with tabs expanded\"?\n> \n> Yeah, you are right, one easily could. And in fact I end up doing\n> \"fuller\" myself occasionally, because I check peoples commit\n> timestamps (some people have a nasty habit of rebasing when they\n> shouldn't).\n> \n> So it's not just the medium format that would want detab by default,\n> it's \"full\" and \"fuller\" too (but probably not \"raw\": that indents the\n> message too, but the only real reason to use \"raw\" is for scripting).\n> \n> So it would probably be better to make it a separate flag, and not tie\n> it to a particular log format (and just make the log format set the\n> default).\n\nYeah, I agree with all of that. I didn't want to force anybody to have\nto think too hard about corner cases they don't care about (again, as\nlong as we don't paint ourselves into a corner) but I tend to think that\nit makes sense to apply it consistently to all of the stock\nhuman-readable formats (short, medium, full, fuller), but not to \"raw\"\nor \"email\", and probably not to user-formats.\n\n-Peff\n"},{"id":"281618","messageId":"1458775426-2215-1-git-send-email-gitster@pobox.com","threadId":"41709","inReplyTo":"xmqq7fh0s5l7.fsf@gitster.mtv.corp.google.com","subject":"[PATCH v3 0/5] Expanding tabs in \"git log\" output","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-23T23:23:41Z","receivedAt":"2016-03-23T23:23:41Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"So here is the third try (previous round is found at $gmane/289166\nand the very first one is at $gmane/288987).\n\nThe first three patches are essentially the same as v2.  The last\ntwo updates how the tab-expansion is internally controlled:\n\n [4/5] adds a bit to pretty-commit-context that tells if tabs should\n       be expanded.  Unlike v2 that tied this to pretty print format,\n       this bit is orthogonal to the format, and theoretically it is\n       possible to expand tabs even with --format=email.  Also,\n       unlike v2, tabs are expanded not just in `medium` format, but\n       also in `full` and `fuller` formats.\n\n [5/5] adds a new option --no-expand-tabs that controls the bit 4/5\n       introduces, so that \"git log [--pretty] --no-expand-tabs\"\n       would show the log message indented by 4 spaces, without tab\n       expansion.\n\nBy the way, I have to say that I hate how pretty formatting and\nrevision machinery interact with each other.\n\npretty.c::commit_formats ought to be the authoritative source of how\neach named format should work, but there are quite a many codepaths\nthat just assign CMIT_FMT_SOMETHING to revs->commit_format without\nbothering with other fields in the cmt_fmt_map like is_tformat, and\nI am not sure if they are working correctly even before this patch.\n\nJunio C Hamano (4):\n  pretty-print: simplify the interaction between pp_handle_indent() and its caller\n  pretty-print: further abstract out pp_handle_indent()\n  pretty-print: limit expand-tabs to selected --pretty formats\n  pretty-print: teach \"--no-expand-tabs\" option to \"git log\"\n\nLinus Torvalds (1):\n  pretty-print: de-tabify indented logs to make things line up properly\n\n Documentation/pretty-options.txt |  6 +++\n commit.h                         |  1 +\n log-tree.c                       |  1 +\n pretty.c                         | 88 ++++++++++++++++++++++++++++++++++++----\n revision.c                       |  3 ++\n revision.h                       |  1 +\n t/t4201-shortlog.sh              |  2 +-\n 7 files changed, 92 insertions(+), 10 deletions(-)\n\n[References]\n\nhttp://thread.gmane.org/gmane.comp.version-control.git/288987/focus=289166\n\n\nInterdiff since v2 is shown below.\n\ndiff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt\nindex 173b932..671cebd 100644\n--- a/Documentation/pretty-formats.txt\n+++ b/Documentation/pretty-formats.txt\n@@ -39,16 +39,6 @@ This is designed to be as compact as possible.\n \n \t      <title line>\n \n-\t      <full commit message, tab-expanded>\n-\n-* 'noexpand'\n-\n-\t  commit <sha1>\n-\t  Author: <author>\n-\t  Date:   <author date>\n-\n-\t      <title line>\n-\n \t      <full commit message>\n \n * 'full'\ndiff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt\nindex 7032b1a..069b927 100644\n--- a/Documentation/pretty-options.txt\n+++ b/Documentation/pretty-options.txt\n@@ -3,7 +3,7 @@\n \n \tPretty-print the contents of the commit logs in a given format,\n \twhere '<format>' can be one of 'oneline', 'short', 'medium',\n-\t'full', 'fuller', 'email', 'raw', 'noexpand', 'format:<string>'\n+\t'full', 'fuller', 'email', 'raw', 'format:<string>'\n \tand 'tformat:<string>'.  When '<format>' is none of the above,\n \tand has '%placeholder' in it, it acts as if\n \t'--pretty=tformat:<format>' were given.\n@@ -42,6 +42,12 @@ people using 80-column terminals.\n \tverbatim; this means that invalid sequences in the original\n \tcommit may be copied to the output.\n \n+--no-expand-tabs::\n+\tThe formats that indent the log message by 4 spaces\n+\t(i.e. 'medium', 'full', and 'fuller') by default show tabs\n+\tin the log message expanded.  This option disables the\n+\texpansion.\n+\n ifndef::git-rev-list[]\n --notes[=<ref>]::\n \tShow the notes (see linkgit:git-notes[1]) that annotate the\ndiff --git a/commit.h b/commit.h\nindex d511c61..a7ef682 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -126,7 +126,6 @@ enum cmit_fmt {\n \tCMIT_FMT_RAW,\n \tCMIT_FMT_MEDIUM,\n \tCMIT_FMT_DEFAULT = CMIT_FMT_MEDIUM,\n-\tCMIT_FMT_NOEXPAND,\n \tCMIT_FMT_SHORT,\n \tCMIT_FMT_FULL,\n \tCMIT_FMT_FULLER,\n@@ -148,6 +147,7 @@ struct pretty_print_context {\n \tint preserve_subject;\n \tstruct date_mode date_mode;\n \tunsigned date_mode_explicit:1;\n+\tunsigned expand_tabs_in_log:1;\n \tint need_8bit_cte;\n \tchar *notes_message;\n \tstruct reflog_walk_info *reflog_info;\ndiff --git a/log-tree.c b/log-tree.c\nindex 60f9839..78a5381 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -683,6 +683,7 @@ void show_log(struct rev_info *opt)\n \tctx.fmt = opt->commit_format;\n \tctx.mailmap = opt->mailmap;\n \tctx.color = opt->diffopt.use_color;\n+\tctx.expand_tabs_in_log = opt->expand_tabs_in_log;\n \tctx.output_encoding = get_log_output_encoding();\n \tif (opt->from_ident.mail_begin && opt->from_ident.name_begin)\n \t\tctx.from_ident = &opt->from_ident;\ndiff --git a/pretty.c b/pretty.c\nindex 8b533dc..5a33b7e 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -16,6 +16,7 @@ static struct cmt_fmt_map {\n \tconst char *name;\n \tenum cmit_fmt format;\n \tint is_tformat;\n+\tint expand_tabs_in_log;\n \tint is_alias;\n \tconst char *user_format;\n } *commit_formats;\n@@ -87,14 +88,13 @@ static int git_pretty_formats_config(const char *var, const char *value, void *c\n static void setup_commit_formats(void)\n {\n \tstruct cmt_fmt_map builtin_formats[] = {\n-\t\t{ \"raw\",\tCMIT_FMT_RAW,\t\t0 },\n-\t\t{ \"medium\",\tCMIT_FMT_MEDIUM,\t0 },\n-\t\t{ \"noexpand\",\tCMIT_FMT_NOEXPAND,\t0 },\n-\t\t{ \"short\",\tCMIT_FMT_SHORT,\t\t0 },\n-\t\t{ \"email\",\tCMIT_FMT_EMAIL,\t\t0 },\n-\t\t{ \"fuller\",\tCMIT_FMT_FULLER,\t0 },\n-\t\t{ \"full\",\tCMIT_FMT_FULL,\t\t0 },\n-\t\t{ \"oneline\",\tCMIT_FMT_ONELINE,\t1 }\n+\t\t{ \"raw\",\tCMIT_FMT_RAW,\t\t0,\t0 },\n+\t\t{ \"medium\",\tCMIT_FMT_MEDIUM,\t0,\t1 },\n+\t\t{ \"short\",\tCMIT_FMT_SHORT,\t\t0,\t0 },\n+\t\t{ \"email\",\tCMIT_FMT_EMAIL,\t\t0,\t0 },\n+\t\t{ \"fuller\",\tCMIT_FMT_FULLER,\t0,\t1 },\n+\t\t{ \"full\",\tCMIT_FMT_FULL,\t\t0,\t1 },\n+\t\t{ \"oneline\",\tCMIT_FMT_ONELINE,\t1,\t0 }\n \t};\n \tcommit_formats_len = ARRAY_SIZE(builtin_formats);\n \tbuiltin_formats_len = commit_formats_len;\n@@ -173,6 +173,7 @@ void get_commit_format(const char *arg, struct rev_info *rev)\n \n \trev->commit_format = commit_format->format;\n \trev->use_terminator = commit_format->is_tformat;\n+\trev->expand_tabs_in_log = commit_format->expand_tabs_in_log;\n \tif (commit_format->format == CMIT_FMT_USERFORMAT) {\n \t\tsave_user_format(rev, commit_format->user_format,\n \t\t\t\t commit_format->is_tformat);\n@@ -1687,12 +1688,11 @@ static void strbuf_add_tabexpand(struct strbuf *sb,\n  * de-tabifying.\n  */\n static void pp_handle_indent(struct pretty_print_context *pp,\n-\t\t\t     struct strbuf *sb,\n-\t\t\t     int indent,\n+\t\t\t     struct strbuf *sb, int indent,\n \t\t\t     const char *line, int linelen)\n {\n \tstrbuf_addchars(sb, ' ', indent);\n-\tif (pp->fmt == CMIT_FMT_MEDIUM)\n+\tif (pp->expand_tabs_in_log)\n \t\tstrbuf_add_tabexpand(sb, line, linelen);\n \telse\n \t\tstrbuf_add(sb, line, linelen);\ndiff --git a/revision.c b/revision.c\nindex df56fce..b0d2a36 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1412,6 +1412,7 @@ void init_revisions(struct rev_info *revs, const char *prefix)\n \trevs->skip_count = -1;\n \trevs->max_count = -1;\n \trevs->max_parents = -1;\n+\trevs->expand_tabs_in_log = 1;\n \n \trevs->commit_format = CMIT_FMT_DEFAULT;\n \n@@ -1915,6 +1916,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\trevs->verbose_header = 1;\n \t\trevs->pretty_given = 1;\n \t\tget_commit_format(arg+9, revs);\n+\t} else if (!strcmp(arg, \"--no-expand-tabs\")) {\n+\t\trevs->expand_tabs_in_log = 0;\n \t} else if (!strcmp(arg, \"--show-notes\") || !strcmp(arg, \"--notes\")) {\n \t\trevs->show_notes = 1;\n \t\trevs->show_notes_given = 1;\ndiff --git a/revision.h b/revision.h\nindex 23857c0..0bbfe0e 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -137,6 +137,7 @@ struct rev_info {\n \t\t\tabbrev_commit_given:1,\n \t\t\tzero_commit:1,\n \t\t\tuse_terminator:1,\n+\t\t\texpand_tabs_in_log:1,\n \t\t\tmissing_newline:1,\n \t\t\tdate_mode_explicit:1,\n \t\t\tpreserve_subject:1;\ndiff --git a/t/t4201-shortlog.sh b/t/t4201-shortlog.sh\nindex 34a9fed..2fec948 100755\n--- a/t/t4201-shortlog.sh\n+++ b/t/t4201-shortlog.sh\n@@ -115,7 +115,7 @@ EOF\n '\n \n test_expect_success !MINGW 'shortlog from non-git directory' '\n-\tgit log --pretty=noexpand HEAD >log &&\n+\tgit log --no-expand-tabs HEAD >log &&\n \tGIT_DIR=non-existing git shortlog -w <log >out &&\n \ttest_cmp expect out\n '\n"},{"id":"281619","messageId":"1458775426-2215-2-git-send-email-gitster@pobox.com","threadId":"41709","inReplyTo":"1458775426-2215-1-git-send-email-gitster@pobox.com","subject":"[PATCH v3 1/5] pretty-print: de-tabify indented logs to make things line up properly","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-23T23:23:42Z","receivedAt":"2016-03-23T23:23:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"From: Linus Torvalds <torvalds@linux-foundation.org>\n\nA commit log message sometimes tries to line things up using tabs,\nassuming fixed-width font with the standard 8-place tab settings.\nViewing such a commit however does not work well in \"git log\", as we\nindent the lines by prefixing 4 spaces in front of them.\n\nThis should all line up:\n\n  Column 1\tColumn 2\n  --------\t--------\n  A\t\tB\n  ABCD\t\tEFGH\n  SPACES        Instead of Tabs\n\nEven with multi-byte UTF8 characters:\n\n  Column 1\tColumn 2\n  --------\t--------\n  Ä\t\tB\n  åäö\t\t100\n  A Møøse\tonce bit my sister..\n\nTab-expand the lines in \"git log --pretty=medium\" output (which is\nthe default), before prefixing 4 spaces.\n\nThis breaks a few tests in t4201, that tests \"git shortlog\".\n\n - One passes \"git log\" output to \"git shortlog\" to use the latter\n   as a filter and does not expect the output of the former to be\n   de-tabified.\n\n - The other expects that \"git shortlog\", when it reads the first\n   line of the commit and produces the output itself, does not\n   de-tabify it.\n\nMark them as expecting failure for now.\n\nSigned-off-by: Linus Torvalds <torvalds@linux-foundation.org>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n pretty.c            | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++--\n t/t4201-shortlog.sh |  4 +--\n 2 files changed, 76 insertions(+), 4 deletions(-)\n\ndiff --git a/pretty.c b/pretty.c\nindex 92b2870..0b40457 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -1629,6 +1629,76 @@ void pp_title_line(struct pretty_print_context *pp,\n \tstrbuf_release(&title);\n }\n \n+static int pp_utf8_width(const char *start, const char *end)\n+{\n+\tint width = 0;\n+\tsize_t remain = end - start;\n+\n+\twhile (remain) {\n+\t\tint n = utf8_width(&start, &remain);\n+\t\tif (n < 0 || !start)\n+\t\t\treturn -1;\n+\t\twidth += n;\n+\t}\n+\treturn width;\n+}\n+\n+/*\n+ * pp_handle_indent() prints out the intendation, and\n+ * perhaps the whole line (without the final newline)\n+ *\n+ * Why \"perhaps\"? If there are tabs in the indented line\n+ * it will print it out in order to de-tabify the line.\n+ *\n+ * But if there are no tabs, we just fall back on the\n+ * normal \"print the whole line\".\n+ */\n+static int pp_handle_indent(struct strbuf *sb, int indent,\n+\t\t\t     const char *line, int linelen)\n+{\n+\tconst char *tab;\n+\n+\tstrbuf_addchars(sb, ' ', indent);\n+\n+\ttab = memchr(line, '\\t', linelen);\n+\tif (!tab)\n+\t\treturn 0;\n+\n+\tdo {\n+\t\tint width = pp_utf8_width(line, tab);\n+\n+\t\t/*\n+\t\t * If it wasn't well-formed utf8, or it\n+\t\t * had characters with badly defined\n+\t\t * width (control characters etc), just\n+\t\t * give up on trying to align things.\n+\t\t */\n+\t\tif (width < 0)\n+\t\t\tbreak;\n+\n+\t\t/* Output the data .. */\n+\t\tstrbuf_add(sb, line, tab - line);\n+\n+\t\t/* .. and the de-tabified tab */\n+\t\tstrbuf_addchars(sb, ' ', 8-(width & 7));\n+\n+\t\t/* Skip over the printed part .. */\n+\t\tlinelen -= 1+tab-line;\n+\t\tline = tab + 1;\n+\n+\t\t/* .. and look for the next tab */\n+\t\ttab = memchr(line, '\\t', linelen);\n+\t} while (tab);\n+\n+\t/*\n+\t * Print out everything after the last tab without\n+\t * worrying about width - there's nothing more to\n+\t * align.\n+\t */\n+\tstrbuf_add(sb, line, linelen);\n+\treturn 1;\n+}\n+\n void pp_remainder(struct pretty_print_context *pp,\n \t\t  const char **msg_p,\n \t\t  struct strbuf *sb,\n@@ -1652,8 +1722,10 @@ void pp_remainder(struct pretty_print_context *pp,\n \t\tfirst = 0;\n \n \t\tstrbuf_grow(sb, linelen + indent + 20);\n-\t\tif (indent)\n-\t\t\tstrbuf_addchars(sb, ' ', indent);\n+\t\tif (indent) {\n+\t\t\tif (pp_handle_indent(sb, indent, line, linelen))\n+\t\t\t\tlinelen = 0;\n+\t\t}\n \t\tstrbuf_add(sb, line, linelen);\n \t\tstrbuf_addch(sb, '\\n');\n \t}\ndiff --git a/t/t4201-shortlog.sh b/t/t4201-shortlog.sh\nindex 7600a3e..987b708 100755\n--- a/t/t4201-shortlog.sh\n+++ b/t/t4201-shortlog.sh\n@@ -93,7 +93,7 @@ test_expect_success 'output from user-defined format is re-wrapped' '\n \ttest_cmp expect log.predictable\n '\n \n-test_expect_success !MINGW 'shortlog wrapping' '\n+test_expect_failure !MINGW 'shortlog wrapping' '\n \tcat >expect <<\\EOF &&\n A U Thor (5):\n       Test\n@@ -114,7 +114,7 @@ EOF\n \ttest_cmp expect out\n '\n \n-test_expect_success !MINGW 'shortlog from non-git directory' '\n+test_expect_failure !MINGW 'shortlog from non-git directory' '\n \tgit log HEAD >log &&\n \tGIT_DIR=non-existing git shortlog -w <log >out &&\n \ttest_cmp expect out\n-- \n2.8.0-rc4-198-g3f6b64c\n"},{"id":"281623","messageId":"1458775426-2215-3-git-send-email-gitster@pobox.com","threadId":"41709","inReplyTo":"1458775426-2215-1-git-send-email-gitster@pobox.com","subject":"[PATCH v3 2/5] pretty-print: simplify the interaction between pp_handle_indent() and its caller","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-23T23:23:43Z","receivedAt":"2016-03-23T23:23:43Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Instead\tof sometimes handling the output itself and some other times\nforcing the caller handle the output, make the helper function\npp_handle_indent() responsible for the output for all cases.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n pretty.c | 32 +++++++++-----------------------\n 1 file changed, 9 insertions(+), 23 deletions(-)\n\ndiff --git a/pretty.c b/pretty.c\nindex 0b40457..6d657fc 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -1645,26 +1645,17 @@ static int pp_utf8_width(const char *start, const char *end)\n \n /*\n  * pp_handle_indent() prints out the intendation, and\n- * perhaps the whole line (without the final newline)\n- *\n- * Why \"perhaps\"? If there are tabs in the indented line\n- * it will print it out in order to de-tabify the line.\n- *\n- * But if there are no tabs, we just fall back on the\n- * normal \"print the whole line\".\n+ * the whole line (without the final newline), after\n+ * de-tabifying.\n  */\n-static int pp_handle_indent(struct strbuf *sb, int indent,\n+static void pp_handle_indent(struct strbuf *sb, int indent,\n \t\t\t     const char *line, int linelen)\n {\n \tconst char *tab;\n \n \tstrbuf_addchars(sb, ' ', indent);\n \n-\ttab = memchr(line, '\\t', linelen);\n-\tif (!tab)\n-\t\treturn 0;\n-\n-\tdo {\n+\twhile ((tab = memchr(line, '\\t', linelen)) != NULL) {\n \t\tint width = pp_utf8_width(line, tab);\n \n \t\t/*\n@@ -1685,10 +1676,7 @@ static int pp_handle_indent(struct strbuf *sb, int indent,\n \t\t/* Skip over the printed part .. */\n \t\tlinelen -= 1+tab-line;\n \t\tline = tab + 1;\n-\n-\t\t/* .. and look for the next tab */\n-\t\ttab = memchr(line, '\\t', linelen);\n-\t} while (tab);\n+\t}\n \n \t/*\n \t * Print out everything after the last tab without\n@@ -1696,7 +1684,6 @@ static int pp_handle_indent(struct strbuf *sb, int indent,\n \t * align.\n \t */\n \tstrbuf_add(sb, line, linelen);\n-\treturn 1;\n }\n \n void pp_remainder(struct pretty_print_context *pp,\n@@ -1722,11 +1709,10 @@ void pp_remainder(struct pretty_print_context *pp,\n \t\tfirst = 0;\n \n \t\tstrbuf_grow(sb, linelen + indent + 20);\n-\t\tif (indent) {\n-\t\t\tif (pp_handle_indent(sb, indent, line, linelen))\n-\t\t\t\tlinelen = 0;\n-\t\t}\n-\t\tstrbuf_add(sb, line, linelen);\n+\t\tif (indent)\n+\t\t\tpp_handle_indent(sb, indent, line, linelen);\n+\t\telse\n+\t\t\tstrbuf_add(sb, line, linelen);\n \t\tstrbuf_addch(sb, '\\n');\n \t}\n }\n-- \n2.8.0-rc4-198-g3f6b64c\n"},{"id":"281621","messageId":"1458775426-2215-4-git-send-email-gitster@pobox.com","threadId":"41709","inReplyTo":"1458775426-2215-1-git-send-email-gitster@pobox.com","subject":"[PATCH v3 3/5] pretty-print: further abstract out pp_handle_indent()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-23T23:23:44Z","receivedAt":"2016-03-23T23:23:44Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Separate the call to add 4-space indent, and a new helper to add a\nline after de-tabifying.\n\nThe new helper function strbuf_add_tabexpand() could later be moved\nto strbuf.[ch] if other callers need to.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n pretty.c | 24 +++++++++++++++---------\n 1 file changed, 15 insertions(+), 9 deletions(-)\n\ndiff --git a/pretty.c b/pretty.c\nindex 6d657fc..717ceed 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -1643,18 +1643,12 @@ static int pp_utf8_width(const char *start, const char *end)\n \treturn width;\n }\n \n-/*\n- * pp_handle_indent() prints out the intendation, and\n- * the whole line (without the final newline), after\n- * de-tabifying.\n- */\n-static void pp_handle_indent(struct strbuf *sb, int indent,\n-\t\t\t     const char *line, int linelen)\n+\n+static void strbuf_add_tabexpand(struct strbuf *sb,\n+\t\t\t\t const char *line, int linelen)\n {\n \tconst char *tab;\n \n-\tstrbuf_addchars(sb, ' ', indent);\n-\n \twhile ((tab = memchr(line, '\\t', linelen)) != NULL) {\n \t\tint width = pp_utf8_width(line, tab);\n \n@@ -1686,6 +1680,18 @@ static void pp_handle_indent(struct strbuf *sb, int indent,\n \tstrbuf_add(sb, line, linelen);\n }\n \n+/*\n+ * pp_handle_indent() prints out the intendation, and\n+ * the whole line (without the final newline), after\n+ * de-tabifying.\n+ */\n+static void pp_handle_indent(struct strbuf *sb, int indent,\n+\t\t\t     const char *line, int linelen)\n+{\n+\tstrbuf_addchars(sb, ' ', indent);\n+\tstrbuf_add_tabexpand(sb, line, linelen);\n+}\n+\n void pp_remainder(struct pretty_print_context *pp,\n \t\t  const char **msg_p,\n \t\t  struct strbuf *sb,\n-- \n2.8.0-rc4-198-g3f6b64c\n"},{"id":"281620","messageId":"1458775426-2215-5-git-send-email-gitster@pobox.com","threadId":"41709","inReplyTo":"1458775426-2215-1-git-send-email-gitster@pobox.com","subject":"[PATCH v3 4/5] pretty-print: limit expand-tabs to selected --pretty formats","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-23T23:23:45Z","receivedAt":"2016-03-23T23:23:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Make sure that \"git log\" (by default, it uses --pretty=medium)\nand \"git log --pretty={full,fuller}\" are the only ones that trigger\nthe new \"expand tabs in the log message\" behaviour.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n commit.h            |  1 +\n log-tree.c          |  1 +\n pretty.c            | 26 ++++++++++++++++----------\n revision.c          |  1 +\n revision.h          |  1 +\n t/t4201-shortlog.sh |  2 +-\n 6 files changed, 21 insertions(+), 11 deletions(-)\n\ndiff --git a/commit.h b/commit.h\nindex 5d58be0..a7ef682 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -147,6 +147,7 @@ struct pretty_print_context {\n \tint preserve_subject;\n \tstruct date_mode date_mode;\n \tunsigned date_mode_explicit:1;\n+\tunsigned expand_tabs_in_log:1;\n \tint need_8bit_cte;\n \tchar *notes_message;\n \tstruct reflog_walk_info *reflog_info;\ndiff --git a/log-tree.c b/log-tree.c\nindex 60f9839..78a5381 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -683,6 +683,7 @@ void show_log(struct rev_info *opt)\n \tctx.fmt = opt->commit_format;\n \tctx.mailmap = opt->mailmap;\n \tctx.color = opt->diffopt.use_color;\n+\tctx.expand_tabs_in_log = opt->expand_tabs_in_log;\n \tctx.output_encoding = get_log_output_encoding();\n \tif (opt->from_ident.mail_begin && opt->from_ident.name_begin)\n \t\tctx.from_ident = &opt->from_ident;\ndiff --git a/pretty.c b/pretty.c\nindex 717ceed..5a33b7e 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -16,6 +16,7 @@ static struct cmt_fmt_map {\n \tconst char *name;\n \tenum cmit_fmt format;\n \tint is_tformat;\n+\tint expand_tabs_in_log;\n \tint is_alias;\n \tconst char *user_format;\n } *commit_formats;\n@@ -87,13 +88,13 @@ static int git_pretty_formats_config(const char *var, const char *value, void *c\n static void setup_commit_formats(void)\n {\n \tstruct cmt_fmt_map builtin_formats[] = {\n-\t\t{ \"raw\",\tCMIT_FMT_RAW,\t\t0 },\n-\t\t{ \"medium\",\tCMIT_FMT_MEDIUM,\t0 },\n-\t\t{ \"short\",\tCMIT_FMT_SHORT,\t\t0 },\n-\t\t{ \"email\",\tCMIT_FMT_EMAIL,\t\t0 },\n-\t\t{ \"fuller\",\tCMIT_FMT_FULLER,\t0 },\n-\t\t{ \"full\",\tCMIT_FMT_FULL,\t\t0 },\n-\t\t{ \"oneline\",\tCMIT_FMT_ONELINE,\t1 }\n+\t\t{ \"raw\",\tCMIT_FMT_RAW,\t\t0,\t0 },\n+\t\t{ \"medium\",\tCMIT_FMT_MEDIUM,\t0,\t1 },\n+\t\t{ \"short\",\tCMIT_FMT_SHORT,\t\t0,\t0 },\n+\t\t{ \"email\",\tCMIT_FMT_EMAIL,\t\t0,\t0 },\n+\t\t{ \"fuller\",\tCMIT_FMT_FULLER,\t0,\t1 },\n+\t\t{ \"full\",\tCMIT_FMT_FULL,\t\t0,\t1 },\n+\t\t{ \"oneline\",\tCMIT_FMT_ONELINE,\t1,\t0 }\n \t};\n \tcommit_formats_len = ARRAY_SIZE(builtin_formats);\n \tbuiltin_formats_len = commit_formats_len;\n@@ -172,6 +173,7 @@ void get_commit_format(const char *arg, struct rev_info *rev)\n \n \trev->commit_format = commit_format->format;\n \trev->use_terminator = commit_format->is_tformat;\n+\trev->expand_tabs_in_log = commit_format->expand_tabs_in_log;\n \tif (commit_format->format == CMIT_FMT_USERFORMAT) {\n \t\tsave_user_format(rev, commit_format->user_format,\n \t\t\t\t commit_format->is_tformat);\n@@ -1685,11 +1687,15 @@ static void strbuf_add_tabexpand(struct strbuf *sb,\n  * the whole line (without the final newline), after\n  * de-tabifying.\n  */\n-static void pp_handle_indent(struct strbuf *sb, int indent,\n+static void pp_handle_indent(struct pretty_print_context *pp,\n+\t\t\t     struct strbuf *sb, int indent,\n \t\t\t     const char *line, int linelen)\n {\n \tstrbuf_addchars(sb, ' ', indent);\n-\tstrbuf_add_tabexpand(sb, line, linelen);\n+\tif (pp->expand_tabs_in_log)\n+\t\tstrbuf_add_tabexpand(sb, line, linelen);\n+\telse\n+\t\tstrbuf_add(sb, line, linelen);\n }\n \n void pp_remainder(struct pretty_print_context *pp,\n@@ -1716,7 +1722,7 @@ void pp_remainder(struct pretty_print_context *pp,\n \n \t\tstrbuf_grow(sb, linelen + indent + 20);\n \t\tif (indent)\n-\t\t\tpp_handle_indent(sb, indent, line, linelen);\n+\t\t\tpp_handle_indent(pp, sb, indent, line, linelen);\n \t\telse\n \t\t\tstrbuf_add(sb, line, linelen);\n \t\tstrbuf_addch(sb, '\\n');\ndiff --git a/revision.c b/revision.c\nindex df56fce..8827d9f 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1412,6 +1412,7 @@ void init_revisions(struct rev_info *revs, const char *prefix)\n \trevs->skip_count = -1;\n \trevs->max_count = -1;\n \trevs->max_parents = -1;\n+\trevs->expand_tabs_in_log = 1;\n \n \trevs->commit_format = CMIT_FMT_DEFAULT;\n \ndiff --git a/revision.h b/revision.h\nindex 23857c0..0bbfe0e 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -137,6 +137,7 @@ struct rev_info {\n \t\t\tabbrev_commit_given:1,\n \t\t\tzero_commit:1,\n \t\t\tuse_terminator:1,\n+\t\t\texpand_tabs_in_log:1,\n \t\t\tmissing_newline:1,\n \t\t\tdate_mode_explicit:1,\n \t\t\tpreserve_subject:1;\ndiff --git a/t/t4201-shortlog.sh b/t/t4201-shortlog.sh\nindex 987b708..d1e8259 100755\n--- a/t/t4201-shortlog.sh\n+++ b/t/t4201-shortlog.sh\n@@ -93,7 +93,7 @@ test_expect_success 'output from user-defined format is re-wrapped' '\n \ttest_cmp expect log.predictable\n '\n \n-test_expect_failure !MINGW 'shortlog wrapping' '\n+test_expect_success !MINGW 'shortlog wrapping' '\n \tcat >expect <<\\EOF &&\n A U Thor (5):\n       Test\n-- \n2.8.0-rc4-198-g3f6b64c\n"},{"id":"281622","messageId":"1458775426-2215-6-git-send-email-gitster@pobox.com","threadId":"41709","inReplyTo":"1458775426-2215-1-git-send-email-gitster@pobox.com","subject":"[PATCH v3 5/5] pretty-print: teach \"--no-expand-tabs\" option to \"git log\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-23T23:23:46Z","receivedAt":"2016-03-23T23:23:46Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"The output formats of \"git log\" that indent the log message by 4\nspaces have been updated to expand tabs by default in previous\nsteps, without a way to restore the original behaviour.\n\nIntroduce a new \"--no-expand-tabs\" option to allow this.\n\nAs the effect of options is cumulative,\n\n    $ git log [--pretty=medium] --no-expand-tabs\n\nwould not expand, while this invocation\n\n    $ git log --no-expand-tabs --pretty[=medium]\n\nby virtue of having --pretty later on the command line, expands tabs\nagain.\n\nWe _could_ introduce --expand-tabs option as well, to allow\n\n    $ git log --pretty=email --expand-tabs\n\nbut we don't bother, as the output format that do not expand tabs by\ndefault are mostly meant to transfer the contents as literally as\npossible.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n---\n Documentation/pretty-options.txt | 6 ++++++\n revision.c                       | 2 ++\n t/t4201-shortlog.sh              | 4 ++--\n 3 files changed, 10 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt\nindex 4b659ac..069b927 100644\n--- a/Documentation/pretty-options.txt\n+++ b/Documentation/pretty-options.txt\n@@ -42,6 +42,12 @@ people using 80-column terminals.\n \tverbatim; this means that invalid sequences in the original\n \tcommit may be copied to the output.\n \n+--no-expand-tabs::\n+\tThe formats that indent the log message by 4 spaces\n+\t(i.e. 'medium', 'full', and 'fuller') by default show tabs\n+\tin the log message expanded.  This option disables the\n+\texpansion.\n+\n ifndef::git-rev-list[]\n --notes[=<ref>]::\n \tShow the notes (see linkgit:git-notes[1]) that annotate the\ndiff --git a/revision.c b/revision.c\nindex 8827d9f..b0d2a36 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1916,6 +1916,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\trevs->verbose_header = 1;\n \t\trevs->pretty_given = 1;\n \t\tget_commit_format(arg+9, revs);\n+\t} else if (!strcmp(arg, \"--no-expand-tabs\")) {\n+\t\trevs->expand_tabs_in_log = 0;\n \t} else if (!strcmp(arg, \"--show-notes\") || !strcmp(arg, \"--notes\")) {\n \t\trevs->show_notes = 1;\n \t\trevs->show_notes_given = 1;\ndiff --git a/t/t4201-shortlog.sh b/t/t4201-shortlog.sh\nindex d1e8259..2fec948 100755\n--- a/t/t4201-shortlog.sh\n+++ b/t/t4201-shortlog.sh\n@@ -114,8 +114,8 @@ EOF\n \ttest_cmp expect out\n '\n \n-test_expect_failure !MINGW 'shortlog from non-git directory' '\n-\tgit log HEAD >log &&\n+test_expect_success !MINGW 'shortlog from non-git directory' '\n+\tgit log --no-expand-tabs HEAD >log &&\n \tGIT_DIR=non-existing git shortlog -w <log >out &&\n \ttest_cmp expect out\n '\n-- \n2.8.0-rc4-198-g3f6b64c\n"},{"id":"281625","messageId":"CA+55aFxBhTK0sa9qfXus3+ct7gZ+BV1aODF7xawQF3crQYYGJQ@mail.gmail.com","threadId":"41709","inReplyTo":"1458775426-2215-1-git-send-email-gitster@pobox.com","subject":"Re: [PATCH v3 0/5] Expanding tabs in \"git log\" output","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2016-03-23T23:47:21Z","receivedAt":"2016-03-23T23:47:21Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"On Wed, Mar 23, 2016 at 4:23 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> So here is the third try (previous round is found at $gmane/289166\n> and the very first one is at $gmane/288987).\n>\n> The first three patches are essentially the same as v2.  The last\n> two updates how the tab-expansion is internally controlled:\n\nI tested this (as it in in 'pu', rather than applying the patches),\nand it all seems to work fine. So Ack.\n\nAnd I agree that it would be good if all the commit printout logic was\nunified rather than having some ad-hoc \"let's just set the format\",\nbut I think that's a separate cleanup.\n\nIt might be more regular to have that \"--expand-tabs\" flag too (which\nwould then work with the email and raw formats), but I don't see any\nactual real use for it so it really doesn't matter.\n\n          Linus\n"},{"id":"281627","messageId":"20160324005849.GA8167@sigill.intra.peff.net","threadId":"41709","inReplyTo":"1458775426-2215-1-git-send-email-gitster@pobox.com","subject":"Re: [PATCH v3 0/5] Expanding tabs in \"git log\" output","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2016-03-24T00:58:50Z","receivedAt":"2016-03-24T00:58:50Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Mar 23, 2016 at 04:23:41PM -0700, Junio C Hamano wrote:\n\n> So here is the third try (previous round is found at $gmane/289166\n> and the very first one is at $gmane/288987).\n\nIs the plan to merge these as-is? The ordering is a bit funny (introduce\nbreakage, then repair it), and I think the first patch still breaks\nt4201.8 (which is then repaired in the fourth one).\n\nI think it would be a lot easier to review as:\n\n  1. Factor out pp_handle_indent(), and any other preparation.\n\n  2. Add --expand-tabs / --no-expand-tabs, with the logic going into\n     pp_handle_indent().\n\n  3. Flip the default for some formats to expand-tabs.\n\nOther than that, the end result seems OK to me (I think adding\n--expand-tabs would be nice, but I suspect it may need to be marked as\nincompatible with some formats; do all formats end up in this same\nwriting code path?).\n\n> By the way, I have to say that I hate how pretty formatting and\n> revision machinery interact with each other.\n> \n> pretty.c::commit_formats ought to be the authoritative source of how\n> each named format should work, but there are quite a many codepaths\n> that just assign CMIT_FMT_SOMETHING to revs->commit_format without\n> bothering with other fields in the cmt_fmt_map like is_tformat, and\n> I am not sure if they are working correctly even before this patch.\n\nI don't disagree with any of that. I suspect some of the logic may be\ncomplicated for sticking in a table, though. Perhaps we need a:\n\n  void set_pp_format(struct pretty_print_context *ctx, enum cmit_fmt fmt);\n\nthat sets up the whole struct based on the given format, and then the\nlogic can live in C code. I haven't looked closely at that code in a\nwhile, though, so maybe that is overkill.\n\n-Peff\n"},{"id":"281634","messageId":"xmqqh9fwbgku.fsf@gitster.mtv.corp.google.com","threadId":"41709","inReplyTo":"20160324005849.GA8167@sigill.intra.peff.net","subject":"Re: [PATCH v3 0/5] Expanding tabs in \"git log\" output","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-24T05:17:05Z","receivedAt":"2016-03-24T05:17:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> On Wed, Mar 23, 2016 at 04:23:41PM -0700, Junio C Hamano wrote:\n>\n>> So here is the third try (previous round is found at $gmane/289166\n>> and the very first one is at $gmane/288987).\n>\n> Is the plan to merge these as-is? The ordering is a bit funny (introduce\n> breakage, then repair it), and I think the first patch still breaks\n> t4201.8 (which is then repaired in the fourth one).\n\nI do not have a firm plan yet.  This was one of those \"during the\npre-release freeze, instead of reviewing shiny new toys by others\ntoo early, spend leftover time to tie loose ends\" attempts ;-)\n\nI'd agree that the \"final\" version should do our usual \"progressive\nimprovement, never stepping back one and then forward two\", but I\nwanted to see what the endgame state would look like first, and by\ndoing the incremental \"the first one gets it 80% right, and fix it\nup with follow-up patches\" I didn't have to worry about at what\npoint I need to take the authorship of which patch.\n"},{"id":"281639","messageId":"56F391A4.6090603@web.de","threadId":"41709","inReplyTo":"1458775426-2215-1-git-send-email-gitster@pobox.com","subject":"Re: [PATCH v3 0/5] Expanding tabs in \"git log\" output","fromName":"Torsten Bögershausen","fromEmail":"tboegi@web.de","sentAt":"2016-03-24T07:05:09Z","receivedAt":"2016-03-24T07:05:09Z","isPatch":true,"sender":{"key":"tboegi@web.de","avatar":"https://avatars.githubusercontent.com/u/7138363?v=4"},"body":">  [5/5] adds a new option --no-expand-tabs that controls the bit 4/5\n>        introduces, so that \"git log [--pretty] --no-expand-tabs\"\n>        would show the log message indented by 4 spaces, without tab\n>        expansion.\n\nDoes this introduce an unnecessary regression out of the sudden ?\n\nWould it make sense to have\ngit log --tab-size=8\n(or similar)\n\nand add a config variable like\ngit config ui.logtabsize\nwhich is 0 by default to get the old handling and 8 for the new one ?\n"},{"id":"281675","messageId":"xmqqd1qjc2g2.fsf@gitster.mtv.corp.google.com","threadId":"41709","inReplyTo":"56F391A4.6090603@web.de","subject":"Re: [PATCH v3 0/5] Expanding tabs in \"git log\" output","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-24T15:37:01Z","receivedAt":"2016-03-24T15:37:01Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Torsten Bögershausen <tboegi@web.de> writes:\n\n>>  [5/5] adds a new option --no-expand-tabs that controls the bit 4/5\n>>        introduces, so that \"git log [--pretty] --no-expand-tabs\"\n>>        would show the log message indented by 4 spaces, without tab\n>>        expansion.\n>\n> Does this introduce an unnecessary regression out of the sudden ?\n\nAs I see this as a pure UI-level improvement done to a few of our\nPorcelain program, I would say there is no regression here.\n"},{"id":"281703","messageId":"xmqqmvpn91o2.fsf@gitster.mtv.corp.google.com","threadId":"41709","inReplyTo":"56F391A4.6090603@web.de","subject":"Re: [PATCH v3 0/5] Expanding tabs in \"git log\" output","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-24T18:22:05Z","receivedAt":"2016-03-24T18:22:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Torsten Bögershausen <tboegi@web.de> writes:\n\n> Would it make sense to have\n> git log --tab-size=8\n> (or similar)\n>\n> and add a config variable like\n> git config ui.logtabsize\n> which is 0 by default to get the old handling and 8 for the new one ?\n\nThat may be a good approach (I agree with you that --tab-size is not\nthe best name).  Want to try it as a replacement?\n"},{"id":"281790","messageId":"56F50608.10606@web.de","threadId":"41709","inReplyTo":"xmqqmvpn91o2.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v3 0/5] Expanding tabs in \"git log\" output","fromName":"Torsten Bögershausen","fromEmail":"tboegi@web.de","sentAt":"2016-03-25T09:34:00Z","receivedAt":"2016-03-25T09:34:00Z","isPatch":true,"sender":{"key":"tboegi@web.de","avatar":"https://avatars.githubusercontent.com/u/7138363?v=4"},"body":"On 2016-03-24 19.22, Junio C Hamano wrote:\n> Torsten Bögershausen <tboegi@web.de> writes:\n> \n>> Would it make sense to have\n>> git log --tab-size=8\n>> (or similar)\n>>\n>> and add a config variable like\n>> git config ui.logtabsize\n>> which is 0 by default to get the old handling and 8 for the new one ?\n> \n> That may be a good approach (I agree with you that --tab-size is not\n> the best name).  Want to try it as a replacement?\n\nMay be log.tabwidth ?\nI'm happy to help out here, if we can cook the feature in pu for 3-4 weeks\nor so ?\n"},{"id":"281811","messageId":"56F5477F.6090600@web.de","threadId":"41709","inReplyTo":"56F50608.10606@web.de","subject":"Re: [PATCH v3 0/5] Expanding tabs in \"git log\" output","fromName":"Torsten Bögershausen","fromEmail":"tboegi@web.de","sentAt":"2016-03-25T14:13:19Z","receivedAt":"2016-03-25T14:13:19Z","isPatch":true,"sender":{"key":"tboegi@web.de","avatar":"https://avatars.githubusercontent.com/u/7138363?v=4"},"body":"This is copy-paste replacement for the last commit.\n(Most probably it is white space damaged)\nI'm not sure, is it's worth it ?\nIf yes, I can send a proper patch later.\n\ngit show HEAD\n\ncommit 3ac551127d51cd59b24f49729d9ce4dd011a09a1\nAuthor: Junio C Hamano <gitster@pobox.com>\nDate:   Wed Mar 23 15:57:42 2016 -0700\n\n    pretty-print: Add the config variable log.tabwidth\n\n    The output formats of \"git log\" that indent the log message by 4\n    spaces have been updated to expand tabs by default in previous\n    steps, without a way to restore the original behaviour.\n\n    Introduce a config variable log.tabwidth to allow this.\n\n        $ git -c log.tabwidth=0 log [--pretty=medium]\n\n    would not expand.\n\n    The non-expansion can be made permanent:\n        $ git config log.tabwidth 0\n\n    Or the TAB width can be changed like this:\n        $ git config log.tabwidth 4\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 2cd6bdd..611f5e4 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -1915,6 +1915,10 @@ log.showRoot::\n \tTools like linkgit:git-log[1] or linkgit:git-whatchanged[1], which\n \tnormally hide the root commit will now show it. True by default.\n\n+log.tabWidth::\n+\tSets the width of a TAB.  If 0, no TAB expansion is done.\n+\t8 by default.\n+\n log.mailmap::\n \tIf true, makes linkgit:git-log[1], linkgit:git-show[1], and\n \tlinkgit:git-whatchanged[1] assume `--use-mailmap`.\ndiff --git a/cache.h b/cache.h\nindex b829410..fd115d2 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -649,6 +649,7 @@ extern int ignore_case;\n extern int assume_unchanged;\n extern int prefer_symlink_refs;\n extern int log_all_ref_updates;\n+extern unsigned log_tab_width;\n extern int warn_ambiguous_refs;\n extern int warn_on_object_refname_ambiguity;\n extern int shared_repository;\ndiff --git a/config.c b/config.c\nindex 9ba40bc..e6aadfe 100644\n--- a/config.c\n+++ b/config.c\n@@ -1030,6 +1030,11 @@ int git_default_config(const char *var, const char\n*value, void *dummy)\n \t\tpack_size_limit_cfg = git_config_ulong(var, value);\n \t\treturn 0;\n \t}\n+\n+\tif (!strcmp(var, \"log.tabwidth\")) {\n+\t\tlog_tab_width = (unsigned)git_config_ulong(var, value);\n+\t\treturn 0;\n+\t}\n \t/* Add other config variables here and to Documentation/config.txt. */\n \treturn 0;\n }\ndiff --git a/environment.c b/environment.c\nindex 6dec9d0..3c72b44 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -21,6 +21,7 @@ int ignore_case;\n int assume_unchanged;\n int prefer_symlink_refs;\n int is_bare_repository_cfg = -1; /* unspecified */\n+unsigned log_tab_width = 8;\n int log_all_ref_updates = -1; /* unspecified */\n int warn_ambiguous_refs = 1;\n int warn_on_object_refname_ambiguity = 1;\ndiff --git a/pretty.c b/pretty.c\nindex 5a33b7e..1d92c55 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -1667,7 +1667,7 @@ static void strbuf_add_tabexpand(struct strbuf *sb,\n \t\tstrbuf_add(sb, line, tab - line);\n\n \t\t/* .. and the de-tabified tab */\n-\t\tstrbuf_addchars(sb, ' ', 8-(width & 7));\n+\t\tstrbuf_addchars(sb, ' ', log_tab_width - (width % log_tab_width));\n\n \t\t/* Skip over the printed part .. */\n \t\tlinelen -= 1+tab-line;\n@@ -1692,7 +1692,7 @@ static void pp_handle_indent(struct pretty_print_context *pp,\n \t\t\t     const char *line, int linelen)\n {\n \tstrbuf_addchars(sb, ' ', indent);\n-\tif (pp->expand_tabs_in_log)\n+\tif (pp->expand_tabs_in_log && log_tab_width)\n \t\tstrbuf_add_tabexpand(sb, line, linelen);\n \telse\n \t\tstrbuf_add(sb, line, linelen);\ndiff --git a/t/t4201-shortlog.sh b/t/t4201-shortlog.sh\nindex 96233ca..9235a2e 100755\n--- a/t/t4201-shortlog.sh\n+++ b/t/t4201-shortlog.sh\n@@ -114,8 +114,8 @@ EOF\n \ttest_cmp expect out\n '\n\n-test_expect_failure !MINGW 'shortlog from non-git directory' '\n-\tgit log HEAD >log &&\n+test_expect_success !MINGW 'shortlog from non-git directory' '\n+\tgit -c log.tabwidth=0 log HEAD >log &&\n \tGIT_DIR=non-existing git shortlog -w <log >out &&\n \ttest_cmp expect out\n '\n"},{"id":"281822","messageId":"xmqqa8lm5xun.fsf@gitster.mtv.corp.google.com","threadId":"41709","inReplyTo":"56F50608.10606@web.de","subject":"Re: [PATCH v3 0/5] Expanding tabs in \"git log\" output","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-25T16:25:04Z","receivedAt":"2016-03-25T16:25:04Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Torsten Bögershausen <tboegi@web.de> writes:\n\n> On 2016-03-24 19.22, Junio C Hamano wrote:\n>> Torsten Bögershausen <tboegi@web.de> writes:\n>> \n>>> Would it make sense to have\n>>> git log --tab-size=8\n>>> (or similar)\n>>>\n>>> and add a config variable like\n>>> git config ui.logtabsize\n>>> which is 0 by default to get the old handling and 8 for the new one ?\n>> \n>> That may be a good approach (I agree with you that --tab-size is not\n>> the best name).  Want to try it as a replacement?\n>\n> May be log.tabwidth ?\n\nThe reason why I thought \"--tab-size=4\" is not the best name is\nbecause it only states that the user prefers a non-standard tab\nstops that are every 4 display spaces, and does not say what we\nwith do that information, i.e. it does not hint \"We expand tabs\nto spaces according to this setting\" in its name.\n\nI think log.tabwidth shares the same characteristics.\n"},{"id":"281824","messageId":"xmqq37re5x33.fsf@gitster.mtv.corp.google.com","threadId":"41709","inReplyTo":"56F5477F.6090600@web.de","subject":"Re: [PATCH v3 0/5] Expanding tabs in \"git log\" output","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-25T16:41:36Z","receivedAt":"2016-03-25T16:41:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Torsten Bögershausen <tboegi@web.de> writes:\n\n> This is copy-paste replacement for the last commit.\n> (Most probably it is white space damaged)\n> I'm not sure, is it's worth it ?\n\nNot if you are keeping \"expand_tabs_in_log\" boolean field.\n\nI was expecting that the new \"log-tab-width\" thing extends the\nexpand_tabs_in_log as the concept--it used to be a boolean \"do we or\ndo we not expand?\" to \"set it to 0 if we do not want to expand, set\nit to N if we do want to expand to every N display spaces\".  In\nother words, if you introduce this new thing, the boolean should not\ne necessary and it should go.  Did I misread your earlier message\nthat described your idea?\n\n> +log.tabWidth::\n> +\tSets the width of a TAB.  If 0, no TAB expansion is done.\n> +\t8 by default.\n\nYou need to make it clear where tabs are expanded.  The readers\nwould wonder if it expands tabs in \"log -p\" patch output, etc.\n\n\nA related tangent. I suspect\n\n\tgit format-patch --expand-tabs-in-log-message=4\n\nmight be a good feature to help people whose editors are configured\nto move to next-multiple-of-4 column with a tab, and applying their\npatch would show unaligned lines in \"git log\" output for others, by\nexpanding their tabs when sending the patch out.  We might even want\nto add a related option\n\n\tgit am --unexpand-tabs\n\nthat collapses a run of SP that fills to next-multiple-of-8 into a\ntab on the receiving end.\n"},{"id":"282145","messageId":"1459293309-25195-1-git-send-email-gitster@pobox.com","threadId":"41709","inReplyTo":"1458775426-2215-1-git-send-email-gitster@pobox.com","subject":"[PATCH v4 0/3] Expanding tabs in \"git log\" output","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-29T23:15:06Z","receivedAt":"2016-03-29T23:15:06Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"So here is the fourth try.  Previous round are at $gmane/289694,\n$gmane/289166, and $gmane/288987.\n\nI didn't quite find a good order to build this progressively, so\nthis series:\n\n - First adds the internal machinery and explicit --expand-tabs.\n   This keeps Linus's authorship, but is different in that it is not\n   enabled by default;\n\n - Then enable --expand-tabs by default for selected pretty formats;\n\n - And optionally, allow custom tab-width to be used.\n\nJunio C Hamano (2):\n  pretty: enable --expand-tabs by default for selected pretty formats\n  pretty: allow tweaking tabwidth in --expand-tabs\n\nLinus Torvalds (1):\n  pretty: expand tabs in indented logs to make things line up properly\n\n Documentation/pretty-options.txt | 14 +++++++\n commit.h                         |  1 +\n log-tree.c                       |  1 +\n pretty.c                         | 87 +++++++++++++++++++++++++++++++++++-----\n revision.c                       | 10 +++++\n revision.h                       |  2 +-\n t/t4201-shortlog.sh              |  2 +-\n 7 files changed, 106 insertions(+), 11 deletions(-)\n\n-- \n2.8.0-215-gd29a7d9\n"},{"id":"282144","messageId":"1459293309-25195-2-git-send-email-gitster@pobox.com","threadId":"41709","inReplyTo":"1459293309-25195-1-git-send-email-gitster@pobox.com","subject":"[PATCH v4 1/3] pretty: expand tabs in indented logs to make things line up properly","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-29T23:15:07Z","receivedAt":"2016-03-29T23:15:07Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"From: Linus Torvalds <torvalds@linux-foundation.org>\n\nA commit log message sometimes tries to line things up using tabs,\nassuming fixed-width font with the standard 8-place tab settings.\nViewing such a commit however does not work well in \"git log\", as\nwe indent the lines by prefixing 4 spaces in front of them.\n\nThis should all line up:\n\n  Column 1\tColumn 2\n  --------\t--------\n  A\t\tB\n  ABCD\t\tEFGH\n  SPACES        Instead of Tabs\n\nEven with multi-byte UTF8 characters:\n\n  Column 1\tColumn 2\n  --------\t--------\n  Ä\t\tB\n  åäö\t\t100\n  A Møøse\tonce bit my sister..\n\nTab-expand the lines in \"git log --expand-tabs\" output before\nprefixing 4 spaces.\n\nThis is based on the patch by Linus Torvalds, but changed to require\nan explicit command line option to enable the behaviour.\n\nSigned-off-by: Linus Torvalds <torvalds@linux-foundation.org>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n Documentation/pretty-options.txt |  6 ++++\n commit.h                         |  1 +\n log-tree.c                       |  1 +\n pretty.c                         | 71 ++++++++++++++++++++++++++++++++++++++--\n revision.c                       |  2 ++\n revision.h                       |  1 +\n 6 files changed, 80 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt\nindex 4b659ac..4fb5c76 100644\n--- a/Documentation/pretty-options.txt\n+++ b/Documentation/pretty-options.txt\n@@ -42,6 +42,12 @@ people using 80-column terminals.\n \tverbatim; this means that invalid sequences in the original\n \tcommit may be copied to the output.\n \n+--expand-tabs::\n+\tPerform a tab expansion (replace each tab with enough number\n+\tof spaces to fill to the next display column that is\n+\tmultiple of 8) in the log message before using the message\n+\tto show in the output.\n+\n ifndef::git-rev-list[]\n --notes[=<ref>]::\n \tShow the notes (see linkgit:git-notes[1]) that annotate the\ndiff --git a/commit.h b/commit.h\nindex 5d58be0..a7ef682 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -147,6 +147,7 @@ struct pretty_print_context {\n \tint preserve_subject;\n \tstruct date_mode date_mode;\n \tunsigned date_mode_explicit:1;\n+\tunsigned expand_tabs_in_log:1;\n \tint need_8bit_cte;\n \tchar *notes_message;\n \tstruct reflog_walk_info *reflog_info;\ndiff --git a/log-tree.c b/log-tree.c\nindex 60f9839..78a5381 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -683,6 +683,7 @@ void show_log(struct rev_info *opt)\n \tctx.fmt = opt->commit_format;\n \tctx.mailmap = opt->mailmap;\n \tctx.color = opt->diffopt.use_color;\n+\tctx.expand_tabs_in_log = opt->expand_tabs_in_log;\n \tctx.output_encoding = get_log_output_encoding();\n \tif (opt->from_ident.mail_begin && opt->from_ident.name_begin)\n \t\tctx.from_ident = &opt->from_ident;\ndiff --git a/pretty.c b/pretty.c\nindex 92b2870..c8b075d 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -1629,6 +1629,72 @@ void pp_title_line(struct pretty_print_context *pp,\n \tstrbuf_release(&title);\n }\n \n+static int pp_utf8_width(const char *start, const char *end)\n+{\n+\tint width = 0;\n+\tsize_t remain = end - start;\n+\n+\twhile (remain) {\n+\t\tint n = utf8_width(&start, &remain);\n+\t\tif (n < 0 || !start)\n+\t\t\treturn -1;\n+\t\twidth += n;\n+\t}\n+\treturn width;\n+}\n+\n+static void strbuf_add_tabexpand(struct strbuf *sb,\n+\t\t\t\t const char *line, int linelen)\n+{\n+\tconst char *tab;\n+\n+\twhile ((tab = memchr(line, '\\t', linelen)) != NULL) {\n+\t\tint width = pp_utf8_width(line, tab);\n+\n+\t\t/*\n+\t\t * If it wasn't well-formed utf8, or it\n+\t\t * had characters with badly defined\n+\t\t * width (control characters etc), just\n+\t\t * give up on trying to align things.\n+\t\t */\n+\t\tif (width < 0)\n+\t\t\tbreak;\n+\n+\t\t/* Output the data .. */\n+\t\tstrbuf_add(sb, line, tab - line);\n+\n+\t\t/* .. and the de-tabified tab */\n+\t\tstrbuf_addchars(sb, ' ', 8 - (width % 8));\n+\n+\t\t/* Skip over the printed part .. */\n+\t\tlinelen -= tab + 1 - line;\n+\t\tline = tab + 1;\n+\t}\n+\n+\t/*\n+\t * Print out everything after the last tab without\n+\t * worrying about width - there's nothing more to\n+\t * align.\n+\t */\n+\tstrbuf_add(sb, line, linelen);\n+}\n+\n+/*\n+ * pp_handle_indent() prints out the intendation, and\n+ * the whole line (without the final newline), after\n+ * de-tabifying.\n+ */\n+static void pp_handle_indent(struct pretty_print_context *pp,\n+\t\t\t     struct strbuf *sb, int indent,\n+\t\t\t     const char *line, int linelen)\n+{\n+\tstrbuf_addchars(sb, ' ', indent);\n+\tif (pp->expand_tabs_in_log)\n+\t\tstrbuf_add_tabexpand(sb, line, linelen);\n+\telse\n+\t\tstrbuf_add(sb, line, linelen);\n+}\n+\n void pp_remainder(struct pretty_print_context *pp,\n \t\t  const char **msg_p,\n \t\t  struct strbuf *sb,\n@@ -1653,8 +1719,9 @@ void pp_remainder(struct pretty_print_context *pp,\n \n \t\tstrbuf_grow(sb, linelen + indent + 20);\n \t\tif (indent)\n-\t\t\tstrbuf_addchars(sb, ' ', indent);\n-\t\tstrbuf_add(sb, line, linelen);\n+\t\t\tpp_handle_indent(pp, sb, indent, line, linelen);\n+\t\telse\n+\t\t\tstrbuf_add(sb, line, linelen);\n \t\tstrbuf_addch(sb, '\\n');\n \t}\n }\ndiff --git a/revision.c b/revision.c\nindex df56fce..e662230 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1915,6 +1915,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\trevs->verbose_header = 1;\n \t\trevs->pretty_given = 1;\n \t\tget_commit_format(arg+9, revs);\n+\t} else if (!strcmp(arg, \"--expand-tabs\")) {\n+\t\trevs->expand_tabs_in_log = 1;\n \t} else if (!strcmp(arg, \"--show-notes\") || !strcmp(arg, \"--notes\")) {\n \t\trevs->show_notes = 1;\n \t\trevs->show_notes_given = 1;\ndiff --git a/revision.h b/revision.h\nindex 23857c0..4079753 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -133,6 +133,7 @@ struct rev_info {\n \t\t\tshow_notes_given:1,\n \t\t\tshow_signature:1,\n \t\t\tpretty_given:1,\n+\t\t\texpand_tabs_in_log:1,\n \t\t\tabbrev_commit:1,\n \t\t\tabbrev_commit_given:1,\n \t\t\tzero_commit:1,\n-- \n2.8.0-215-gd29a7d9\n"},{"id":"282146","messageId":"1459293309-25195-3-git-send-email-gitster@pobox.com","threadId":"41709","inReplyTo":"1459293309-25195-1-git-send-email-gitster@pobox.com","subject":"[PATCH v4 2/3] pretty: enable --expand-tabs by default for selected pretty formats","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-29T23:15:08Z","receivedAt":"2016-03-29T23:15:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"git log --pretty={medium,full,fuller}\" and \"git log\" by default\nprepend 4 spaces to the log message, so it makes sense to enable\nthe new \"expand-tabs\" facility by default for these formats.\nAdd --no-expand-tabs option to override the new default.\n\nThe change alone breaks a test in t4201 that runs \"git shortlog\"\non the output from \"git log\", and expects that the output from\n\"git log\" does not do such a tab expansion.  Adjust the test to\nexplicitly disable expand-tabs with --no-expand-tabs.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n Documentation/pretty-options.txt |  6 ++++++\n pretty.c                         | 16 +++++++++-------\n revision.c                       |  3 +++\n t/t4201-shortlog.sh              |  2 +-\n 4 files changed, 19 insertions(+), 8 deletions(-)\n\ndiff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt\nindex 4fb5c76..23967b6 100644\n--- a/Documentation/pretty-options.txt\n+++ b/Documentation/pretty-options.txt\n@@ -43,10 +43,16 @@ people using 80-column terminals.\n \tcommit may be copied to the output.\n \n --expand-tabs::\n+--no-expand-tabs::\n \tPerform a tab expansion (replace each tab with enough number\n \tof spaces to fill to the next display column that is\n \tmultiple of 8) in the log message before using the message\n \tto show in the output.\n++\n+By default, tabs are expanded in pretty formats that indent the log\n+message by 4 spaces (i.e.  'medium', which is the default, 'full',\n+and \"fuller').  `--no-expand-tabs` option can be used to disable\n+this.\n \n ifndef::git-rev-list[]\n --notes[=<ref>]::\ndiff --git a/pretty.c b/pretty.c\nindex c8b075d..de22a8c 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -16,6 +16,7 @@ static struct cmt_fmt_map {\n \tconst char *name;\n \tenum cmit_fmt format;\n \tint is_tformat;\n+\tint expand_tabs_in_log;\n \tint is_alias;\n \tconst char *user_format;\n } *commit_formats;\n@@ -87,13 +88,13 @@ static int git_pretty_formats_config(const char *var, const char *value, void *c\n static void setup_commit_formats(void)\n {\n \tstruct cmt_fmt_map builtin_formats[] = {\n-\t\t{ \"raw\",\tCMIT_FMT_RAW,\t\t0 },\n-\t\t{ \"medium\",\tCMIT_FMT_MEDIUM,\t0 },\n-\t\t{ \"short\",\tCMIT_FMT_SHORT,\t\t0 },\n-\t\t{ \"email\",\tCMIT_FMT_EMAIL,\t\t0 },\n-\t\t{ \"fuller\",\tCMIT_FMT_FULLER,\t0 },\n-\t\t{ \"full\",\tCMIT_FMT_FULL,\t\t0 },\n-\t\t{ \"oneline\",\tCMIT_FMT_ONELINE,\t1 }\n+\t\t{ \"raw\",\tCMIT_FMT_RAW,\t\t0,\t0 },\n+\t\t{ \"medium\",\tCMIT_FMT_MEDIUM,\t0,\t1 },\n+\t\t{ \"short\",\tCMIT_FMT_SHORT,\t\t0,\t0 },\n+\t\t{ \"email\",\tCMIT_FMT_EMAIL,\t\t0,\t0 },\n+\t\t{ \"fuller\",\tCMIT_FMT_FULLER,\t0,\t1 },\n+\t\t{ \"full\",\tCMIT_FMT_FULL,\t\t0,\t1 },\n+\t\t{ \"oneline\",\tCMIT_FMT_ONELINE,\t1,\t0 }\n \t};\n \tcommit_formats_len = ARRAY_SIZE(builtin_formats);\n \tbuiltin_formats_len = commit_formats_len;\n@@ -172,6 +173,7 @@ void get_commit_format(const char *arg, struct rev_info *rev)\n \n \trev->commit_format = commit_format->format;\n \trev->use_terminator = commit_format->is_tformat;\n+\trev->expand_tabs_in_log = commit_format->expand_tabs_in_log;\n \tif (commit_format->format == CMIT_FMT_USERFORMAT) {\n \t\tsave_user_format(rev, commit_format->user_format,\n \t\t\t\t commit_format->is_tformat);\ndiff --git a/revision.c b/revision.c\nindex e662230..b1d767a 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1412,6 +1412,7 @@ void init_revisions(struct rev_info *revs, const char *prefix)\n \trevs->skip_count = -1;\n \trevs->max_count = -1;\n \trevs->max_parents = -1;\n+\trevs->expand_tabs_in_log = 1;\n \n \trevs->commit_format = CMIT_FMT_DEFAULT;\n \n@@ -1917,6 +1918,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\tget_commit_format(arg+9, revs);\n \t} else if (!strcmp(arg, \"--expand-tabs\")) {\n \t\trevs->expand_tabs_in_log = 1;\n+\t} else if (!strcmp(arg, \"--no-expand-tabs\")) {\n+\t\trevs->expand_tabs_in_log = 0;\n \t} else if (!strcmp(arg, \"--show-notes\") || !strcmp(arg, \"--notes\")) {\n \t\trevs->show_notes = 1;\n \t\trevs->show_notes_given = 1;\ndiff --git a/t/t4201-shortlog.sh b/t/t4201-shortlog.sh\nindex 7600a3e..2fec948 100755\n--- a/t/t4201-shortlog.sh\n+++ b/t/t4201-shortlog.sh\n@@ -115,7 +115,7 @@ EOF\n '\n \n test_expect_success !MINGW 'shortlog from non-git directory' '\n-\tgit log HEAD >log &&\n+\tgit log --no-expand-tabs HEAD >log &&\n \tGIT_DIR=non-existing git shortlog -w <log >out &&\n \ttest_cmp expect out\n '\n-- \n2.8.0-215-gd29a7d9\n"},{"id":"282147","messageId":"1459293309-25195-4-git-send-email-gitster@pobox.com","threadId":"41709","inReplyTo":"1459293309-25195-1-git-send-email-gitster@pobox.com","subject":"[PATCH v4 3/3] pretty: allow tweaking tabwidth in --expand-tabs","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-29T23:15:09Z","receivedAt":"2016-03-29T23:15:09Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"When the local convention of the project is to use tab width that is\nnot 8, it may make sense to allow \"git log --expand-tabs=<n>\" to\ntweak the output to match it.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n Documentation/pretty-options.txt | 10 ++++++----\n commit.h                         |  2 +-\n pretty.c                         | 12 ++++++------\n revision.c                       |  9 +++++++--\n revision.h                       |  3 +--\n 5 files changed, 21 insertions(+), 15 deletions(-)\n\ndiff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt\nindex 23967b6..8a944b1 100644\n--- a/Documentation/pretty-options.txt\n+++ b/Documentation/pretty-options.txt\n@@ -42,17 +42,19 @@ people using 80-column terminals.\n \tverbatim; this means that invalid sequences in the original\n \tcommit may be copied to the output.\n \n+--expand-tabs=<n>::\n --expand-tabs::\n --no-expand-tabs::\n \tPerform a tab expansion (replace each tab with enough number\n \tof spaces to fill to the next display column that is\n-\tmultiple of 8) in the log message before using the message\n-\tto show in the output.\n+\tmultiple of '<n>') in the log message before using the message\n+\tto show in the output.  `--expand-tabs` is a short-hand for\n+\t`--expand-tabs=8`, and `--no-expand-tabs` is a short-hand for\n+\t`--expand-tabs=0`, which disables tab expansion.\n +\n By default, tabs are expanded in pretty formats that indent the log\n message by 4 spaces (i.e.  'medium', which is the default, 'full',\n-and \"fuller').  `--no-expand-tabs` option can be used to disable\n-this.\n+and \"fuller').\n \n ifndef::git-rev-list[]\n --notes[=<ref>]::\ndiff --git a/commit.h b/commit.h\nindex a7ef682..2185c8d 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -147,7 +147,7 @@ struct pretty_print_context {\n \tint preserve_subject;\n \tstruct date_mode date_mode;\n \tunsigned date_mode_explicit:1;\n-\tunsigned expand_tabs_in_log:1;\n+\tunsigned expand_tabs_in_log;\n \tint need_8bit_cte;\n \tchar *notes_message;\n \tstruct reflog_walk_info *reflog_info;\ndiff --git a/pretty.c b/pretty.c\nindex de22a8c..b340ecd 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -89,11 +89,11 @@ static void setup_commit_formats(void)\n {\n \tstruct cmt_fmt_map builtin_formats[] = {\n \t\t{ \"raw\",\tCMIT_FMT_RAW,\t\t0,\t0 },\n-\t\t{ \"medium\",\tCMIT_FMT_MEDIUM,\t0,\t1 },\n+\t\t{ \"medium\",\tCMIT_FMT_MEDIUM,\t0,\t8 },\n \t\t{ \"short\",\tCMIT_FMT_SHORT,\t\t0,\t0 },\n \t\t{ \"email\",\tCMIT_FMT_EMAIL,\t\t0,\t0 },\n-\t\t{ \"fuller\",\tCMIT_FMT_FULLER,\t0,\t1 },\n-\t\t{ \"full\",\tCMIT_FMT_FULL,\t\t0,\t1 },\n+\t\t{ \"fuller\",\tCMIT_FMT_FULLER,\t0,\t8 },\n+\t\t{ \"full\",\tCMIT_FMT_FULL,\t\t0,\t8 },\n \t\t{ \"oneline\",\tCMIT_FMT_ONELINE,\t1,\t0 }\n \t};\n \tcommit_formats_len = ARRAY_SIZE(builtin_formats);\n@@ -1645,7 +1645,7 @@ static int pp_utf8_width(const char *start, const char *end)\n \treturn width;\n }\n \n-static void strbuf_add_tabexpand(struct strbuf *sb,\n+static void strbuf_add_tabexpand(struct strbuf *sb, int tabwidth,\n \t\t\t\t const char *line, int linelen)\n {\n \tconst char *tab;\n@@ -1666,7 +1666,7 @@ static void strbuf_add_tabexpand(struct strbuf *sb,\n \t\tstrbuf_add(sb, line, tab - line);\n \n \t\t/* .. and the de-tabified tab */\n-\t\tstrbuf_addchars(sb, ' ', 8 - (width % 8));\n+\t\tstrbuf_addchars(sb, ' ', tabwidth - (width % tabwidth));\n \n \t\t/* Skip over the printed part .. */\n \t\tlinelen -= tab + 1 - line;\n@@ -1692,7 +1692,7 @@ static void pp_handle_indent(struct pretty_print_context *pp,\n {\n \tstrbuf_addchars(sb, ' ', indent);\n \tif (pp->expand_tabs_in_log)\n-\t\tstrbuf_add_tabexpand(sb, line, linelen);\n+\t\tstrbuf_add_tabexpand(sb, pp->expand_tabs_in_log, line, linelen);\n \telse\n \t\tstrbuf_add(sb, line, linelen);\n }\ndiff --git a/revision.c b/revision.c\nindex b1d767a..4f9ecbe 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1412,7 +1412,7 @@ void init_revisions(struct rev_info *revs, const char *prefix)\n \trevs->skip_count = -1;\n \trevs->max_count = -1;\n \trevs->max_parents = -1;\n-\trevs->expand_tabs_in_log = 1;\n+\trevs->expand_tabs_in_log = 8;\n \n \trevs->commit_format = CMIT_FMT_DEFAULT;\n \n@@ -1917,9 +1917,14 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\trevs->pretty_given = 1;\n \t\tget_commit_format(arg+9, revs);\n \t} else if (!strcmp(arg, \"--expand-tabs\")) {\n-\t\trevs->expand_tabs_in_log = 1;\n+\t\trevs->expand_tabs_in_log = 8;\n \t} else if (!strcmp(arg, \"--no-expand-tabs\")) {\n \t\trevs->expand_tabs_in_log = 0;\n+\t} else if (skip_prefix(arg, \"--expand-tabs=\", &arg)) {\n+\t\tint val;\n+\t\tif (strtol_i(arg, 10, &val) < 0 || val < 0)\n+\t\t\tdie(\"'%s': not a non-negative integer\", arg);\n+\t\trevs->expand_tabs_in_log = val;\n \t} else if (!strcmp(arg, \"--show-notes\") || !strcmp(arg, \"--notes\")) {\n \t\trevs->show_notes = 1;\n \t\trevs->show_notes_given = 1;\ndiff --git a/revision.h b/revision.h\nindex 4079753..cf6615a 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -133,7 +133,6 @@ struct rev_info {\n \t\t\tshow_notes_given:1,\n \t\t\tshow_signature:1,\n \t\t\tpretty_given:1,\n-\t\t\texpand_tabs_in_log:1,\n \t\t\tabbrev_commit:1,\n \t\t\tabbrev_commit_given:1,\n \t\t\tzero_commit:1,\n@@ -149,7 +148,7 @@ struct rev_info {\n \t\t\tlinear:1;\n \n \tstruct date_mode date_mode;\n-\n+\tunsigned int\texpand_tabs_in_log;\n \tunsigned int\tabbrev;\n \tenum cmit_fmt\tcommit_format;\n \tstruct log_info *loginfo;\n-- \n2.8.0-215-gd29a7d9\n"},{"id":"282154","messageId":"CAPig+cTd_VRnikMzN7b2qfeG87M0v-4_qM42MkhOcRT54Wmv=Q@mail.gmail.com","threadId":"41709","inReplyTo":"1459293309-25195-2-git-send-email-gitster@pobox.com","subject":"Re: [PATCH v4 1/3] pretty: expand tabs in indented logs to make things line up properly","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2016-03-30T00:17:24Z","receivedAt":"2016-03-30T00:17:24Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Tue, Mar 29, 2016 at 7:15 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> From: Linus Torvalds <torvalds@linux-foundation.org>\n>\n> A commit log message sometimes tries to line things up using tabs,\n> assuming fixed-width font with the standard 8-place tab settings.\n> Viewing such a commit however does not work well in \"git log\", as\n> we indent the lines by prefixing 4 spaces in front of them.\n> [...]\n> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>\n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n> diff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt\n> @@ -42,6 +42,12 @@ people using 80-column terminals.\n> +--expand-tabs::\n> +       Perform a tab expansion (replace each tab with enough number\n> +       of spaces to fill to the next display column that is\n\nNit: \"enough spaces\" or \"a sufficient number of spaces\".\n\n> +       multiple of 8) in the log message before using the message\n> +       to show in the output.\n"},{"id":"282184","messageId":"20160330013851.GF2237@sigill.intra.peff.net","threadId":"41709","inReplyTo":"1459293309-25195-3-git-send-email-gitster@pobox.com","subject":"Re: [PATCH v4 2/3] pretty: enable --expand-tabs by default for selected pretty formats","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2016-03-30T01:38:51Z","receivedAt":"2016-03-30T01:38:51Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Mar 29, 2016 at 04:15:08PM -0700, Junio C Hamano wrote:\n\n> diff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt\n> index 4fb5c76..23967b6 100644\n> --- a/Documentation/pretty-options.txt\n> +++ b/Documentation/pretty-options.txt\n> @@ -43,10 +43,16 @@ people using 80-column terminals.\n>  \tcommit may be copied to the output.\n>  \n>  --expand-tabs::\n> +--no-expand-tabs::\n>  \tPerform a tab expansion (replace each tab with enough number\n>  \tof spaces to fill to the next display column that is\n>  \tmultiple of 8) in the log message before using the message\n>  \tto show in the output.\n> ++\n> +By default, tabs are expanded in pretty formats that indent the log\n> +message by 4 spaces (i.e.  'medium', which is the default, 'full',\n> +and \"fuller').  `--no-expand-tabs` option can be used to disable\n> +this.\n\nMismatched quote types on \"fuller\".\n\n> @@ -172,6 +173,7 @@ void get_commit_format(const char *arg, struct rev_info *rev)\n>  \n>  \trev->commit_format = commit_format->format;\n>  \trev->use_terminator = commit_format->is_tformat;\n> +\trev->expand_tabs_in_log = commit_format->expand_tabs_in_log;\n>  \tif (commit_format->format == CMIT_FMT_USERFORMAT) {\n>  \t\tsave_user_format(rev, commit_format->user_format,\n>  \t\t\t\t commit_format->is_tformat);\n\nThis feels like the wrong time to set the value in rev_info, as it means\nthat:\n\n  git log --no-expand-tabs --pretty=full\n\nand\n\n  git log --pretty=full --no-expand-tabs\n\nbehave differently. The other values set in get_commit_format, like\n\"use_terminator\", are inherently part of the format, but I don't think\nthis is. We just want to set the default if the user did not express\nanother preference.\n\nLikewise, if we were to eventually add config like \"[log]expandtab = 4\",\nit should not be overridden by \"--pretty=full\" (but we probably _would_\nwant to have it kick in only for certain formats).\n\nSo I think we really want to set an alternate variable here, and then do\nsomething like:\n\n  if (rev->expand_tabs_in_log < 0)\n\trev->expand_tabs_in_log = rev->commit_format_expand_tab_default;\n\n-Peff\n"},{"id":"282258","messageId":"xmqq7fgju8tl.fsf@gitster.mtv.corp.google.com","threadId":"41709","inReplyTo":"CAPig+cTd_VRnikMzN7b2qfeG87M0v-4_qM42MkhOcRT54Wmv=Q@mail.gmail.com","subject":"Re: [PATCH v4 1/3] pretty: expand tabs in indented logs to make things line up properly","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-30T18:20:06Z","receivedAt":"2016-03-30T18:20:06Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Eric Sunshine <sunshine@sunshineco.com> writes:\n\n> On Tue, Mar 29, 2016 at 7:15 PM, Junio C Hamano <gitster@pobox.com> wrote:\n>> From: Linus Torvalds <torvalds@linux-foundation.org>\n>>\n>> A commit log message sometimes tries to line things up using tabs,\n>> assuming fixed-width font with the standard 8-place tab settings.\n>> Viewing such a commit however does not work well in \"git log\", as\n>> we indent the lines by prefixing 4 spaces in front of them.\n>> [...]\n>> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>\n>> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n>> ---\n>> diff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt\n>> @@ -42,6 +42,12 @@ people using 80-column terminals.\n>> +--expand-tabs::\n>> +       Perform a tab expansion (replace each tab with enough number\n>> +       of spaces to fill to the next display column that is\n>\n> Nit: \"enough spaces\" or \"a sufficient number of spaces\".\n\nThanks, will be part of a reroll (when it happens ;-).\n"},{"id":"282261","messageId":"xmqq37r7u64f.fsf@gitster.mtv.corp.google.com","threadId":"41709","inReplyTo":"20160330013851.GF2237@sigill.intra.peff.net","subject":"Re: [PATCH v4 2/3] pretty: enable --expand-tabs by default for selected pretty formats","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-30T19:18:24Z","receivedAt":"2016-03-30T19:18:24Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> On Tue, Mar 29, 2016 at 04:15:08PM -0700, Junio C Hamano wrote:\n>\n>> diff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt\n>> index 4fb5c76..23967b6 100644\n>> --- a/Documentation/pretty-options.txt\n>> +++ b/Documentation/pretty-options.txt\n>> @@ -43,10 +43,16 @@ people using 80-column terminals.\n>>  \tcommit may be copied to the output.\n>>  \n>>  --expand-tabs::\n>> +--no-expand-tabs::\n>>  \tPerform a tab expansion (replace each tab with enough number\n>>  \tof spaces to fill to the next display column that is\n>>  \tmultiple of 8) in the log message before using the message\n>>  \tto show in the output.\n>> ++\n>> +By default, tabs are expanded in pretty formats that indent the log\n>> +message by 4 spaces (i.e.  'medium', which is the default, 'full',\n>> +and \"fuller').  `--no-expand-tabs` option can be used to disable\n>> +this.\n>\n> Mismatched quote types on \"fuller\".\n\nThanks.\n\n>> @@ -172,6 +173,7 @@ void get_commit_format(const char *arg, struct rev_info *rev)\n>>  \n>>  \trev->commit_format = commit_format->format;\n>>  \trev->use_terminator = commit_format->is_tformat;\n>> +\trev->expand_tabs_in_log = commit_format->expand_tabs_in_log;\n>>  \tif (commit_format->format == CMIT_FMT_USERFORMAT) {\n>>  \t\tsave_user_format(rev, commit_format->user_format,\n>>  \t\t\t\t commit_format->is_tformat);\n>\n> This feels like the wrong time to set the value in rev_info, as it means\n> that:\n>\n>   git log --no-expand-tabs --pretty=full\n>\n> and\n>\n>   git log --pretty=full --no-expand-tabs\n>\n> behave differently.\n\nI was sort of hoping that we can get away by defining that \"an\nexplicit --pretty asks for the full behaviour of the format it\nspecifies, e.g. if you ask --pretty=medium, you are asking for\n4-space indented tab-expanded log with the headers at the medium\nlevel of detail\".\n\n> The other values set in get_commit_format, like \"use_terminator\",\n> are inherently part of the format, but I don't think this is.\n\nIOW, I was hoping nobody would agree with that and rather everybody\nwould consider tab-expansion is part of the format.\n\nLet me try your way instead and report how it went when I send out a\nreroll.\n\n> Likewise, if we were to eventually add config like \"[log]expandtab = 4\",\n> it should not be overridden by \"--pretty=full\" (but we probably _would_\n> want to have it kick in only for certain formats).\n\nThis is exactly why I didn't do a configuration variable, as I think\nwe can make only 50% of people happy.  Some would say \"when I\nexplicitly ask for the \"email\" format, I expect that expandtab\nconfiguration gets ignored\" while others would say \"I said I want\nexpandtab in the configuration no matter what\".\n"},{"id":"282663","messageId":"1459817917-32078-1-git-send-email-gitster@pobox.com","threadId":"41709","inReplyTo":"1459293309-25195-1-git-send-email-gitster@pobox.com","subject":"[PATCH v5 0/4] Expanding tabs in \"git log\" output","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-04-05T00:58:33Z","receivedAt":"2016-04-05T00:58:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"So here is the fifth and hopefully the final try.  Previous round\nare at $gmane/289694, $gmane/289166, $gmane/288987 and\n$gmane/290222.\n\nThis round is different from v4 in the following ways.\n\n * wording changes, grammo- and typo-fixes in the documentation\n   (thanks to Eric Sunshine and Jeff King).\n\n * v4 made --pretty=$fmt to override an earlier --expand-tabs=<n>;\n   this round only allows --pretty=$fmt to set the default behaviour\n   when an explicit --expand-tabs=<n> is given on the command line\n   (thanks to Jeff King).\n   \n * comes with a test.\n\nSee the end of this cover letter for an interdiff.\n\nJunio C Hamano (3):\n  pretty: enable --expand-tabs by default for selected pretty formats\n  pretty: allow tweaking tabwidth in --expand-tabs\n  pretty: test --expand-tabs\n\nLinus Torvalds (1):\n  pretty: expand tabs in indented logs to make things line up properly\n\n Documentation/pretty-options.txt | 14 ++++++\n builtin/log.c                    |  1 +\n commit.h                         |  1 +\n log-tree.c                       |  1 +\n pretty.c                         | 90 ++++++++++++++++++++++++++++++++----\n revision.c                       | 14 ++++++\n revision.h                       |  2 +\n t/t4201-shortlog.sh              |  2 +-\n t/t4213-log-tabexpand.sh         | 98 ++++++++++++++++++++++++++++++++++++++++\n 9 files changed, 213 insertions(+), 10 deletions(-)\n create mode 100755 t/t4213-log-tabexpand.sh\n\n-- \n2.8.1-251-g9997610\n\n\ndiff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt\nindex 8a944b1..93ad1cd 100644\n--- a/Documentation/pretty-options.txt\n+++ b/Documentation/pretty-options.txt\n@@ -45,16 +45,16 @@ people using 80-column terminals.\n --expand-tabs=<n>::\n --expand-tabs::\n --no-expand-tabs::\n-\tPerform a tab expansion (replace each tab with enough number\n-\tof spaces to fill to the next display column that is\n-\tmultiple of '<n>') in the log message before using the message\n-\tto show in the output.  `--expand-tabs` is a short-hand for\n-\t`--expand-tabs=8`, and `--no-expand-tabs` is a short-hand for\n-\t`--expand-tabs=0`, which disables tab expansion.\n+\tPerform a tab expansion (replace each tab with enough spaces\n+\tto fill to the next display column that is multiple of '<n>')\n+\tin the log message before showing it in the output.\n+\t`--expand-tabs` is a short-hand for `--expand-tabs=8`, and\n+\t`--no-expand-tabs` is a short-hand for `--expand-tabs=0`,\n+\twhich disables tab expansion.\n +\n By default, tabs are expanded in pretty formats that indent the log\n message by 4 spaces (i.e.  'medium', which is the default, 'full',\n-and \"fuller').\n+and 'fuller').\n \n ifndef::git-rev-list[]\n --notes[=<ref>]::\ndiff --git a/builtin/log.c b/builtin/log.c\nindex e00cea7..e5775ae 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -1281,6 +1281,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \tgit_config(git_format_config, NULL);\n \tinit_revisions(&rev, prefix);\n \trev.commit_format = CMIT_FMT_EMAIL;\n+\trev.expand_tabs_in_log_default = 0;\n \trev.verbose_header = 1;\n \trev.diff = 1;\n \trev.max_parents = 1;\ndiff --git a/commit.h b/commit.h\nindex 2185c8d..b06db4d 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -147,7 +147,7 @@ struct pretty_print_context {\n \tint preserve_subject;\n \tstruct date_mode date_mode;\n \tunsigned date_mode_explicit:1;\n-\tunsigned expand_tabs_in_log;\n+\tint expand_tabs_in_log;\n \tint need_8bit_cte;\n \tchar *notes_message;\n \tstruct reflog_walk_info *reflog_info;\ndiff --git a/pretty.c b/pretty.c\nindex b340ecd..87c4497 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -173,7 +173,7 @@ void get_commit_format(const char *arg, struct rev_info *rev)\n \n \trev->commit_format = commit_format->format;\n \trev->use_terminator = commit_format->is_tformat;\n-\trev->expand_tabs_in_log = commit_format->expand_tabs_in_log;\n+\trev->expand_tabs_in_log_default = commit_format->expand_tabs_in_log;\n \tif (commit_format->format == CMIT_FMT_USERFORMAT) {\n \t\tsave_user_format(rev, commit_format->user_format,\n \t\t\t\t commit_format->is_tformat);\n@@ -1722,6 +1722,9 @@ void pp_remainder(struct pretty_print_context *pp,\n \t\tstrbuf_grow(sb, linelen + indent + 20);\n \t\tif (indent)\n \t\t\tpp_handle_indent(pp, sb, indent, line, linelen);\n+\t\telse if (pp->expand_tabs_in_log)\n+\t\t\tstrbuf_add_tabexpand(sb, pp->expand_tabs_in_log,\n+\t\t\t\t\t     line, linelen);\n \t\telse\n \t\t\tstrbuf_add(sb, line, linelen);\n \t\tstrbuf_addch(sb, '\\n');\ndiff --git a/revision.c b/revision.c\nindex 4f9ecbe..47e9ee7 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1412,9 +1412,10 @@ void init_revisions(struct rev_info *revs, const char *prefix)\n \trevs->skip_count = -1;\n \trevs->max_count = -1;\n \trevs->max_parents = -1;\n-\trevs->expand_tabs_in_log = 8;\n+\trevs->expand_tabs_in_log = -1;\n \n \trevs->commit_format = CMIT_FMT_DEFAULT;\n+\trevs->expand_tabs_in_log_default = 8;\n \n \tinit_grep_defaults();\n \tgrep_init(&revs->grep_filter, prefix);\n@@ -2398,6 +2399,9 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s\n \tif (revs->first_parent_only && revs->bisect)\n \t\tdie(_(\"--first-parent is incompatible with --bisect\"));\n \n+\tif (revs->expand_tabs_in_log < 0)\n+\t\trevs->expand_tabs_in_log = revs->expand_tabs_in_log_default;\n+\n \treturn left;\n }\n \ndiff --git a/revision.h b/revision.h\nindex cf6615a..6cc36b4 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -148,7 +148,9 @@ struct rev_info {\n \t\t\tlinear:1;\n \n \tstruct date_mode date_mode;\n-\tunsigned int\texpand_tabs_in_log;\n+\tint\t\texpand_tabs_in_log; /* unset if negative */\n+\tint\t\texpand_tabs_in_log_default;\n+\n \tunsigned int\tabbrev;\n \tenum cmit_fmt\tcommit_format;\n \tstruct log_info *loginfo;\ndiff --git a/t/t4213-log-tabexpand.sh b/t/t4213-log-tabexpand.sh\nnew file mode 100755\nindex 0000000..74ca03a\n--- /dev/null\n+++ b/t/t4213-log-tabexpand.sh\n@@ -0,0 +1,98 @@\n+#!/bin/sh\n+\n+test_description='log/show --expand-tabs'\n+\n+. ./test-lib.sh\n+\n+HT=\"\t\"\n+title='tab indent at the beginning of the title line'\n+body='tab indent on a line in the body'\n+\n+count_expand ()\n+{\n+\tcase \" $* \" in\n+\t*' --pretty=short '*)\n+\t\tline=$title ;;\n+\t*)\n+\t\tline=$body ;;\n+\tesac\n+\texpect=\n+\tcount=$(( $1 + $2 )) ;# expected spaces\n+\twhile test $count -gt 0\n+\tdo\n+\t\texpect=\"$expect \"\n+\t\tcount=$(( $count - 1 ))\n+\tdone\n+\tshift 2\n+\tcount=$1 ;# expected tabs\n+\twhile test $count -gt 0\n+\tdo\n+\t\texpect=\"$expect$HT\"\n+\t\tcount=$(( $count - 1 ))\n+\tdone\n+\tshift\n+\t{\n+\t\techo \"git show -s $*\"\n+\t\techo \"$expect$line\"\n+\t} | sed -e 's/ /./g' >expect\n+\n+\t{\n+\t\techo \"git show -s $*\"\n+\t\tgit show -s \"$@\" |\n+\t\tsed -n -e \"/$line\\$/p\"\n+\t} | sed -e 's/ /./g' >actual\n+\n+\ttest_cmp expect actual\n+}\n+\n+test_expand ()\n+{\n+\tfmt=$1\n+\tcase \"$fmt\" in\n+\t*=raw | *=short | *=email)\n+\t\tdefault=\"0 1\" ;;\n+\t*)\n+\t\tdefault=\"8 0\" ;;\n+\tesac\n+\tcase \"$fmt\" in\n+\t*=email)\n+\t\tin=0 ;;\n+\t*)\n+\t\tin=4 ;;\n+\tesac\n+\ttest_expect_success \"expand/no-expand${fmt:+ for $fmt}\" '\n+\t\tcount_expand $in $default $fmt &&\n+\t\tcount_expand $in 8 0 $fmt --expand-tabs &&\n+\t\tcount_expand $in 8 0 --expand-tabs $fmt &&\n+\t\tcount_expand $in 8 0 $fmt --expand-tabs=8 &&\n+\t\tcount_expand $in 8 0 --expand-tabs=8 $fmt &&\n+\t\tcount_expand $in 0 1 $fmt --no-expand-tabs &&\n+\t\tcount_expand $in 0 1 --no-expand-tabs $fmt &&\n+\t\tcount_expand $in 0 1 $fmt --expand-tabs=0 &&\n+\t\tcount_expand $in 0 1 --expand-tabs=0 $fmt &&\n+\t\tcount_expand $in 4 0 $fmt --expand-tabs=4 &&\n+\t\tcount_expand $in 4 0 --expand-tabs=4 $fmt\n+\t'\n+}\n+\n+test_expect_success 'setup' '\n+\ttest_tick &&\n+\tsed -e \"s/Q/$HT/g\" <<-EOF >msg &&\n+\tQ$title\n+\n+\tQ$body\n+\tEOF\n+\tgit commit --allow-empty -F msg\n+'\n+\n+test_expand \"\"\n+test_expand --pretty\n+test_expand --pretty=short\n+test_expand --pretty=medium\n+test_expand --pretty=full\n+test_expand --pretty=fuller\n+test_expand --pretty=fuller\n+test_expand --pretty=raw\n+test_expand --pretty=email\n+\n+test_done\n"},{"id":"282664","messageId":"1459817917-32078-2-git-send-email-gitster@pobox.com","threadId":"41709","inReplyTo":"1459817917-32078-1-git-send-email-gitster@pobox.com","subject":"[PATCH v5 1/4] pretty: expand tabs in indented logs to make things line up properly","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-04-05T00:58:34Z","receivedAt":"2016-04-05T00:58:34Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"From: Linus Torvalds <torvalds@linux-foundation.org>\n\nA commit log message sometimes tries to line things up using tabs,\nassuming fixed-width font with the standard 8-place tab settings.\nViewing such a commit however does not work well in \"git log\", as\nwe indent the lines by prefixing 4 spaces in front of them.\n\nThis should all line up:\n\n  Column 1\tColumn 2\n  --------\t--------\n  A\t\tB\n  ABCD\t\tEFGH\n  SPACES        Instead of Tabs\n\nEven with multi-byte UTF8 characters:\n\n  Column 1\tColumn 2\n  --------\t--------\n  Ä\t\tB\n  åäö\t\t100\n  A Møøse\tonce bit my sister..\n\nTab-expand the lines in \"git log --expand-tabs\" output before\nprefixing 4 spaces.\n\nThis is based on the patch by Linus Torvalds, but at this step, we\nrequire an explicit command line option to enable the behaviour.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n Documentation/pretty-options.txt |  5 +++\n commit.h                         |  1 +\n log-tree.c                       |  1 +\n pretty.c                         | 71 ++++++++++++++++++++++++++++++++++++++--\n revision.c                       |  2 ++\n revision.h                       |  1 +\n 6 files changed, 79 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt\nindex 4b659ac..d820653 100644\n--- a/Documentation/pretty-options.txt\n+++ b/Documentation/pretty-options.txt\n@@ -42,6 +42,11 @@ people using 80-column terminals.\n \tverbatim; this means that invalid sequences in the original\n \tcommit may be copied to the output.\n \n+--expand-tabs::\n+\tPerform a tab expansion (replace each tab with enough spaces\n+\tto fill to the next display column that is multiple of 8)\n+\tin the log message before showing it in the output.\n+\n ifndef::git-rev-list[]\n --notes[=<ref>]::\n \tShow the notes (see linkgit:git-notes[1]) that annotate the\ndiff --git a/commit.h b/commit.h\nindex 5d58be0..a7ef682 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -147,6 +147,7 @@ struct pretty_print_context {\n \tint preserve_subject;\n \tstruct date_mode date_mode;\n \tunsigned date_mode_explicit:1;\n+\tunsigned expand_tabs_in_log:1;\n \tint need_8bit_cte;\n \tchar *notes_message;\n \tstruct reflog_walk_info *reflog_info;\ndiff --git a/log-tree.c b/log-tree.c\nindex 60f9839..78a5381 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -683,6 +683,7 @@ void show_log(struct rev_info *opt)\n \tctx.fmt = opt->commit_format;\n \tctx.mailmap = opt->mailmap;\n \tctx.color = opt->diffopt.use_color;\n+\tctx.expand_tabs_in_log = opt->expand_tabs_in_log;\n \tctx.output_encoding = get_log_output_encoding();\n \tif (opt->from_ident.mail_begin && opt->from_ident.name_begin)\n \t\tctx.from_ident = &opt->from_ident;\ndiff --git a/pretty.c b/pretty.c\nindex 92b2870..c8b075d 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -1629,6 +1629,72 @@ void pp_title_line(struct pretty_print_context *pp,\n \tstrbuf_release(&title);\n }\n \n+static int pp_utf8_width(const char *start, const char *end)\n+{\n+\tint width = 0;\n+\tsize_t remain = end - start;\n+\n+\twhile (remain) {\n+\t\tint n = utf8_width(&start, &remain);\n+\t\tif (n < 0 || !start)\n+\t\t\treturn -1;\n+\t\twidth += n;\n+\t}\n+\treturn width;\n+}\n+\n+static void strbuf_add_tabexpand(struct strbuf *sb,\n+\t\t\t\t const char *line, int linelen)\n+{\n+\tconst char *tab;\n+\n+\twhile ((tab = memchr(line, '\\t', linelen)) != NULL) {\n+\t\tint width = pp_utf8_width(line, tab);\n+\n+\t\t/*\n+\t\t * If it wasn't well-formed utf8, or it\n+\t\t * had characters with badly defined\n+\t\t * width (control characters etc), just\n+\t\t * give up on trying to align things.\n+\t\t */\n+\t\tif (width < 0)\n+\t\t\tbreak;\n+\n+\t\t/* Output the data .. */\n+\t\tstrbuf_add(sb, line, tab - line);\n+\n+\t\t/* .. and the de-tabified tab */\n+\t\tstrbuf_addchars(sb, ' ', 8 - (width % 8));\n+\n+\t\t/* Skip over the printed part .. */\n+\t\tlinelen -= tab + 1 - line;\n+\t\tline = tab + 1;\n+\t}\n+\n+\t/*\n+\t * Print out everything after the last tab without\n+\t * worrying about width - there's nothing more to\n+\t * align.\n+\t */\n+\tstrbuf_add(sb, line, linelen);\n+}\n+\n+/*\n+ * pp_handle_indent() prints out the intendation, and\n+ * the whole line (without the final newline), after\n+ * de-tabifying.\n+ */\n+static void pp_handle_indent(struct pretty_print_context *pp,\n+\t\t\t     struct strbuf *sb, int indent,\n+\t\t\t     const char *line, int linelen)\n+{\n+\tstrbuf_addchars(sb, ' ', indent);\n+\tif (pp->expand_tabs_in_log)\n+\t\tstrbuf_add_tabexpand(sb, line, linelen);\n+\telse\n+\t\tstrbuf_add(sb, line, linelen);\n+}\n+\n void pp_remainder(struct pretty_print_context *pp,\n \t\t  const char **msg_p,\n \t\t  struct strbuf *sb,\n@@ -1653,8 +1719,9 @@ void pp_remainder(struct pretty_print_context *pp,\n \n \t\tstrbuf_grow(sb, linelen + indent + 20);\n \t\tif (indent)\n-\t\t\tstrbuf_addchars(sb, ' ', indent);\n-\t\tstrbuf_add(sb, line, linelen);\n+\t\t\tpp_handle_indent(pp, sb, indent, line, linelen);\n+\t\telse\n+\t\t\tstrbuf_add(sb, line, linelen);\n \t\tstrbuf_addch(sb, '\\n');\n \t}\n }\ndiff --git a/revision.c b/revision.c\nindex df56fce..e662230 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1915,6 +1915,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\trevs->verbose_header = 1;\n \t\trevs->pretty_given = 1;\n \t\tget_commit_format(arg+9, revs);\n+\t} else if (!strcmp(arg, \"--expand-tabs\")) {\n+\t\trevs->expand_tabs_in_log = 1;\n \t} else if (!strcmp(arg, \"--show-notes\") || !strcmp(arg, \"--notes\")) {\n \t\trevs->show_notes = 1;\n \t\trevs->show_notes_given = 1;\ndiff --git a/revision.h b/revision.h\nindex 23857c0..4079753 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -133,6 +133,7 @@ struct rev_info {\n \t\t\tshow_notes_given:1,\n \t\t\tshow_signature:1,\n \t\t\tpretty_given:1,\n+\t\t\texpand_tabs_in_log:1,\n \t\t\tabbrev_commit:1,\n \t\t\tabbrev_commit_given:1,\n \t\t\tzero_commit:1,\n-- \n2.8.1-251-g9997610\n"},{"id":"282665","messageId":"1459817917-32078-3-git-send-email-gitster@pobox.com","threadId":"41709","inReplyTo":"1459817917-32078-1-git-send-email-gitster@pobox.com","subject":"[PATCH v5 2/4] pretty: enable --expand-tabs by default for selected pretty formats","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-04-05T00:58:35Z","receivedAt":"2016-04-05T00:58:35Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"git log --pretty={medium,full,fuller}\" and \"git log\" by default\nprepend 4 spaces to the log message, so it makes sense to enable\nthe new \"expand-tabs\" facility by default for these formats.\nAdd --no-expand-tabs option to override the new default.\n\nThe change alone breaks a test in t4201 that runs \"git shortlog\"\non the output from \"git log\", and expects that the output from\n\"git log\" does not do such a tab expansion.  Adjust the test to\nexplicitly disable expand-tabs with --no-expand-tabs.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n Documentation/pretty-options.txt |  6 ++++++\n builtin/log.c                    |  1 +\n pretty.c                         | 18 +++++++++++-------\n revision.c                       |  7 +++++++\n revision.h                       |  3 ++-\n t/t4201-shortlog.sh              |  2 +-\n 6 files changed, 28 insertions(+), 9 deletions(-)\n\ndiff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt\nindex d820653..edbb02f 100644\n--- a/Documentation/pretty-options.txt\n+++ b/Documentation/pretty-options.txt\n@@ -43,9 +43,15 @@ people using 80-column terminals.\n \tcommit may be copied to the output.\n \n --expand-tabs::\n+--no-expand-tabs::\n \tPerform a tab expansion (replace each tab with enough spaces\n \tto fill to the next display column that is multiple of 8)\n \tin the log message before showing it in the output.\n++\n+By default, tabs are expanded in pretty formats that indent the log\n+message by 4 spaces (i.e.  'medium', which is the default, 'full',\n+and 'fuller').  `--no-expand-tabs` option can be used to disable\n+this.\n \n ifndef::git-rev-list[]\n --notes[=<ref>]::\ndiff --git a/builtin/log.c b/builtin/log.c\nindex e00cea7..e5775ae 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -1281,6 +1281,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \tgit_config(git_format_config, NULL);\n \tinit_revisions(&rev, prefix);\n \trev.commit_format = CMIT_FMT_EMAIL;\n+\trev.expand_tabs_in_log_default = 0;\n \trev.verbose_header = 1;\n \trev.diff = 1;\n \trev.max_parents = 1;\ndiff --git a/pretty.c b/pretty.c\nindex c8b075d..b7938e0 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -16,6 +16,7 @@ static struct cmt_fmt_map {\n \tconst char *name;\n \tenum cmit_fmt format;\n \tint is_tformat;\n+\tint expand_tabs_in_log;\n \tint is_alias;\n \tconst char *user_format;\n } *commit_formats;\n@@ -87,13 +88,13 @@ static int git_pretty_formats_config(const char *var, const char *value, void *c\n static void setup_commit_formats(void)\n {\n \tstruct cmt_fmt_map builtin_formats[] = {\n-\t\t{ \"raw\",\tCMIT_FMT_RAW,\t\t0 },\n-\t\t{ \"medium\",\tCMIT_FMT_MEDIUM,\t0 },\n-\t\t{ \"short\",\tCMIT_FMT_SHORT,\t\t0 },\n-\t\t{ \"email\",\tCMIT_FMT_EMAIL,\t\t0 },\n-\t\t{ \"fuller\",\tCMIT_FMT_FULLER,\t0 },\n-\t\t{ \"full\",\tCMIT_FMT_FULL,\t\t0 },\n-\t\t{ \"oneline\",\tCMIT_FMT_ONELINE,\t1 }\n+\t\t{ \"raw\",\tCMIT_FMT_RAW,\t\t0,\t0 },\n+\t\t{ \"medium\",\tCMIT_FMT_MEDIUM,\t0,\t1 },\n+\t\t{ \"short\",\tCMIT_FMT_SHORT,\t\t0,\t0 },\n+\t\t{ \"email\",\tCMIT_FMT_EMAIL,\t\t0,\t0 },\n+\t\t{ \"fuller\",\tCMIT_FMT_FULLER,\t0,\t1 },\n+\t\t{ \"full\",\tCMIT_FMT_FULL,\t\t0,\t1 },\n+\t\t{ \"oneline\",\tCMIT_FMT_ONELINE,\t1,\t0 }\n \t};\n \tcommit_formats_len = ARRAY_SIZE(builtin_formats);\n \tbuiltin_formats_len = commit_formats_len;\n@@ -172,6 +173,7 @@ void get_commit_format(const char *arg, struct rev_info *rev)\n \n \trev->commit_format = commit_format->format;\n \trev->use_terminator = commit_format->is_tformat;\n+\trev->expand_tabs_in_log_default = commit_format->expand_tabs_in_log;\n \tif (commit_format->format == CMIT_FMT_USERFORMAT) {\n \t\tsave_user_format(rev, commit_format->user_format,\n \t\t\t\t commit_format->is_tformat);\n@@ -1720,6 +1722,8 @@ void pp_remainder(struct pretty_print_context *pp,\n \t\tstrbuf_grow(sb, linelen + indent + 20);\n \t\tif (indent)\n \t\t\tpp_handle_indent(pp, sb, indent, line, linelen);\n+\t\telse if (pp->expand_tabs_in_log)\n+\t\t\tstrbuf_add_tabexpand(sb, line, linelen);\n \t\telse\n \t\t\tstrbuf_add(sb, line, linelen);\n \t\tstrbuf_addch(sb, '\\n');\ndiff --git a/revision.c b/revision.c\nindex e662230..da53b6c 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1412,8 +1412,10 @@ void init_revisions(struct rev_info *revs, const char *prefix)\n \trevs->skip_count = -1;\n \trevs->max_count = -1;\n \trevs->max_parents = -1;\n+\trevs->expand_tabs_in_log = -1;\n \n \trevs->commit_format = CMIT_FMT_DEFAULT;\n+\trevs->expand_tabs_in_log_default = 1;\n \n \tinit_grep_defaults();\n \tgrep_init(&revs->grep_filter, prefix);\n@@ -1917,6 +1919,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\tget_commit_format(arg+9, revs);\n \t} else if (!strcmp(arg, \"--expand-tabs\")) {\n \t\trevs->expand_tabs_in_log = 1;\n+\t} else if (!strcmp(arg, \"--no-expand-tabs\")) {\n+\t\trevs->expand_tabs_in_log = 0;\n \t} else if (!strcmp(arg, \"--show-notes\") || !strcmp(arg, \"--notes\")) {\n \t\trevs->show_notes = 1;\n \t\trevs->show_notes_given = 1;\n@@ -2390,6 +2394,9 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s\n \tif (revs->first_parent_only && revs->bisect)\n \t\tdie(_(\"--first-parent is incompatible with --bisect\"));\n \n+\tif (revs->expand_tabs_in_log < 0)\n+\t\trevs->expand_tabs_in_log = revs->expand_tabs_in_log_default;\n+\n \treturn left;\n }\n \ndiff --git a/revision.h b/revision.h\nindex 4079753..6cc36b4 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -133,7 +133,6 @@ struct rev_info {\n \t\t\tshow_notes_given:1,\n \t\t\tshow_signature:1,\n \t\t\tpretty_given:1,\n-\t\t\texpand_tabs_in_log:1,\n \t\t\tabbrev_commit:1,\n \t\t\tabbrev_commit_given:1,\n \t\t\tzero_commit:1,\n@@ -149,6 +148,8 @@ struct rev_info {\n \t\t\tlinear:1;\n \n \tstruct date_mode date_mode;\n+\tint\t\texpand_tabs_in_log; /* unset if negative */\n+\tint\t\texpand_tabs_in_log_default;\n \n \tunsigned int\tabbrev;\n \tenum cmit_fmt\tcommit_format;\ndiff --git a/t/t4201-shortlog.sh b/t/t4201-shortlog.sh\nindex 7600a3e..2fec948 100755\n--- a/t/t4201-shortlog.sh\n+++ b/t/t4201-shortlog.sh\n@@ -115,7 +115,7 @@ EOF\n '\n \n test_expect_success !MINGW 'shortlog from non-git directory' '\n-\tgit log HEAD >log &&\n+\tgit log --no-expand-tabs HEAD >log &&\n \tGIT_DIR=non-existing git shortlog -w <log >out &&\n \ttest_cmp expect out\n '\n-- \n2.8.1-251-g9997610\n"},{"id":"282667","messageId":"1459817917-32078-4-git-send-email-gitster@pobox.com","threadId":"41709","inReplyTo":"1459817917-32078-1-git-send-email-gitster@pobox.com","subject":"[PATCH v5 3/4] pretty: allow tweaking tabwidth in --expand-tabs","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-04-05T00:58:36Z","receivedAt":"2016-04-05T00:58:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"When the local convention of the project is to use tab width that is\nnot 8, it may make sense to allow \"git log --expand-tabs=<n>\" to\ntweak the output to match it.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n Documentation/pretty-options.txt |  9 ++++++---\n commit.h                         |  2 +-\n pretty.c                         | 15 ++++++++-------\n revision.c                       |  9 +++++++--\n 4 files changed, 22 insertions(+), 13 deletions(-)\n\ndiff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt\nindex edbb02f..93ad1cd 100644\n--- a/Documentation/pretty-options.txt\n+++ b/Documentation/pretty-options.txt\n@@ -42,16 +42,19 @@ people using 80-column terminals.\n \tverbatim; this means that invalid sequences in the original\n \tcommit may be copied to the output.\n \n+--expand-tabs=<n>::\n --expand-tabs::\n --no-expand-tabs::\n \tPerform a tab expansion (replace each tab with enough spaces\n-\tto fill to the next display column that is multiple of 8)\n+\tto fill to the next display column that is multiple of '<n>')\n \tin the log message before showing it in the output.\n+\t`--expand-tabs` is a short-hand for `--expand-tabs=8`, and\n+\t`--no-expand-tabs` is a short-hand for `--expand-tabs=0`,\n+\twhich disables tab expansion.\n +\n By default, tabs are expanded in pretty formats that indent the log\n message by 4 spaces (i.e.  'medium', which is the default, 'full',\n-and 'fuller').  `--no-expand-tabs` option can be used to disable\n-this.\n+and 'fuller').\n \n ifndef::git-rev-list[]\n --notes[=<ref>]::\ndiff --git a/commit.h b/commit.h\nindex a7ef682..b06db4d 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -147,7 +147,7 @@ struct pretty_print_context {\n \tint preserve_subject;\n \tstruct date_mode date_mode;\n \tunsigned date_mode_explicit:1;\n-\tunsigned expand_tabs_in_log:1;\n+\tint expand_tabs_in_log;\n \tint need_8bit_cte;\n \tchar *notes_message;\n \tstruct reflog_walk_info *reflog_info;\ndiff --git a/pretty.c b/pretty.c\nindex b7938e0..87c4497 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -89,11 +89,11 @@ static void setup_commit_formats(void)\n {\n \tstruct cmt_fmt_map builtin_formats[] = {\n \t\t{ \"raw\",\tCMIT_FMT_RAW,\t\t0,\t0 },\n-\t\t{ \"medium\",\tCMIT_FMT_MEDIUM,\t0,\t1 },\n+\t\t{ \"medium\",\tCMIT_FMT_MEDIUM,\t0,\t8 },\n \t\t{ \"short\",\tCMIT_FMT_SHORT,\t\t0,\t0 },\n \t\t{ \"email\",\tCMIT_FMT_EMAIL,\t\t0,\t0 },\n-\t\t{ \"fuller\",\tCMIT_FMT_FULLER,\t0,\t1 },\n-\t\t{ \"full\",\tCMIT_FMT_FULL,\t\t0,\t1 },\n+\t\t{ \"fuller\",\tCMIT_FMT_FULLER,\t0,\t8 },\n+\t\t{ \"full\",\tCMIT_FMT_FULL,\t\t0,\t8 },\n \t\t{ \"oneline\",\tCMIT_FMT_ONELINE,\t1,\t0 }\n \t};\n \tcommit_formats_len = ARRAY_SIZE(builtin_formats);\n@@ -1645,7 +1645,7 @@ static int pp_utf8_width(const char *start, const char *end)\n \treturn width;\n }\n \n-static void strbuf_add_tabexpand(struct strbuf *sb,\n+static void strbuf_add_tabexpand(struct strbuf *sb, int tabwidth,\n \t\t\t\t const char *line, int linelen)\n {\n \tconst char *tab;\n@@ -1666,7 +1666,7 @@ static void strbuf_add_tabexpand(struct strbuf *sb,\n \t\tstrbuf_add(sb, line, tab - line);\n \n \t\t/* .. and the de-tabified tab */\n-\t\tstrbuf_addchars(sb, ' ', 8 - (width % 8));\n+\t\tstrbuf_addchars(sb, ' ', tabwidth - (width % tabwidth));\n \n \t\t/* Skip over the printed part .. */\n \t\tlinelen -= tab + 1 - line;\n@@ -1692,7 +1692,7 @@ static void pp_handle_indent(struct pretty_print_context *pp,\n {\n \tstrbuf_addchars(sb, ' ', indent);\n \tif (pp->expand_tabs_in_log)\n-\t\tstrbuf_add_tabexpand(sb, line, linelen);\n+\t\tstrbuf_add_tabexpand(sb, pp->expand_tabs_in_log, line, linelen);\n \telse\n \t\tstrbuf_add(sb, line, linelen);\n }\n@@ -1723,7 +1723,8 @@ void pp_remainder(struct pretty_print_context *pp,\n \t\tif (indent)\n \t\t\tpp_handle_indent(pp, sb, indent, line, linelen);\n \t\telse if (pp->expand_tabs_in_log)\n-\t\t\tstrbuf_add_tabexpand(sb, line, linelen);\n+\t\t\tstrbuf_add_tabexpand(sb, pp->expand_tabs_in_log,\n+\t\t\t\t\t     line, linelen);\n \t\telse\n \t\t\tstrbuf_add(sb, line, linelen);\n \t\tstrbuf_addch(sb, '\\n');\ndiff --git a/revision.c b/revision.c\nindex da53b6c..47e9ee7 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1415,7 +1415,7 @@ void init_revisions(struct rev_info *revs, const char *prefix)\n \trevs->expand_tabs_in_log = -1;\n \n \trevs->commit_format = CMIT_FMT_DEFAULT;\n-\trevs->expand_tabs_in_log_default = 1;\n+\trevs->expand_tabs_in_log_default = 8;\n \n \tinit_grep_defaults();\n \tgrep_init(&revs->grep_filter, prefix);\n@@ -1918,9 +1918,14 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\trevs->pretty_given = 1;\n \t\tget_commit_format(arg+9, revs);\n \t} else if (!strcmp(arg, \"--expand-tabs\")) {\n-\t\trevs->expand_tabs_in_log = 1;\n+\t\trevs->expand_tabs_in_log = 8;\n \t} else if (!strcmp(arg, \"--no-expand-tabs\")) {\n \t\trevs->expand_tabs_in_log = 0;\n+\t} else if (skip_prefix(arg, \"--expand-tabs=\", &arg)) {\n+\t\tint val;\n+\t\tif (strtol_i(arg, 10, &val) < 0 || val < 0)\n+\t\t\tdie(\"'%s': not a non-negative integer\", arg);\n+\t\trevs->expand_tabs_in_log = val;\n \t} else if (!strcmp(arg, \"--show-notes\") || !strcmp(arg, \"--notes\")) {\n \t\trevs->show_notes = 1;\n \t\trevs->show_notes_given = 1;\n-- \n2.8.1-251-g9997610\n"},{"id":"282666","messageId":"1459817917-32078-5-git-send-email-gitster@pobox.com","threadId":"41709","inReplyTo":"1459817917-32078-1-git-send-email-gitster@pobox.com","subject":"[PATCH v5 4/4] pretty: test --expand-tabs","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-04-05T00:58:37Z","receivedAt":"2016-04-05T00:58:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"The test prepares a simple commit with HT on its log message lines,\nand makes sure that\n\n - formats that should or should not expand tabs by default do or do\n   not expand tabs respectively,\n\n - with explicit --expand-tabs=<N> and short-hands --expand-tabs\n   (equivalent to --expand-tabs=8) and --no-expand-tabs (equivalent\n   to --expand-tabs=0) before or after the explicit --pretty=$fmt,\n   the tabs are expanded (or not expanded) accordingly.\n\nThe tests use the second line of the log message for formats other\nthan --pretty=short, primarily because the first line of the email\nformat is handled specially to add the [PATCH] prefix, etc. in a\nseparate codepath (--pretty=short uses the first line because there\nis no other line to test).\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n t/t4213-log-tabexpand.sh | 98 ++++++++++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 98 insertions(+)\n create mode 100755 t/t4213-log-tabexpand.sh\n\ndiff --git a/t/t4213-log-tabexpand.sh b/t/t4213-log-tabexpand.sh\nnew file mode 100755\nindex 0000000..74ca03a\n--- /dev/null\n+++ b/t/t4213-log-tabexpand.sh\n@@ -0,0 +1,98 @@\n+#!/bin/sh\n+\n+test_description='log/show --expand-tabs'\n+\n+. ./test-lib.sh\n+\n+HT=\"\t\"\n+title='tab indent at the beginning of the title line'\n+body='tab indent on a line in the body'\n+\n+count_expand ()\n+{\n+\tcase \" $* \" in\n+\t*' --pretty=short '*)\n+\t\tline=$title ;;\n+\t*)\n+\t\tline=$body ;;\n+\tesac\n+\texpect=\n+\tcount=$(( $1 + $2 )) ;# expected spaces\n+\twhile test $count -gt 0\n+\tdo\n+\t\texpect=\"$expect \"\n+\t\tcount=$(( $count - 1 ))\n+\tdone\n+\tshift 2\n+\tcount=$1 ;# expected tabs\n+\twhile test $count -gt 0\n+\tdo\n+\t\texpect=\"$expect$HT\"\n+\t\tcount=$(( $count - 1 ))\n+\tdone\n+\tshift\n+\t{\n+\t\techo \"git show -s $*\"\n+\t\techo \"$expect$line\"\n+\t} | sed -e 's/ /./g' >expect\n+\n+\t{\n+\t\techo \"git show -s $*\"\n+\t\tgit show -s \"$@\" |\n+\t\tsed -n -e \"/$line\\$/p\"\n+\t} | sed -e 's/ /./g' >actual\n+\n+\ttest_cmp expect actual\n+}\n+\n+test_expand ()\n+{\n+\tfmt=$1\n+\tcase \"$fmt\" in\n+\t*=raw | *=short | *=email)\n+\t\tdefault=\"0 1\" ;;\n+\t*)\n+\t\tdefault=\"8 0\" ;;\n+\tesac\n+\tcase \"$fmt\" in\n+\t*=email)\n+\t\tin=0 ;;\n+\t*)\n+\t\tin=4 ;;\n+\tesac\n+\ttest_expect_success \"expand/no-expand${fmt:+ for $fmt}\" '\n+\t\tcount_expand $in $default $fmt &&\n+\t\tcount_expand $in 8 0 $fmt --expand-tabs &&\n+\t\tcount_expand $in 8 0 --expand-tabs $fmt &&\n+\t\tcount_expand $in 8 0 $fmt --expand-tabs=8 &&\n+\t\tcount_expand $in 8 0 --expand-tabs=8 $fmt &&\n+\t\tcount_expand $in 0 1 $fmt --no-expand-tabs &&\n+\t\tcount_expand $in 0 1 --no-expand-tabs $fmt &&\n+\t\tcount_expand $in 0 1 $fmt --expand-tabs=0 &&\n+\t\tcount_expand $in 0 1 --expand-tabs=0 $fmt &&\n+\t\tcount_expand $in 4 0 $fmt --expand-tabs=4 &&\n+\t\tcount_expand $in 4 0 --expand-tabs=4 $fmt\n+\t'\n+}\n+\n+test_expect_success 'setup' '\n+\ttest_tick &&\n+\tsed -e \"s/Q/$HT/g\" <<-EOF >msg &&\n+\tQ$title\n+\n+\tQ$body\n+\tEOF\n+\tgit commit --allow-empty -F msg\n+'\n+\n+test_expand \"\"\n+test_expand --pretty\n+test_expand --pretty=short\n+test_expand --pretty=medium\n+test_expand --pretty=full\n+test_expand --pretty=fuller\n+test_expand --pretty=fuller\n+test_expand --pretty=raw\n+test_expand --pretty=email\n+\n+test_done\n-- \n2.8.1-251-g9997610\n"},{"id":"282668","messageId":"CAPig+cSTp6R0XNwNAU=QhKOTqB4=uSuPd_mnwfvy6wHs8X7FRg@mail.gmail.com","threadId":"41709","inReplyTo":"1459817917-32078-5-git-send-email-gitster@pobox.com","subject":"Re: [PATCH v5 4/4] pretty: test --expand-tabs","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2016-04-05T01:10:46Z","receivedAt":"2016-04-05T01:10:46Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Mon, Apr 4, 2016 at 8:58 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> The test prepares a simple commit with HT on its log message lines,\n> and makes sure that\n>\n>  - formats that should or should not expand tabs by default do or do\n>    not expand tabs respectively,\n>\n>  - with explicit --expand-tabs=<N> and short-hands --expand-tabs\n>    (equivalent to --expand-tabs=8) and --no-expand-tabs (equivalent\n>    to --expand-tabs=0) before or after the explicit --pretty=$fmt,\n>    the tabs are expanded (or not expanded) accordingly.\n>\n> The tests use the second line of the log message for formats other\n> than --pretty=short, primarily because the first line of the email\n> format is handled specially to add the [PATCH] prefix, etc. in a\n> separate codepath (--pretty=short uses the first line because there\n> is no other line to test).\n>\n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n> diff --git a/t/t4213-log-tabexpand.sh b/t/t4213-log-tabexpand.sh\n> @@ -0,0 +1,98 @@\n> +count_expand ()\n> +{\n> +       case \" $* \" in\n> +       *' --pretty=short '*)\n> +               line=$title ;;\n> +       *)\n> +               line=$body ;;\n> +       esac\n> +       expect=\n> +       count=$(( $1 + $2 )) ;# expected spaces\n> +       while test $count -gt 0\n> +       do\n> +               expect=\"$expect \"\n> +               count=$(( $count - 1 ))\n> +       done\n> +       shift 2\n> +       count=$1 ;# expected tabs\n\nWhy semicolon before the hash here and above?\n"},{"id":"282674","messageId":"20160405014703.GA29953@sigill.intra.peff.net","threadId":"41709","inReplyTo":"CAPig+cSTp6R0XNwNAU=QhKOTqB4=uSuPd_mnwfvy6wHs8X7FRg@mail.gmail.com","subject":"Re: [PATCH v5 4/4] pretty: test --expand-tabs","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2016-04-05T01:47:03Z","receivedAt":"2016-04-05T01:47:03Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Apr 04, 2016 at 09:10:46PM -0400, Eric Sunshine wrote:\n\n> > +       count=$1 ;# expected tabs\n> \n> Why semicolon before the hash here and above?\n\nI am in the habit of doing this, too. I have a vague recollection of\ngetting bitten by a shell that treated:\n\n  echo foo # bar\n\nor something similar as not-a-comment. But neither bash, dash, nor ksh\nseem to. So I'm not sure if it was some other shell in my past, or if I\nsimply have an irrational fear.\n\n-Peff\n"},{"id":"282676","messageId":"20160405015234.GB29953@sigill.intra.peff.net","threadId":"41709","inReplyTo":"1459817917-32078-5-git-send-email-gitster@pobox.com","subject":"Re: [PATCH v5 4/4] pretty: test --expand-tabs","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2016-04-05T01:52:34Z","receivedAt":"2016-04-05T01:52:34Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Apr 04, 2016 at 05:58:37PM -0700, Junio C Hamano wrote:\n\n> +count_expand ()\n> +{\n\nThis function takes a lot of unnamed arguments that we process with\n\"shift\". It might be nice to give a brief comment describing them.\n\n> +test_expand \"\"\n> +test_expand --pretty\n> +test_expand --pretty=short\n> +test_expand --pretty=medium\n> +test_expand --pretty=full\n> +test_expand --pretty=fuller\n> +test_expand --pretty=fuller\n> +test_expand --pretty=raw\n> +test_expand --pretty=email\n\nDuplicated fuller?\n\n-Peff\n"},{"id":"282675","messageId":"20160405015326.GC29953@sigill.intra.peff.net","threadId":"41709","inReplyTo":"1459817917-32078-1-git-send-email-gitster@pobox.com","subject":"Re: [PATCH v5 0/4] Expanding tabs in \"git log\" output","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2016-04-05T01:53:26Z","receivedAt":"2016-04-05T01:53:26Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Apr 04, 2016 at 05:58:33PM -0700, Junio C Hamano wrote:\n\n> So here is the fifth and hopefully the final try.  Previous round\n> are at $gmane/289694, $gmane/289166, $gmane/288987 and\n> $gmane/290222.\n\nWith the exception of two minor nits on the final patch, this looks good\nto me. Thanks for cleaning up the option-parsing ordering thing; I think\nit turned out rather nice.\n\n-Peff\n"},{"id":"282685","messageId":"xmqqfuv04lnv.fsf@gitster.mtv.corp.google.com","threadId":"41709","inReplyTo":"20160405014703.GA29953@sigill.intra.peff.net","subject":"Re: [PATCH v5 4/4] pretty: test --expand-tabs","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-04-05T06:25:24Z","receivedAt":"2016-04-05T06:25:24Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> On Mon, Apr 04, 2016 at 09:10:46PM -0400, Eric Sunshine wrote:\n>\n>> > +       count=$1 ;# expected tabs\n>> \n>> Why semicolon before the hash here and above?\n>\n> I am in the habit of doing this, too. I have a vague recollection of\n> getting bitten by a shell that treated:\n>\n>   echo foo # bar\n>\n> or something similar as not-a-comment. But neither bash, dash, nor ksh\n> seem to.\n\nI think the reason why I started doing the same is because some\nshells can be configured to lose the comment-introducer-ness of \"#\"\nin interactive mode, and I wanted to make sure that many things I\nwrite can be tried out by others more easily by copy-and-paste to\ntheir interactive session.\n"},{"id":"282686","messageId":"xmqqbn5o4lca.fsf@gitster.mtv.corp.google.com","threadId":"41709","inReplyTo":"20160405015234.GB29953@sigill.intra.peff.net","subject":"Re: [PATCH v5 4/4] pretty: test --expand-tabs","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-04-05T06:32:21Z","receivedAt":"2016-04-05T06:32:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> On Mon, Apr 04, 2016 at 05:58:37PM -0700, Junio C Hamano wrote:\n>\n>> +count_expand ()\n>> +{\n>\n> This function takes a lot of unnamed arguments that we process with\n> \"shift\". It might be nice to give a brief comment describing them.\n> ...\n>> +test_expand --pretty=fuller\n>> +test_expand --pretty=fuller\n> ...\n> Duplicated fuller?\n\nThanks.  Here is a replacement.\n\n-- >8 --\nThe test prepares a simple commit with HT on its log message lines,\nand makes sure that\n\n - formats that should or should not expand tabs by default do or do\n   not expand tabs respectively,\n\n - with explicit --expand-tabs=<N> and short-hands --expand-tabs\n   (equivalent to --expand-tabs=8) and --no-expand-tabs (equivalent\n   to --expand-tabs=0) before or after the explicit --pretty=$fmt,\n   the tabs are expanded (or not expanded) accordingly.\n\nThe tests use the second line of the log message for formats other\nthan --pretty=short, primarily because the first line of the email\nformat is handled specially to add the [PATCH] prefix, etc. in a\nseparate codepath (--pretty=short uses the first line because there\nis no other line to test).\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n t/t4213-log-tabexpand.sh | 105 +++++++++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 105 insertions(+)\n create mode 100755 t/t4213-log-tabexpand.sh\n\ndiff --git a/t/t4213-log-tabexpand.sh b/t/t4213-log-tabexpand.sh\nnew file mode 100755\nindex 0000000..e01a8f6\n--- /dev/null\n+++ b/t/t4213-log-tabexpand.sh\n@@ -0,0 +1,105 @@\n+#!/bin/sh\n+\n+test_description='log/show --expand-tabs'\n+\n+. ./test-lib.sh\n+\n+HT=\"\t\"\n+title='tab indent at the beginning of the title line'\n+body='tab indent on a line in the body'\n+\n+# usage: count_expand $indent $numSP $numHT @format_args\n+count_expand ()\n+{\n+\texpect=\n+\tcount=$(( $1 + $2 )) ;# expected spaces\n+\twhile test $count -gt 0\n+\tdo\n+\t\texpect=\"$expect \"\n+\t\tcount=$(( $count - 1 ))\n+\tdone\n+\tshift 2\n+\tcount=$1 ;# expected tabs\n+\twhile test $count -gt 0\n+\tdo\n+\t\texpect=\"$expect$HT\"\n+\t\tcount=$(( $count - 1 ))\n+\tdone\n+\tshift\n+\n+\t# The remainder of the command line is \"git show -s\" options\n+\tcase \" $* \" in\n+\t*' --pretty=short '*)\n+\t\tline=$title ;;\n+\t*)\n+\t\tline=$body ;;\n+\tesac\n+\n+\t# Prefix the output with the command line arguments, and\n+\t# replace SP with a dot both in the expecte and actual output\n+\t# so that test_cmp would show the differene together with the\n+\t# breakage in a way easier to consume by the debugging user.\n+\t{\n+\t\techo \"git show -s $*\"\n+\t\techo \"$expect$line\"\n+\t} | sed -e 's/ /./g' >expect\n+\n+\t{\n+\t\techo \"git show -s $*\"\n+\t\tgit show -s \"$@\" |\n+\t\tsed -n -e \"/$line\\$/p\"\n+\t} | sed -e 's/ /./g' >actual\n+\n+\ttest_cmp expect actual\n+}\n+\n+test_expand ()\n+{\n+\tfmt=$1\n+\tcase \"$fmt\" in\n+\t*=raw | *=short | *=email)\n+\t\tdefault=\"0 1\" ;;\n+\t*)\n+\t\tdefault=\"8 0\" ;;\n+\tesac\n+\tcase \"$fmt\" in\n+\t*=email)\n+\t\tin=0 ;;\n+\t*)\n+\t\tin=4 ;;\n+\tesac\n+\ttest_expect_success \"expand/no-expand${fmt:+ for $fmt}\" '\n+\t\tcount_expand $in $default $fmt &&\n+\t\tcount_expand $in 8 0 $fmt --expand-tabs &&\n+\t\tcount_expand $in 8 0 --expand-tabs $fmt &&\n+\t\tcount_expand $in 8 0 $fmt --expand-tabs=8 &&\n+\t\tcount_expand $in 8 0 --expand-tabs=8 $fmt &&\n+\t\tcount_expand $in 0 1 $fmt --no-expand-tabs &&\n+\t\tcount_expand $in 0 1 --no-expand-tabs $fmt &&\n+\t\tcount_expand $in 0 1 $fmt --expand-tabs=0 &&\n+\t\tcount_expand $in 0 1 --expand-tabs=0 $fmt &&\n+\t\tcount_expand $in 4 0 $fmt --expand-tabs=4 &&\n+\t\tcount_expand $in 4 0 --expand-tabs=4 $fmt\n+\t'\n+}\n+\n+test_expect_success 'setup' '\n+\ttest_tick &&\n+\tsed -e \"s/Q/$HT/g\" <<-EOF >msg &&\n+\tQ$title\n+\n+\tQ$body\n+\tEOF\n+\tgit commit --allow-empty -F msg\n+'\n+\n+test_expand \"\"\n+test_expand --pretty\n+test_expand --pretty=short\n+test_expand --pretty=medium\n+test_expand --pretty=full\n+test_expand --pretty=fuller\n+test_expand --pretty=raw\n+test_expand --pretty=email\n+\n+test_done\n-- \n2.8.1-253-gd0f4798\n"},{"id":"282691","messageId":"570365b0.XpU7/8LiRCyNhiKo%perryh@pluto.rain.com","threadId":"41709","inReplyTo":"20160405015234.GB29953@sigill.intra.peff.net","subject":"Re: [PATCH v5 4/4] pretty: test --expand-tabs","fromName":"Perry Hutchison","fromEmail":"perryh@pluto.rain.com","sentAt":"2016-04-05T07:13:52Z","receivedAt":"2016-04-05T07:13:52Z","isPatch":true,"sender":{"key":"perryh@pluto.rain.com","avatar":null},"body":"Jeff King <peff@peff.net> wrote:\n> > +test_expand --pretty=fuller\n> > +test_expand --pretty=fuller\n>\n> Duplicated fuller?\n\nJust brush it off :)\n\n\n\n\n\n[Those too young to get the joke can\n look up \"fuller brush\" in Wikipedia.]\n"}]}