{"thread":{"id":"29248","subject":"[PATCH] Support wrapping commit messages when you read them","startedAt":"2011-12-25T05:05:32Z","lastAt":"2012-02-20T21:09:25Z","messageCount":6,"participants":["Sidney San Martín","Junio C Hamano","Holger Hellmuth"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"181685","messageId":"8DE6E894-B50D-4F7E-AE18-C10E7E40A550@sidneysm.com","threadId":"29248","inReplyTo":null,"subject":"[PATCH] Support wrapping commit messages when you read them","fromName":"Sidney San Martín","fromEmail":"s@sidneysm.com","sentAt":"2011-12-25T05:05:32Z","receivedAt":"2011-12-25T05:05:32Z","isPatch":true,"sender":{"key":"s@sidneysm.com","avatar":"https://gravatar.com/avatar/c1b1247190da54d5f0b65993070b7a31a800a486f2551ee9252a269c78c28e4c?d=mp&s=160"},"body":"Fairly simpleminded line wrapping that makes commit messages\nreadable if they weren’t wrapped by the committer.\n\n- Use strbuf_add_wrapped_text() to do the dirty work\n- Detect simple lists which begin with \"+ \", \"* \", or \"- \" and indent\n  them appropriately (like this line)\n- Print lines which begin with whitespace as-is (e.g. code samples)\n\nAdd --wrap[=<width>] and --no-wrap to commands that pretty-print commit\nmessages, and add log.wrap and log.wrap.width configuration options.\n\nlog.wrap defaults to never, and can be set to never/false, auto/true,\nor always. If auto, hijack want_color() to decide whether it’s\nappropriate to use line wrapping. (This is a little hacky, but as far\nas I can tell the conditions for auto color and auto wrapping are the\nsame. Maybe it would make sense to rename want_color()?)\n\nlog.wrap.width defaults to 80.\n\nSigned-off-by: Sidney San Martín <s@sidneysm.com>\n---\n\nI hope I’m doing this right!\n\nConsider this a first draft of the new feature I brought up a few weeks ago.\n\n\n Documentation/config.txt         |    8 ++++\n Documentation/pretty-options.txt |   14 +++++++\n commit.h                         |    6 +++\n log-tree.c                       |    1 +\n pretty.c                         |   71 +++++++++++++++++++++++++++++++++++++-\n revision.c                       |   10 +++++\n revision.h                       |    3 ++\n 7 files changed, 112 insertions(+), 1 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 6e63b59..b8c1a81 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -1403,6 +1403,14 @@ 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.wrap::\n+\tCommit message wrapping. May be set to always, false (or never) or\n+\tauto (or true), in which case commit messages are only wrapped when\n+\tthe output is to a terminal. Defaults to false. See linkgit:git-log[1].\n+\n+log.wrap.width::\n+\tLine width for commit message wrapping. Defaults to 80 characters.\n+\n mailmap.file::\n \tThe location of an augmenting mailmap file. The default\n \tmailmap, located in the root of the repository, is loaded\ndiff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt\nindex 2a3dc86..7601a43 100644\n--- a/Documentation/pretty-options.txt\n+++ b/Documentation/pretty-options.txt\n@@ -10,6 +10,20 @@\n Note: you can specify the default pretty format in the repository\n configuration (see linkgit:git-config[1]).\n \n+--wrap[=<width>]::\n+\tWord-wrap commit messages to the specified width, 80 characters\n+\tby default. Lines beginning with +, *, or - and a space, or with a\n+\tnumber followed by a period and a space, are interpreted as lists\n+\tand wrapped with a hanging indent. Lines beginning with whitespace\n+\t(e.g. code samples) are left as-is.\n++\n+Note: you can specify the default wrapping behavior in the repository\n+configuration (see linkgit:git-config[1]).\n+\n+--no-wrap::\n+\tTurn off commit message wrapping. This is the default (unless\n+\totherwise specified in the repository configuration).\n+\n --abbrev-commit::\n \tInstead of showing the full 40-byte hexadecimal commit object\n \tname, show only a partial prefix.  Non default number of\ndiff --git a/commit.h b/commit.h\nindex 4df3978..1321666 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -86,6 +86,12 @@ struct pretty_print_context {\n \tint show_notes;\n \tstruct reflog_walk_info *reflog_info;\n \tconst char *output_encoding;\n+\tstruct wrap_options {\n+\t\tunsigned int\n+\t\t\twidth,\n+\t\t\twrap:1,\n+\t\t\twrap_given:1;\n+\t} wrap;\n };\n \n struct userformat_want {\ndiff --git a/log-tree.c b/log-tree.c\nindex 319bd31..3dfa944 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -414,6 +414,7 @@ void show_log(struct rev_info *opt)\n \n \topt->loginfo = NULL;\n \tctx.show_notes = opt->show_notes;\n+\tctx.wrap = opt->wrap;\n \tif (!opt->verbose_header) {\n \t\tgraph_show_commit(opt->graph);\n \ndiff --git a/pretty.c b/pretty.c\nindex 1580299..133bc53 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -23,6 +23,10 @@ static size_t commit_formats_len;\n static size_t commit_formats_alloc;\n static struct cmt_fmt_map *find_commit_format(const char *sought);\n \n+static unsigned int wrap_configured = 0;\n+static unsigned int wrap = 0;\n+static unsigned int wrap_width = 80;\n+\n static void save_user_format(struct rev_info *rev, const char *cp, int is_tformat)\n {\n \tfree(user_format);\n@@ -172,6 +176,63 @@ void get_commit_format(const char *arg, struct rev_info *rev)\n \t}\n }\n \n+static int git_wrap_config(const char *name, const char *value, void *cb)\n+{\n+\twrap_configured = 1;\n+\n+\tif (prefixcmp(name, \"log.wrap\"))\n+\t\treturn 0;\n+\n+\tif (name[8] == '\\0') {\n+\t\tif (value && !strcmp(value, \"always\")) {\n+\t\t\twrap = 1;\n+\t\t} else if (value && !strcmp(value, \"never\")) {\n+\t\t\twrap = 0;\n+\t\t} else if (!value || !strcmp(value, \"auto\") || git_config_bool(name, value)) {\n+\t\t\twrap = want_color(GIT_COLOR_AUTO);\n+\t\t}\n+\t} else if (name[8] == '.') {\n+\t\tname += 9;\n+\t\tif (!strcmp(name, \"width\")) {\n+\t\t\twrap_width = git_config_int(name, value);\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static unsigned int want_wrap(struct wrap_options options)\n+{\n+\tif(!wrap_configured)\n+\t\tgit_config(git_wrap_config, NULL);\n+\treturn (options.wrap_given ? options.wrap : wrap);\n+}\n+static unsigned int get_wrap_width(struct wrap_options options)\n+{\n+\tif(!wrap_configured)\n+\t\tgit_config(git_wrap_config, NULL);\n+\treturn options.width ? options.width : wrap_width;\n+}\n+\n+static int line_list_prefix(const char *line, int len)\n+{\n+\tunsigned int numberLength = 0;\n+\tconst char *pos = line;\n+\tif (len < 3) {\n+\t\treturn 0;\n+\t} else if ((line[0] == '*' || line[0] == '+' || line[0] == '-') && line[1] == ' ') {\n+\t\treturn 2;\n+\t} else {\n+\t\twhile (pos - line < len && pos[0] >= '0' && pos[0] <= '9'){\n+\t\t\tnumberLength++;\n+\t\t\tpos++;\n+\t\t}\n+\t\tif (numberLength && pos - line + 1 < len && pos[0] == '.' && pos[1] == ' ') {\n+\t\t\treturn numberLength + 2;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n /*\n  * Generic support for pretty-printing the header\n  */\n@@ -1246,6 +1307,8 @@ void pp_remainder(const struct pretty_print_context *pp,\n \t\t  struct strbuf *sb,\n \t\t  int indent)\n {\n+\tunsigned int wrap = want_wrap(pp->wrap);\n+\tunsigned int width = get_wrap_width(pp->wrap);\n \tint first = 1;\n \tfor (;;) {\n \t\tconst char *line = *msg_p;\n@@ -1268,7 +1331,13 @@ void pp_remainder(const struct pretty_print_context *pp,\n \t\t\tmemset(sb->buf + sb->len, ' ', indent);\n \t\t\tstrbuf_setlen(sb, sb->len + indent);\n \t\t}\n-\t\tstrbuf_add(sb, line, linelen);\n+\t\tif (wrap && linelen && line[0] != ' ' && line[0] != '\\t') {\n+\t\t\tstruct strbuf wrapped = STRBUF_INIT;\n+\t\t\tstrbuf_add(&wrapped, line, linelen);\n+\t\t\tstrbuf_add_wrapped_text(sb, wrapped.buf, 0, indent + line_list_prefix(line, linelen), width - indent);\n+\t\t} else {\n+\t\t\tstrbuf_add(sb, line, linelen);\n+\t\t}\n \t\tstrbuf_addch(sb, '\\n');\n \t}\n }\ndiff --git a/revision.c b/revision.c\nindex 8764dde..ca4b386 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1465,6 +1465,16 @@ 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, \"--wrap\")) {\n+\t\trevs->wrap.wrap = 1;\n+\t\trevs->wrap.wrap_given = 1;\n+\t} else if (!prefixcmp(arg, \"--wrap=\")) {\n+\t\trevs->wrap.wrap = 1;\n+\t\trevs->wrap.wrap_given = 1;\n+\t\trevs->wrap.width = atoi(arg+7);\n+\t} else if (!prefixcmp(arg, \"--no-wrap\")) {\n+\t\trevs->wrap.wrap = 0;\n+\t\trevs->wrap.wrap_given = 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 6aa53d1..f812685 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -117,6 +117,9 @@ struct rev_info {\n \t\t\tmissing_newline:1,\n \t\t\tdate_mode_explicit:1,\n \t\t\tpreserve_subject:1;\n+\n+\tstruct wrap_options wrap;\n+\n \tunsigned int\tdisable_stdin:1;\n \tunsigned int\tleak_pending:1;\n \n-- \n1.7.8.1\n"},{"id":"181687","messageId":"7vfwg99dom.fsf@alter.siamese.dyndns.org","threadId":"29248","inReplyTo":"8DE6E894-B50D-4F7E-AE18-C10E7E40A550@sidneysm.com","subject":"Re: [PATCH] Support wrapping commit messages when you read them","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-12-25T09:57:13Z","receivedAt":"2011-12-25T09:57:13Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Sidney San Martín <s@sidneysm.com> writes:\n\n> Fairly simpleminded line wrapping that makes commit messages\n> readable if they weren’t wrapped by the committer.\n\nThis does not say anything useful, other than \"this is a naïve\nimplementation of message wrapper\" and invites \"So what?\".\n\nThe most simple-minded solution is to reject such commits with crappy log\nmessage.\n\nAfter all, SCM is merely a method to help communication between\ndevelopers, and sticking to the common denominator is a proven good way to\nmake sure everybody involved in the project can use what is recorded in\nthe repository. This is not limited only to the log message, but equally\napplies to filenames (e.g. don't create xt_tcpmss.c and xt_TCPMSS.c in the\nsame directory if you want your project extractable on case insensitive\nfilesystems) and even to the sources.\n\nYou need to justify the cause a bit better. Why is such a new logic\njustified?\n\n> - Use strbuf_add_wrapped_text() to do the dirty work\n> - Detect simple lists which begin with \"+ \", \"* \", or \"- \" and indent\n>   them appropriately (like this line)\n> - Print lines which begin with whitespace as-is (e.g. code samples)\n\nI suspect the above would make it more palatable than format=flowed\nbrought up in earlier discussions, which is unsuitable for nothing but\nstraight text.\n\n> Add --wrap[=<width>] and --no-wrap to commands that pretty-print commit\n> messages, and add log.wrap and log.wrap.width configuration options.\n\nWhy do you need two separate options and configurations that look as if\nthey are independent but in reality not?  If you say \"no wrap\", there is\nno room for you to say \"wrap width is 72\".\n\nI would expect something like:\n\n --log-message-wrap, --log-message-wrap=72, --log-message-wrap=no \n\nwith --log-message-wrap=yes as a synonym for --log-message-wrap to give\nconsistency. The corresponding configuraiton would be log.messageWrap\nwhose values could be the usual bool-or-int.\n\n> log.wrap defaults to never, and can be set to never/false, auto/true,\n> or always. If auto, hijack want_color() to decide whether it’s\n> appropriate to use line wrapping. (This is a little hacky, but as far\n> as I can tell the conditions for auto color and auto wrapping are the\n> same.\n\nWhy does coloring have _anything_ to do with line wrapping? Maybe your\npersonaly preference might be \"wrap and color if interactive terminal\" but\nthat is conflating two unrelated concepts. A user may not expect coloring\non a dumb interactive terminal, but wrapping may still be useful.\n\n> log.wrap.width defaults to 80.\n\nThis does not deserve a comment as I already rejected the \"two\nconfiguration\" approach, but do not use three-level names this way. We try\nto reserve three-level names only for cases where the second level is used\nfor an unbound collection (e.g. \"remote.$name.url\", \"branch.$name.merge\").\nthat is user-specified.\n"},{"id":"184611","messageId":"46957CEB-5E48-4C11-8428-9A88C3810548@sidneysm.com","threadId":"29248","inReplyTo":"7vfwg99dom.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] Support wrapping commit messages when you read them","fromName":"Sidney San Martín","fromEmail":"s@sidneysm.com","sentAt":"2012-02-13T21:26:24Z","receivedAt":"2012-02-13T21:26:24Z","isPatch":true,"sender":{"key":"s@sidneysm.com","avatar":"https://gravatar.com/avatar/c1b1247190da54d5f0b65993070b7a31a800a486f2551ee9252a269c78c28e4c?d=mp&s=160"},"body":"Hey Junio,\n\nI apologize for the delay, I do want to keep working on this idea. I had to put it down but should have more time now if you're willing to keep talking about it.\n\nThanks for taking the time to look at my first patch.\n\nOn Dec 25, 2011, at 4:57 AM, Junio C Hamano wrote:\n\n>> Fairly simpleminded line wrapping that makes commit messages\n>> readable if they weren’t wrapped by the committer.\n> \n> This does not say anything useful, other than \"this is a naïve\n> implementation of message wrapper\" and invites \"So what?\".\n> \n> The most simple-minded solution is to reject such commits with crappy log\n> message.\n> \n> After all, SCM is merely a method to help communication between\n> developers, and sticking to the common denominator is a proven good way to\n> make sure everybody involved in the project can use what is recorded in\n> the repository. This is not limited only to the log message, but equally\n> applies to filenames (e.g. don't create xt_tcpmss.c and xt_TCPMSS.c in the\n> same directory if you want your project extractable on case insensitive\n> filesystems) and even to the sources.\n> \n> You need to justify the cause a bit better. Why is such a new logic\n> justified?\n\nYou’re right, that sentence doesn't say anything.\n\nI agree that projects need to have standards for their commit messages, but I also think that line wrapping should be taken care of by the computer so that the humans can think about the content of their commit messages. It's easier for everyone.\n\nIt also makes sense to not assume the user is using an 80-column terminal. Like I mentioned in another email, other tools work this way (e.g. manpages). It turns out that \"git help\" already has code to detect the width of the terminal, and it formats its output to fit it. I want to adapt that logic for this feature.\n\nHow about replacing that paragraph with this:\n\n“Git didn’t previously support formatting commit messages for a user’s terminal, and the common practice has been to pre-wrap commit messages to under 80 columns. This is necessary for some projects, especially those which trade patches over email where mail clients might damage longer lines, but in many cases it’s only done so that the messages are readable in \"git log\" and the like. Supporting line wrapping in git lets users choose to leave their commit messages unwrapped and have them formatted for their terminal when displayed.”\n\n>> - Use strbuf_add_wrapped_text() to do the dirty work\n>> - Detect simple lists which begin with \"+ \", \"* \", or \"- \" and indent\n>>  them appropriately (like this line)\n>> - Print lines which begin with whitespace as-is (e.g. code samples)\n> \n> I suspect the above would make it more palatable than format=flowed\n> brought up in earlier discussions, which is unsuitable for nothing but\n> straight text.\n> \n>> Add --wrap[=<width>] and --no-wrap to commands that pretty-print commit\n>> messages, and add log.wrap and log.wrap.width configuration options.\n> \n> Why do you need two separate options and configurations that look as if\n> they are independent but in reality not?  If you say \"no wrap\", there is\n> no room for you to say \"wrap width is 72\".\n> \n> I would expect something like:\n> \n> --log-message-wrap, --log-message-wrap=72, --log-message-wrap=no \n> \n> with --log-message-wrap=yes as a synonym for --log-message-wrap to give\n> consistency. The corresponding configuraiton would be log.messageWrap\n> whose values could be the usual bool-or-int.\n\nI stole this from other options: --progress/--no-progress, --color/--color=[<when>]/--no-color, --track/--no-track, etc.\n\nThe separate wrap/wrap.width config options were so that you could set it separately to auto or always and also specify a width. But, I don't know if that's needed anymore. See below.\n\n>> log.wrap defaults to never, and can be set to never/false, auto/true,\n>> or always. If auto, hijack want_color() to decide whether it’s\n>> appropriate to use line wrapping. (This is a little hacky, but as far\n>> as I can tell the conditions for auto color and auto wrapping are the\n>> same.\n> \n> Why does coloring have _anything_ to do with line wrapping? Maybe your\n> personaly preference might be \"wrap and color if interactive terminal\" but\n> that is conflating two unrelated concepts. A user may not expect coloring\n> on a dumb interactive terminal, but wrapping may still be useful.\n\nIt doesn’t — I used want_color() so that I could get the patch out there without making other changes to the codebase or duplicating its code, so you could comment on the rest of it. I'll get it out of the next version of the patch, which I'll try to get to you later today or tomorrow.\n\n>> log.wrap.width defaults to 80.\n> \n> This does not deserve a comment as I already rejected the \"two\n> configuration\" approach, but do not use three-level names this way. We try\n> to reserve three-level names only for cases where the second level is used\n> for an unbound collection (e.g. \"remote.$name.url\", \"branch.$name.merge\").\n> that is user-specified.\n\nOK, that was a misunderstanding on my part. Actually, I would be in favor of getting rid of that option completely, moving in support for detecting the terminal width from \"git help\" and making it just a boolean, auto-only. How does that sound?\n\nSidney"},{"id":"184615","messageId":"7vzkcmbcbq.fsf@alter.siamese.dyndns.org","threadId":"29248","inReplyTo":"46957CEB-5E48-4C11-8428-9A88C3810548@sidneysm.com","subject":"Re: [PATCH] Support wrapping commit messages when you read them","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-13T22:25:29Z","receivedAt":"2012-02-13T22:25:29Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Sidney San Martín <s@sidneysm.com> writes:\n\n>> After all, SCM is merely a method to help communication between\n>> developers, and sticking to the common denominator is a proven good way to\n>> make sure everybody involved in the project can use what is recorded in\n>> the repository. This is not limited only to the log message, but equally\n>> applies to filenames (e.g. don't create xt_tcpmss.c and xt_TCPMSS.c in the\n>> same directory if you want your project extractable on case insensitive\n>> filesystems) and even to the sources.\n>> \n>> You need to justify the cause a bit better. Why is such a new logic\n>> justified?\n>\n> You’re right, that sentence doesn't say anything.\n>\n> I agree that projects need to have standards for their commit messages,\n> but I also think that line wrapping should be taken care of by the\n> computer so that the humans can think about the content of their commit\n> messages. It's easier for everyone.\n\nI just typed M-q to wrap the above paragraph from you to make it readable.\n\n\"Computers are good at automating\" is true, and that is why real editors\ngive an easy way to auto-wrap long prose in a paragraph while composing.\nBut \"computers are good at automating\" is not a convincing justification\nto let the composer leave unreasonably long lines in the commit log object\nand force the reader side to line-wrap the mess only to fix it up.\n"},{"id":"184653","messageId":"4F3A4F53.9030302@ira.uka.de","threadId":"29248","inReplyTo":"7vzkcmbcbq.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] Support wrapping commit messages when you read them","fromName":"Holger Hellmuth","fromEmail":"hellmuth@ira.uka.de","sentAt":"2012-02-14T12:10:59Z","receivedAt":"2012-02-14T12:10:59Z","isPatch":true,"sender":{"key":"hellmuth@ira.uka.de","avatar":null},"body":"On 13.02.2012 23:25, Junio C Hamano wrote:\n> \"Computers are good at automating\" is true, and that is why real editors\n> give an easy way to auto-wrap long prose in a paragraph while composing.\n> But \"computers are good at automating\" is not a convincing justification\n> to let the composer leave unreasonably long lines in the commit log object\n> and force the reader side to line-wrap the mess only to fix it up.\n\nMaybe this is more convincing: Only the reader side knows the \nline-length of the display or window.\n"},{"id":"185025","messageId":"5171724E-AAE9-4419-9D0F-C09FB8048488@sidneysm.com","threadId":"29248","inReplyTo":"7vzkcmbcbq.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] Support wrapping commit messages when you read them","fromName":"Sidney San Martín","fromEmail":"s@sidneysm.com","sentAt":"2012-02-20T21:09:25Z","receivedAt":"2012-02-20T21:09:25Z","isPatch":true,"sender":{"key":"s@sidneysm.com","avatar":"https://gravatar.com/avatar/c1b1247190da54d5f0b65993070b7a31a800a486f2551ee9252a269c78c28e4c?d=mp&s=160"},"body":"On Feb 13, 2012, at 5:25 PM, Junio C Hamano wrote:\n\n> I just typed M-q to wrap the above paragraph from you to make it readable.\n\nOut of curiosity, how do you read your mail? I don’t know anyone whose mail\nis set up like that.\n\nI’m happy to wrap my text if it’s tricky for you to read it otherwise — but\nFWIW my mail client doesn’t support hard wrapping (I’m doing it in my editor).\n\n> \"Computers are good at automating\" is true, and that is why real editors\n> give an easy way to auto-wrap long prose in a paragraph while composing.\n> But \"computers are good at automating\" is not a convincing justification\n> to let the composer leave unreasonably long lines in the commit log object\n> and force the reader side to line-wrap the mess only to fix it up.\n\nI asked in #git how other people handle wrapping. Out of three people who\nresponded, only one said that they had configured their editor (the other two\ndo it by hand). One thought that Git already did dumb (character-level) line\nwrapping, but it turns out he had set LESS= and GIT_PAGER='less -FRX'.\n\nSo, even if it is possible to set up your editor to wrap prose appropriately,\nI don’t think it’s as common as one might hope.\n\nI’m not suggesting that the reader side should take care of the wrapping\nbecause it *can*, I’m suggesting that it shouldn’t take specially-configured\neditors to get consistent and good results — which I assume is why virtually\nall new prose-writing tools do wrapping on the viewing end.\n\nWhat do you think about Git UIs which use proportional fonts for text where\nhard wrapping doesn’t work at all? (I brought this up before but want your\ntake on it).\n\nAnd, using man and, now, \"git help -a\" as examples: they both adapt their\noutput to the width of the user’s terminal. Isn’t that a good thing?\n\nIf those aren’t good justification… what would be?"}]}