{"thread":{"id":"45543","subject":"[PATCH 0/3] Respect column.ui in commented status in git-commit","startedAt":"2017-03-30T01:42:50Z","lastAt":"2017-04-10T11:35:24Z","messageCount":9,"participants":["Stefan Beller","Jeff King","Duy Nguyen"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"315730","messageId":"20170330014238.30032-1-sbeller@google.com","threadId":"45543","inReplyTo":null,"subject":"[PATCH 0/3] Respect column.ui in commented status in git-commit","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-03-30T01:42:35Z","receivedAt":"2017-03-30T01:42:50Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"When studying the code, I was nerd-sniped by the commit message of\n4d2292e9a9 (status: refactor colopts handling, 2012-05-07)\nas I did not understand why it was so important to reset the s.colopts to 0\nin builtin/commit.c.\n\nIn my adolescent hybris I nearly sent out a patch claiming that line to be\nuseless and wrong, but then I studied a bit more. After the background story\nbecame clear, I decided to \"just write the missing piece\", how hard can it be?\n\nI would consider the following three patches a hack, but they work. You can\nhave untracked files in column mode in the commented text for a commit.\n\nThanks,\nStefan\n\nStefan Beller (3):\n  column.c: pass column_options to down to display_plain\n  column: allow for custom printf\n  WIP - Allow custom printf function for column printing\n\n builtin/commit.c |  1 -\n column.c         | 21 +++++++++++++--------\n column.h         |  3 +++\n wt-status.c      | 29 ++++++++++++++++++++++++-----\n 4 files changed, 40 insertions(+), 14 deletions(-)\n\n-- \n2.12.2.511.g2abb8caf66\n\n"},{"id":"315731","messageId":"20170330014238.30032-3-sbeller@google.com","threadId":"45543","inReplyTo":"20170330014238.30032-1-sbeller@google.com","subject":"[PATCH 2/3] column: allow for custom printf","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-03-30T01:42:37Z","receivedAt":"2017-03-30T01:42:53Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"Signed-off-by: Stefan Beller <sbeller@google.com>\n---\n column.c | 13 ++++++++-----\n column.h |  3 +++\n 2 files changed, 11 insertions(+), 5 deletions(-)\n\ndiff --git a/column.c b/column.c\nindex 4851b9aa04..522e554f29 100644\n--- a/column.c\n+++ b/column.c\n@@ -114,7 +114,9 @@ static void display_plain(const struct string_list *list,\n \tint i;\n \n \tfor (i = 0; i < list->nr; i++)\n-\t\tprintf(\"%s%s%s\", opts->indent, list->items[i].string, opts->nl);\n+\t\topts->_printf(\"%s%s%s\", opts->indent,\n+\t\t\t\t\tlist->items[i].string,\n+\t\t\t\t\topts->nl);\n }\n \n /* Print a cell to stdout with all necessary leading/traling space */\n@@ -143,10 +145,10 @@ static int display_cell(struct column_data *data, int initial_width,\n \telse\n \t\tnewline = x == data->cols - 1 || i == data->list->nr - 1;\n \n-\tprintf(\"%s%s%s\",\n-\t       x == 0 ? data->opts.indent : \"\",\n-\t       data->list->items[i].string,\n-\t       newline ? data->opts.nl : empty_cell + len);\n+\tdata->opts._printf(\"%s%s%s\",\n+\t\t\t   x == 0 ? data->opts.indent : \"\",\n+\t\t\t   data->list->items[i].string,\n+\t\t\t   newline ? data->opts.nl : empty_cell + len);\n \treturn 0;\n }\n \n@@ -200,6 +202,7 @@ void print_columns(const struct string_list *list, unsigned int colopts,\n \tnopts.nl = opts && opts->nl ? opts->nl : \"\\n\";\n \tnopts.padding = opts ? opts->padding : 1;\n \tnopts.width = opts && opts->width ? opts->width : term_columns() - 1;\n+\tnopts._printf = opts && opts->_printf ? opts->_printf : printf;\n \tif (!column_active(colopts)) {\n \t\tnopts.indent = \"\";\n \t\tnopts.nl = \"\\n\";\ndiff --git a/column.h b/column.h\nindex 0a61917fa7..c44a1525a9 100644\n--- a/column.h\n+++ b/column.h\n@@ -24,6 +24,9 @@ struct column_options {\n \tint padding;\n \tconst char *indent;\n \tconst char *nl;\n+\n+\t/* when non-NULL, use this printing function, fallback to printf */\n+\tint (*_printf)(const char *__format, ...);\n };\n \n struct option;\n-- \n2.12.2.511.g2abb8caf66\n\n"},{"id":"315732","messageId":"20170330014238.30032-4-sbeller@google.com","threadId":"45543","inReplyTo":"20170330014238.30032-1-sbeller@google.com","subject":"[PATCH 3/3] WIP - Allow custom printf function for column printing","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-03-30T01:42:38Z","receivedAt":"2017-03-30T01:42:54Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"Ever wondered why column.ui applies the untracked files in git-status,\nbut not for the help text comment in git-commit? Nobody wrote the code!\n\nThis is marked as WIP, as it barely demonstrates how the code may look\nlike. No tests, no documentation.\n\nSigned-off-by: Stefan Beller <sbeller@google.com>\n---\n builtin/commit.c |  1 -\n wt-status.c      | 29 ++++++++++++++++++++++++-----\n 2 files changed, 24 insertions(+), 6 deletions(-)\n\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex 4e288bc513..f482150df8 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -1649,7 +1649,6 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \n \tstatus_init_config(&s, git_commit_config);\n \tstatus_format = STATUS_FORMAT_NONE; /* Ignore status.short */\n-\ts.colopts = 0;\n \n \tif (get_sha1(\"HEAD\", oid.hash))\n \t\tcurrent_head = NULL;\ndiff --git a/wt-status.c b/wt-status.c\nindex 308cf3779e..cfba352683 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -43,12 +43,13 @@ static const char *color(int slot, struct wt_status *s)\n \treturn c;\n }\n \n-static void status_vprintf(struct wt_status *s, int at_bol, const char *color,\n+static int status_vprintf(struct wt_status *s, int at_bol, const char *color,\n \t\tconst char *fmt, va_list ap, const char *trail)\n {\n \tstruct strbuf sb = STRBUF_INIT;\n \tstruct strbuf linebuf = STRBUF_INIT;\n \tconst char *line, *eol;\n+\tint ret = 0;\n \n \tstrbuf_vaddf(&sb, fmt, ap);\n \tif (!sb.len) {\n@@ -59,9 +60,9 @@ static void status_vprintf(struct wt_status *s, int at_bol, const char *color,\n \t\t}\n \t\tcolor_print_strbuf(s->fp, color, &sb);\n \t\tif (trail)\n-\t\t\tfprintf(s->fp, \"%s\", trail);\n+\t\t\tret += fprintf(s->fp, \"%s\", trail);\n \t\tstrbuf_release(&sb);\n-\t\treturn;\n+\t\treturn ret;\n \t}\n \tfor (line = sb.buf; *line; line = eol + 1) {\n \t\teol = strchr(line, '\\n');\n@@ -78,15 +79,16 @@ static void status_vprintf(struct wt_status *s, int at_bol, const char *color,\n \t\t\tstrbuf_addstr(&linebuf, line);\n \t\tcolor_print_strbuf(s->fp, color, &linebuf);\n \t\tif (eol)\n-\t\t\tfprintf(s->fp, \"\\n\");\n+\t\t\tret += fprintf(s->fp, \"\\n\");\n \t\telse\n \t\t\tbreak;\n \t\tat_bol = 1;\n \t}\n \tif (trail)\n-\t\tfprintf(s->fp, \"%s\", trail);\n+\t\tret += fprintf(s->fp, \"%s\", trail);\n \tstrbuf_release(&linebuf);\n \tstrbuf_release(&sb);\n+\treturn ret;\n }\n \n void status_printf_ln(struct wt_status *s, const char *color,\n@@ -834,6 +836,20 @@ static void wt_longstatus_print_submodule_summary(struct wt_status *s, int uncom\n \tstrbuf_release(&summary);\n }\n \n+static struct wt_status *global_wt_status_hack;\n+static int column_status_printf(const char *fmt, ...)\n+{\n+\tva_list ap;\n+\tstruct wt_status *s = global_wt_status_hack;\n+\tint ret;\n+\n+\tva_start(ap, fmt);\n+\tret = status_vprintf(s, 0, \"\", fmt, ap, NULL);\n+\tva_end(ap);\n+\n+\treturn ret;\n+}\n+\n static void wt_longstatus_print_other(struct wt_status *s,\n \t\t\t\t      struct string_list *l,\n \t\t\t\t      const char *what,\n@@ -856,6 +872,7 @@ static void wt_longstatus_print_other(struct wt_status *s,\n \t\tpath = quote_path(it->string, s->prefix, &buf);\n \t\tif (column_active(s->colopts)) {\n \t\t\tstring_list_append(&output, path);\n+\t\t\tglobal_wt_status_hack = s;\n \t\t\tcontinue;\n \t\t}\n \t\tstatus_printf(s, color(WT_STATUS_HEADER, s), \"\\t\");\n@@ -876,6 +893,8 @@ static void wt_longstatus_print_other(struct wt_status *s,\n \tcopts.indent = buf.buf;\n \tif (want_color(s->use_color))\n \t\tcopts.nl = GIT_COLOR_RESET \"\\n\";\n+\n+\tcopts._printf = column_status_printf;\n \tprint_columns(&output, s->colopts, &copts);\n \tstring_list_clear(&output, 0);\n \tstrbuf_release(&buf);\n-- \n2.12.2.511.g2abb8caf66\n\n"},{"id":"315733","messageId":"20170330014238.30032-2-sbeller@google.com","threadId":"45543","inReplyTo":"20170330014238.30032-1-sbeller@google.com","subject":"[PATCH 1/3] column.c: pass column_options to down to display_plain","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-03-30T01:42:36Z","receivedAt":"2017-03-30T01:42:56Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"In a later patch we want to use more of the column_options members at\nplaces, where we do actual output, so it will be handy to have the whole\nstruct around in `display_plain`.\n\nSigned-off-by: Stefan Beller <sbeller@google.com>\n---\n column.c | 10 ++++++----\n 1 file changed, 6 insertions(+), 4 deletions(-)\n\ndiff --git a/column.c b/column.c\nindex d55ead18ef..4851b9aa04 100644\n--- a/column.c\n+++ b/column.c\n@@ -109,12 +109,12 @@ static void shrink_columns(struct column_data *data)\n \n /* Display without layout when not enabled */\n static void display_plain(const struct string_list *list,\n-\t\t\t  const char *indent, const char *nl)\n+\t\t\t  const struct column_options *opts)\n {\n \tint i;\n \n \tfor (i = 0; i < list->nr; i++)\n-\t\tprintf(\"%s%s%s\", indent, list->items[i].string, nl);\n+\t\tprintf(\"%s%s%s\", opts->indent, list->items[i].string, opts->nl);\n }\n \n /* Print a cell to stdout with all necessary leading/traling space */\n@@ -201,12 +201,14 @@ void print_columns(const struct string_list *list, unsigned int colopts,\n \tnopts.padding = opts ? opts->padding : 1;\n \tnopts.width = opts && opts->width ? opts->width : term_columns() - 1;\n \tif (!column_active(colopts)) {\n-\t\tdisplay_plain(list, \"\", \"\\n\");\n+\t\tnopts.indent = \"\";\n+\t\tnopts.nl = \"\\n\";\n+\t\tdisplay_plain(list, &nopts);\n \t\treturn;\n \t}\n \tswitch (COL_LAYOUT(colopts)) {\n \tcase COL_PLAIN:\n-\t\tdisplay_plain(list, nopts.indent, nopts.nl);\n+\t\tdisplay_plain(list, &nopts);\n \t\tbreak;\n \tcase COL_ROW:\n \tcase COL_COLUMN:\n-- \n2.12.2.511.g2abb8caf66\n\n"},{"id":"315735","messageId":"20170330031232.cac2av5v5mk5bz7e@sigill.intra.peff.net","threadId":"45543","inReplyTo":"20170330014238.30032-3-sbeller@google.com","subject":"Re: [PATCH 2/3] column: allow for custom printf","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2017-03-30T03:12:32Z","receivedAt":"2017-03-30T03:12:41Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Mar 29, 2017 at 06:42:37PM -0700, Stefan Beller wrote:\n\n> Signed-off-by: Stefan Beller <sbeller@google.com>\n\nNo justification?\n\nI assume it will be used in a future patch.\n\n> diff --git a/column.h b/column.h\n> index 0a61917fa7..c44a1525a9 100644\n> --- a/column.h\n> +++ b/column.h\n> @@ -24,6 +24,9 @@ struct column_options {\n>  \tint padding;\n>  \tconst char *indent;\n>  \tconst char *nl;\n> +\n> +\t/* when non-NULL, use this printing function, fallback to printf */\n> +\tint (*_printf)(const char *__format, ...);\n>  };\n\nAvoid names with leading underscores. They're reserved by the C\nstandard.\n\nI wonder if gcc is smart enough to let us mark this function pointer\nwith a \"format\" attribute so we can get compile-time checking of the\nformat string.\n\n-Peff\n"},{"id":"315736","messageId":"20170330032219.ujqddocibufn535d@sigill.intra.peff.net","threadId":"45543","inReplyTo":"20170330014238.30032-4-sbeller@google.com","subject":"Re: [PATCH 3/3] WIP - Allow custom printf function for column printing","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2017-03-30T03:22:19Z","receivedAt":"2017-03-30T03:22:28Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Mar 29, 2017 at 06:42:38PM -0700, Stefan Beller wrote:\n\n> Ever wondered why column.ui applies the untracked files in git-status,\n> but not for the help text comment in git-commit? Nobody wrote the code!\n> \n> This is marked as WIP, as it barely demonstrates how the code may look\n> like. No tests, no documentation.\n\nI'm confused about what this patch is trying to do. Is it just to turn\non column.status support for the template shown by git-commit? Or is it\ncolumnizing more than the untracked files list?\n\nIf the former, why isn't just setting s.colopts enough? I guess because\nwe write into a strbuf?\n\nIf the latter, then isn't that a separate logical patch from \"should\ncommit use columns\"?\n\nI don't have an opinion on the whole thing myself, as I do not use\ncolumns nor really know how they are supposed to work. You found my\n4d2292e9a9, but I was explicitly trying _not_ to get involved in any\nbehavior changes there due to my cluelessness. :)\n\nI think Duy, who wrote all of the column code, is a better person to cc.\n\n-Peff\n"},{"id":"315809","messageId":"CAGZ79ka6_wmVecBDpCrxr+3Vp5evKVUf164fs=CMGxgTx5PWxQ@mail.gmail.com","threadId":"45543","inReplyTo":"20170330032219.ujqddocibufn535d@sigill.intra.peff.net","subject":"Re: [PATCH 3/3] WIP - Allow custom printf function for column printing","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-03-30T18:53:23Z","receivedAt":"2017-03-30T18:53:30Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Wed, Mar 29, 2017 at 8:22 PM, Jeff King <peff@peff.net> wrote:\n> On Wed, Mar 29, 2017 at 06:42:38PM -0700, Stefan Beller wrote:\n>\n>> Ever wondered why column.ui applies the untracked files in git-status,\n>> but not for the help text comment in git-commit? Nobody wrote the code!\n>>\n>> This is marked as WIP, as it barely demonstrates how the code may look\n>> like. No tests, no documentation.\n>\n> I'm confused about what this patch is trying to do. Is it just to turn\n> on column.status support for the template shown by git-commit? Or is it\n> columnizing more than the untracked files list?\n\nIt is just columnizing the untracked files list.\n\n>\n> If the former, why isn't just setting s.colopts enough? I guess because\n> we write into a strbuf?\n\nYes, because it is a strbuf, and not stdout. the column code could only write\nto stdout (which was solved in prior patches), but we still have to provide a\n\"printf like\" function, which is the majority of this patch.\n\nThe remaining part of the patch, which could go into a separate patch\nis the removal of:\n-       s.colopts = 0;\n\n> If the latter, then isn't that a separate logical patch from \"should\n> commit use columns\"?\n\nyes, I was too quick there.\n\n\n> I don't have an opinion on the whole thing myself, as I do not use\n> columns nor really know how they are supposed to work. You found my\n> 4d2292e9a9, but I was explicitly trying _not_ to get involved in any\n> behavior changes there due to my cluelessness. :)\n\neh, ok. I thought you had deeper reasons than that.\nI did not use columns either, but now it looks like I am\na new user of that feature. If only Git would users easily\ndiscover cool features. ;)\n\n>\n> I think Duy, who wrote all of the column code, is a better person to cc.\n>\n> -Peff\n"},{"id":"316475","messageId":"20170410111318.GA23601@ash","threadId":"45543","inReplyTo":"20170330014238.30032-3-sbeller@google.com","subject":"Re: [PATCH 2/3] column: allow for custom printf","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2017-04-10T11:13:18Z","receivedAt":"2017-04-10T11:13:28Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Wed, Mar 29, 2017 at 06:42:37PM -0700, Stefan Beller wrote:\n> diff --git a/column.h b/column.h\n> index 0a61917fa7..c44a1525a9 100644\n> --- a/column.h\n> +++ b/column.h\n> @@ -24,6 +24,9 @@ struct column_options {\n>  \tint padding;\n>  \tconst char *indent;\n>  \tconst char *nl;\n> +\n> +\t/* when non-NULL, use this printing function, fallback to printf */\n> +\tint (*_printf)(const char *__format, ...);\n\nThis function should take 'struct column_options *' as the first\nargument so a future implementation have full information. Yes we need\nto add a couple more lines for just wrapping plain printf, but I think\nit's worth it.\n\n>  };\n>  \n>  struct option;\n> -- \n> 2.12.2.511.g2abb8caf66\n> \n"},{"id":"316478","messageId":"20170410113513.GB23601@ash","threadId":"45543","inReplyTo":"20170330014238.30032-4-sbeller@google.com","subject":"Re: [PATCH 3/3] WIP - Allow custom printf function for column printing","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2017-04-10T11:35:13Z","receivedAt":"2017-04-10T11:35:24Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Wed, Mar 29, 2017 at 06:42:38PM -0700, Stefan Beller wrote:\n> Ever wondered why column.ui applies the untracked files in git-status,\n> but not for the help text comment in git-commit? Nobody wrote the code!\n\nHow do you decide text width for this help text? If the output is\nterminal, we know how wide it is.\n\nBut editors are different animal. We might use terminal width for\ntext-based editors, but we won't even know if it's text or gui\nbased. Or should we just go with 72 columns? I don't think we even\nenforce that anywhere now.\n\n> diff --git a/wt-status.c b/wt-status.c\n> index 308cf3779e..cfba352683 100644\n> --- a/wt-status.c\n> +++ b/wt-status.c\n> @@ -43,12 +43,13 @@ static const char *color(int slot, struct wt_status *s)\n>  \treturn c;\n>  }\n>  \n> -static void status_vprintf(struct wt_status *s, int at_bol, const char *color,\n> +static int status_vprintf(struct wt_status *s, int at_bol, const char *color,\n>  \t\tconst char *fmt, va_list ap, const char *trail)\n>  {\n>  \tstruct strbuf sb = STRBUF_INIT;\n>  \tstruct strbuf linebuf = STRBUF_INIT;\n>  \tconst char *line, *eol;\n> +\tint ret = 0;\n>  \n>  \tstrbuf_vaddf(&sb, fmt, ap);\n>  \tif (!sb.len) {\n> @@ -59,9 +60,9 @@ static void status_vprintf(struct wt_status *s, int at_bol, const char *color,\n>  \t\t}\n>  \t\tcolor_print_strbuf(s->fp, color, &sb);\n>  \t\tif (trail)\n> -\t\t\tfprintf(s->fp, \"%s\", trail);\n> +\t\t\tret += fprintf(s->fp, \"%s\", trail);\n>  \t\tstrbuf_release(&sb);\n> -\t\treturn;\n> +\t\treturn ret;\n>  \t}\n>  \tfor (line = sb.buf; *line; line = eol + 1) {\n>  \t\teol = strchr(line, '\\n');\n> @@ -78,15 +79,16 @@ static void status_vprintf(struct wt_status *s, int at_bol, const char *color,\n>  \t\t\tstrbuf_addstr(&linebuf, line);\n>  \t\tcolor_print_strbuf(s->fp, color, &linebuf);\n>  \t\tif (eol)\n> -\t\t\tfprintf(s->fp, \"\\n\");\n> +\t\t\tret += fprintf(s->fp, \"\\n\");\n>  \t\telse\n>  \t\t\tbreak;\n>  \t\tat_bol = 1;\n>  \t}\n>  \tif (trail)\n> -\t\tfprintf(s->fp, \"%s\", trail);\n> +\t\tret += fprintf(s->fp, \"%s\", trail);\n>  \tstrbuf_release(&linebuf);\n>  \tstrbuf_release(&sb);\n> +\treturn ret;\n>  }\n>  \n>  void status_printf_ln(struct wt_status *s, const char *color,\n> @@ -834,6 +836,20 @@ static void wt_longstatus_print_submodule_summary(struct wt_status *s, int uncom\n>  \tstrbuf_release(&summary);\n>  }\n>  \n> +static struct wt_status *global_wt_status_hack;\n> +static int column_status_printf(const char *fmt, ...)\n> +{\n> +\tva_list ap;\n> +\tstruct wt_status *s = global_wt_status_hack;\n> +\tint ret;\n> +\n> +\tva_start(ap, fmt);\n> +\tret = status_vprintf(s, 0, \"\", fmt, ap, NULL);\n> +\tva_end(ap);\n> +\n> +\treturn ret;\n> +}\n> +\n>  static void wt_longstatus_print_other(struct wt_status *s,\n>  \t\t\t\t      struct string_list *l,\n>  \t\t\t\t      const char *what,\n> @@ -856,6 +872,7 @@ static void wt_longstatus_print_other(struct wt_status *s,\n>  \t\tpath = quote_path(it->string, s->prefix, &buf);\n>  \t\tif (column_active(s->colopts)) {\n>  \t\t\tstring_list_append(&output, path);\n> +\t\t\tglobal_wt_status_hack = s;\n>  \t\t\tcontinue;\n>  \t\t}\n>  \t\tstatus_printf(s, color(WT_STATUS_HEADER, s), \"\\t\");\n> @@ -876,6 +893,8 @@ static void wt_longstatus_print_other(struct wt_status *s,\n>  \tcopts.indent = buf.buf;\n>  \tif (want_color(s->use_color))\n>  \t\tcopts.nl = GIT_COLOR_RESET \"\\n\";\n> +\n> +\tcopts._printf = column_status_printf;\n\nThis is kinda ugly. I think status_vprintf() can handle multi-line\nstrings well. In that case maybe you just need to make\nstrbuf_print_columns() return a strbuf instead, then pass the entire\nstring to one status_vprintf() call.\n\nThere isn't need to abstract the printf() calls in column.c. Just\nchange it unconditionally to strbuf_addf() and print the whole thing\nout to stdout in the end in print_coluns(), or pass the strbuf back\nwith strbuf_print_columns().\n\nThe small delay before printing the first line (because we know buffer\neverything in strbuf first) won't be an issue because we already have\nto queue all items for layout before we can print anything anyway.\n\n>  \tprint_columns(&output, s->colopts, &copts);\n>  \tstring_list_clear(&output, 0);\n>  \tstrbuf_release(&buf);\n> -- \n> 2.12.2.511.g2abb8caf66\n> \n"}]}