{"thread":{"id":"22938","subject":"[PATCH 05/12] Add builtin command \"column\"","startedAt":"2010-03-07T12:09:33Z","lastAt":"2010-03-12T04:22:26Z","messageCount":24,"participants":["Nguyễn Thái Ngọc Duy","René Scharfe","Nguyen Thai Ngoc Duy","Junio C Hamano","Johannes Sixt"],"isPatch":true,"patchVersion":1,"patchTotal":12},"messages":[{"id":"136302","messageId":"1267963785-473-1-git-send-email-pclouds@gmail.com","threadId":"22938","inReplyTo":null,"subject":"[PATCH 00/12] Support columinized output in tag/branch/ls-files/grep","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-03-07T12:09:33Z","receivedAt":"2010-03-07T12:09:33Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"This adds support to show columnized output in the mentioned commands.\nI am quite happy with columnized \"git branch/tag\".\n\nThere is still room for improvement. For example, if \"git column\" is going to\ndisplay all items in one or two lines (too wide screen), then falling back to\none column mode would be better.\n\nI'm also experimenting aligned grep output.  While it's useful\nsometimes to look for things near the beginning of line, I don't know\nif it's really worth the effort.\n\nAnyway, enjoy the new output (Hmm.. \"git config -l\" may be applicable for\ncolumnization too)\n\nNguyễn Thái Ngọc Duy (12):\n  Move term_columns() to pager.c\n  setup_pager(): save terminal width before redirecting stdout\n  Add columnizer\n  help: use columnizer\n  Add builtin command \"column\"\n  Add helpers to redirect stdout to \"git column\"\n  add core.columns\n  tag: support column output with --columns\n  branch: support column output with --columns\n  ls-files: support column output with --columns\n  grep: do not return early in cmd_grep() if there is no error\n  grep: support column output with --columns\n\n .gitignore                   |    1 +\n Documentation/config.txt     |    8 ++\n Documentation/git-branch.txt |    8 ++\n Documentation/git-column.txt |   40 ++++++++++\n Documentation/git-grep.txt   |   10 +++\n Documentation/git-tag.txt    |   11 +++-\n Makefile                     |    3 +\n builtin.h                    |    1 +\n builtin/branch.c             |   18 ++++-\n builtin/column.c             |   42 +++++++++++\n builtin/grep.c               |   48 +++++++------\n builtin/ls-files.c           |   10 +++\n builtin/tag.c                |   17 ++++-\n cache.h                      |    2 +\n column.c                     |  164 ++++++++++++++++++++++++++++++++++++++++++\n column.h                     |   25 +++++++\n command-list.txt             |    1 +\n config.c                     |    6 ++\n environment.c                |    1 +\n git.c                        |    1 +\n help.c                       |   55 +++-----------\n pager.c                      |   95 ++++++++++++++++++++++++\n t/t9002-column.sh            |  101 ++++++++++++++++++++++++++\n 23 files changed, 595 insertions(+), 73 deletions(-)\n create mode 100644 Documentation/git-column.txt\n create mode 100644 builtin/column.c\n create mode 100644 column.c\n create mode 100644 column.h\n create mode 100755 t/t9002-column.sh\n"},{"id":"136307","messageId":"1267963785-473-2-git-send-email-pclouds@gmail.com","threadId":"22938","inReplyTo":"1267963785-473-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 01/12] Move term_columns() to pager.c","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-03-07T12:09:34Z","receivedAt":"2010-03-07T12:09:34Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n cache.h |    1 +\n help.c  |   22 ----------------------\n pager.c |   23 +++++++++++++++++++++++\n 3 files changed, 24 insertions(+), 22 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex 89f6a40..124f100 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -985,6 +985,7 @@ extern void setup_pager(void);\n extern const char *pager_program;\n extern int pager_in_use(void);\n extern int pager_use_color;\n+extern int term_columns();\n \n extern const char *editor_program;\n extern const char *excludes_file;\ndiff --git a/help.c b/help.c\nindex 7f4928e..888bf8c 100644\n--- a/help.c\n+++ b/help.c\n@@ -4,28 +4,6 @@\n #include \"levenshtein.h\"\n #include \"help.h\"\n \n-/* most GUI terminals set COLUMNS (although some don't export it) */\n-static int term_columns(void)\n-{\n-\tchar *col_string = getenv(\"COLUMNS\");\n-\tint n_cols;\n-\n-\tif (col_string && (n_cols = atoi(col_string)) > 0)\n-\t\treturn n_cols;\n-\n-#ifdef TIOCGWINSZ\n-\t{\n-\t\tstruct winsize ws;\n-\t\tif (!ioctl(1, TIOCGWINSZ, &ws)) {\n-\t\t\tif (ws.ws_col)\n-\t\t\t\treturn ws.ws_col;\n-\t\t}\n-\t}\n-#endif\n-\n-\treturn 80;\n-}\n-\n void add_cmdname(struct cmdnames *cmds, const char *name, int len)\n {\n \tstruct cmdname *ent = xmalloc(sizeof(*ent) + len + 1);\ndiff --git a/pager.c b/pager.c\nindex dac358f..fc6c3e0 100644\n--- a/pager.c\n+++ b/pager.c\n@@ -12,6 +12,7 @@\n  */\n \n static int spawned_pager;\n+static int max_columns;\n \n #ifndef WIN32\n static void pager_preexec(void)\n@@ -116,3 +117,25 @@ int pager_in_use(void)\n \tenv = getenv(\"GIT_PAGER_IN_USE\");\n \treturn env ? git_config_bool(\"GIT_PAGER_IN_USE\", env) : 0;\n }\n+\n+int term_columns()\n+{\n+\tchar *col_string = getenv(\"COLUMNS\");\n+\tint n_cols;\n+\n+\tif (col_string && (n_cols = atoi(col_string)) > 0)\n+\t\treturn n_cols;\n+\n+\telse if (spawned_pager && max_columns)\n+\t\treturn max_columns;\n+#ifdef TIOCGWINSZ\n+\telse {\n+\t\tstruct winsize ws;\n+\t\tif (!ioctl(1, TIOCGWINSZ, &ws)) {\n+\t\t\tif (ws.ws_col)\n+\t\t\t\treturn ws.ws_col;\n+\t\t}\n+\t}\n+#endif\n+\treturn 80;\n+}\n-- \n1.7.0.1.370.gd3c5\n"},{"id":"136301","messageId":"1267963785-473-3-git-send-email-pclouds@gmail.com","threadId":"22938","inReplyTo":"1267963785-473-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 02/12] setup_pager(): save terminal width before redirecting stdout","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-03-07T12:09:35Z","receivedAt":"2010-03-07T12:09:35Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"After redirecting, we may no longer read terminal width.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n pager.c |    9 +++++++++\n 1 files changed, 9 insertions(+), 0 deletions(-)\n\ndiff --git a/pager.c b/pager.c\nindex fc6c3e0..ad447cf 100644\n--- a/pager.c\n+++ b/pager.c\n@@ -81,6 +81,15 @@ void setup_pager(void)\n \n \tspawned_pager = 1; /* means we are emitting to terminal */\n \n+#ifdef TIOCGWINSZ\n+\t{\n+\t\tstruct winsize ws;\n+\t\tif (!ioctl(1, TIOCGWINSZ, &ws)) {\n+\t\t\tif (ws.ws_col)\n+\t\t\t\tmax_columns = ws.ws_col;\n+\t\t}\n+\t}\n+#endif\n \t/* spawn the pager */\n \tpager_argv[0] = pager;\n \tpager_process.use_shell = 1;\n-- \n1.7.0.1.370.gd3c5\n"},{"id":"136304","messageId":"1267963785-473-4-git-send-email-pclouds@gmail.com","threadId":"22938","inReplyTo":"1267963785-473-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 03/12] Add columnizer","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-03-07T12:09:36Z","receivedAt":"2010-03-07T12:09:36Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n .gitignore       |    1 +\n Makefile         |    2 +\n column.c         |  164 ++++++++++++++++++++++++++++++++++++++++++++++++++++++\n column.h         |   23 ++++++++\n command-list.txt |    1 +\n 5 files changed, 191 insertions(+), 0 deletions(-)\n create mode 100644 column.c\n create mode 100644 column.h\n\ndiff --git a/.gitignore b/.gitignore\nindex 7b3acb7..8e087e6 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -25,6 +25,7 @@\n /git-cherry-pick\n /git-clean\n /git-clone\n+/git-column\n /git-commit\n /git-commit-tree\n /git-config\ndiff --git a/Makefile b/Makefile\nindex 7358a20..337f5bf 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -454,6 +454,7 @@ LIB_H += builtin.h\n LIB_H += cache.h\n LIB_H += cache-tree.h\n LIB_H += color.h\n+LIB_H += column.h\n LIB_H += commit.h\n LIB_H += compat/bswap.h\n LIB_H += compat/cygwin.h\n@@ -526,6 +527,7 @@ LIB_OBJS += branch.o\n LIB_OBJS += bundle.o\n LIB_OBJS += cache-tree.o\n LIB_OBJS += color.o\n+LIB_OBJS += column.o\n LIB_OBJS += combine-diff.o\n LIB_OBJS += commit.o\n LIB_OBJS += config.o\ndiff --git a/column.c b/column.c\nnew file mode 100644\nindex 0000000..0e88763\n--- /dev/null\n+++ b/column.c\n@@ -0,0 +1,164 @@\n+#include \"cache.h\"\n+#include \"column.h\"\n+\n+static int ansi_length(const char *s)\n+{\n+\tint a_len = 0;\n+\n+\twhile ((s = strstr(s, \"\\033[\")) != NULL) {\n+\t\tint len = strspn(s+2, \"0123456789;\");\n+\t\ts += len+3; /* \\033[<len><func char> */\n+\t\ta_len += len+3;\n+\t}\n+\treturn a_len;\n+}\n+\n+static void print_row(struct columnizer *cp, int row)\n+{\n+\tint mode = cp->flags & COLUMNIZER_MODE_MASK;\n+\tint j;\n+\n+\tif (cp->left_space)\n+\t\tprintf(\"%-*s\", cp->left_space, \"\");\n+\n+\tfor (j = 0; j < cp->nr_cols; j++) {\n+\t\tint n, size;\n+\n+\t\tswitch (mode) {\n+\t\tcase COLUMNIZER_COLUMN_FIRST:\n+\t\t\tn = j * cp->nr_rows + row;\n+\t\t\tsize = cp->column_width;\n+\t\t\tbreak;\n+\t\tcase COLUMNIZER_ROW_FIRST:\n+\t\t\tn = row * cp->nr_cols + j;\n+\t\t\tsize = cp->column_width;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tif (n >= cp->cells_nr)\n+\t\t\tbreak;\n+\n+\t\tsize += cp->space;\n+\t\tif (cp->flags & COLUMNIZER_HAVE_ANSI)\n+\t\t\tsize += ansi_length(cp->cells[n]);\n+\t\tif (j == cp->nr_cols-1)\n+\t\t\tsize = 1;\n+\t\tprintf(\"%-*s\", size, cp->cells[n]);\n+\t}\n+\tputchar('\\n');\n+}\n+\n+static void calculate_column_width(struct columnizer *cp)\n+{\n+\tint max_cols, longest;\n+\n+\tif (cp->flags & COLUMNIZER_READY)\n+\t\treturn;\n+\n+\tif (!cp->terminal_width)\n+\t\tcp->terminal_width = term_columns();\n+\n+\tif (cp->column_width)\n+\t\tlongest = cp->column_width;\n+\telse {\n+\t\tint i, len;\n+\t\tlongest = 0;\n+\t\tfor (i = 0; i < cp->cells_nr; i++) {\n+\t\t\tlen = strlen(cp->cells[i]);\n+\t\t\tif (cp->flags & COLUMNIZER_HAVE_ANSI)\n+\t\t\t\tlen -= ansi_length(cp->cells[i]);\n+\t\t\tif (longest < len)\n+\t\t\t\tlongest = len;\n+\t\t}\n+\t}\n+\n+\tmax_cols = cp->terminal_width - 1; /* don't print *on* the edge */\n+\tmax_cols -= cp->left_space + cp->right_space;\n+\n+\t/* we don't have space after the last column */\n+\tmax_cols += cp->space;\n+\n+\tcp->nr_cols = (longest + cp->space) < max_cols ? max_cols / (longest + cp->space) : 1;\n+\tcp->nr_rows = DIV_ROUND_UP(cp->cells_nr, cp->nr_cols);\n+\tif (!cp->column_width)\n+\t\tcp->column_width = max_cols / cp->nr_cols - cp->space;\n+\tcp->flags |= COLUMNIZER_READY;\n+}\n+\n+static int feed_cell(struct columnizer *cp, char *cell)\n+{\n+\tint len;\n+\n+\t/* Non-homogeneous column is not supported yet */\n+\tif (!(cp->flags & COLUMNIZER_HOMOGENEOUS))\n+\t\treturn -1;\n+\n+\tif (!cell) {\t\t/* EOF */\n+\t\tint i;\n+\n+\t\tcalculate_column_width(cp);\n+\t\tfor (i = 0;i < cp->nr_rows; i++)\n+\t\t\tprint_row(cp, i);\n+\t\treturn 0;\n+\t}\n+\n+\tcp->cells_nr++;\n+\tALLOC_GROW(cp->cells, cp->cells_nr, cp->cells_alloc);\n+\tcp->cells[cp->cells_nr-1] = cell;\n+\n+\tlen = strlen(cell);\n+\tif (cp->flags & COLUMNIZER_HAVE_ANSI)\n+\t\tlen -= ansi_length(cell);\n+\n+\tif (!cp->terminal_width)\n+\t\tcp->terminal_width = term_columns();\n+\tif (cp->longest < len)\n+\t\tcp->longest = len;\n+\n+\t/* Can't have more than one column? */\n+\tif (cp->terminal_width < cp->left_space+cp->longest*2+cp->space+cp->right_space) {\n+\t\tint i;\n+\t\tfor (i = 0;i < cp->cells_nr;i++) {\n+\t\t\tif (cp->left_space)\n+\t\t\t\tprintf(\"%-*s\", cp->left_space, \"\");\n+\t\t\tprintf(\"%s\\n\", cp->cells[i]);\n+\t\t\tif (cp->detach)\n+\t\t\t\tcp->detach(cp->cells[i]);\n+\t\t}\n+\t\tfree(cp->cells);\n+\t\tcp->cells_alloc = cp->cells_nr = 0;\n+\n+\t\tcp->nr_cols = 1;\n+\t\tcp->flags |= COLUMNIZER_READY;\n+\t}\n+\treturn 0;\n+}\n+\n+int feed_columnizer(struct columnizer *cp, char *cell)\n+{\n+\tint ret;\n+\n+\t/* Degradation case, no special layout needed */\n+\tif (cp->flags & COLUMNIZER_READY && cp->nr_cols == 1) {\n+\t\tif (cell) {\n+\t\t\tif (cp->left_space)\n+\t\t\t\tprintf(\"%-*s\", cp->left_space, \"\");\n+\t\t\tprintf(\"%s\\n\", cell);\n+\t\t}\n+\t\tret = 0;\n+\t}\n+\telse\n+\t\tret = feed_cell(cp, cell);\n+\n+\tif (!cell) {\t\t/* EOF, cleanup */\n+\t\tif (cp->detach) {\n+\t\t\tint i;\n+\t\t\tfor (i = 0;i < cp->cells_nr;i++)\n+\t\t\t\tcp->detach(cp->cells[i]);\n+\t\t}\n+\t\tif (cp->cells_alloc)\n+\t\t\tfree(cp->cells);\n+\t}\n+\n+\treturn ret;\n+}\ndiff --git a/column.h b/column.h\nnew file mode 100644\nindex 0000000..28122e0\n--- /dev/null\n+++ b/column.h\n@@ -0,0 +1,23 @@\n+#define COLUMNIZER_MODE_MASK    0x000F\n+#define COLUMNIZER_COLUMN_FIRST      0\n+#define COLUMNIZER_ROW_FIRST         1\n+\n+#define COLUMNIZER_HOMOGENEOUS  0x0010\n+#define COLUMNIZER_HAVE_ANSI    0x0020\n+#define COLUMNIZER_READY        0x0040\n+\n+struct columnizer {\n+\tint flags;\n+\tint terminal_width, column_width;\n+\tint left_space, right_space, space;\n+\tvoid (*detach)(void *p);\n+\n+\t/* private variables */\n+\tchar **cells;\n+\tint cells_nr, cells_alloc;\n+\tint nr_cols, nr_rows;\n+\n+\tint longest;\n+};\n+\n+extern int feed_columnizer(struct columnizer *cp, char *cell);\ndiff --git a/command-list.txt b/command-list.txt\nindex 95bf18c..5d6bfc8 100644\n--- a/command-list.txt\n+++ b/command-list.txt\n@@ -20,6 +20,7 @@ git-cherry-pick                         mainporcelain\n git-citool                              mainporcelain\n git-clean                               mainporcelain\n git-clone                               mainporcelain common\n+git-column                              purehelpers\n git-commit                              mainporcelain common\n git-commit-tree                         plumbingmanipulators\n git-config                              ancillarymanipulators\n-- \n1.7.0.1.370.gd3c5\n"},{"id":"136300","messageId":"1267963785-473-5-git-send-email-pclouds@gmail.com","threadId":"22938","inReplyTo":"1267963785-473-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 04/12] help: use columnizer","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-03-07T12:09:37Z","receivedAt":"2010-03-07T12:09:37Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n help.c |   33 +++++++++++----------------------\n 1 files changed, 11 insertions(+), 22 deletions(-)\n\ndiff --git a/help.c b/help.c\nindex 888bf8c..e039c14 100644\n--- a/help.c\n+++ b/help.c\n@@ -3,6 +3,7 @@\n #include \"exec_cmd.h\"\n #include \"levenshtein.h\"\n #include \"help.h\"\n+#include \"column.h\"\n \n void add_cmdname(struct cmdnames *cmds, const char *name, int len)\n {\n@@ -71,29 +72,17 @@ void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes)\n \n static void pretty_print_string_list(struct cmdnames *cmds, int longest)\n {\n-\tint cols = 1, rows;\n-\tint space = longest + 1; /* min 1 SP between words */\n-\tint max_cols = term_columns() - 1; /* don't print *on* the edge */\n-\tint i, j;\n-\n-\tif (space < max_cols)\n-\t\tcols = max_cols / space;\n-\trows = DIV_ROUND_UP(cmds->cnt, cols);\n+\tstruct columnizer cp;\n+\tint i;\n \n-\tfor (i = 0; i < rows; i++) {\n-\t\tprintf(\"  \");\n+\tmemset(&cp, 0, sizeof(cp));\n+\tcp.flags |= COLUMNIZER_HOMOGENEOUS | COLUMNIZER_COLUMN_FIRST;\n+\tcp.space = 1;\n+\tcp.left_space = 2;\n \n-\t\tfor (j = 0; j < cols; j++) {\n-\t\t\tint n = j * rows + i;\n-\t\t\tint size = space;\n-\t\t\tif (n >= cmds->cnt)\n-\t\t\t\tbreak;\n-\t\t\tif (j == cols-1 || n + rows >= cmds->cnt)\n-\t\t\t\tsize = 1;\n-\t\t\tprintf(\"%-*s\", size, cmds->names[n]->name);\n-\t\t}\n-\t\tputchar('\\n');\n-\t}\n+\tfor (i = 0; i < cmds->cnt; i++)\n+\t\tfeed_columnizer(&cp, cmds->names[i]->name);\n+\tfeed_columnizer(&cp, NULL);\n }\n \n static int is_executable(const char *name)\n-- \n1.7.0.1.370.gd3c5\n"},{"id":"136299","messageId":"1267963785-473-6-git-send-email-pclouds@gmail.com","threadId":"22938","inReplyTo":"1267963785-473-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 05/12] Add builtin command \"column\"","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-03-07T12:09:38Z","receivedAt":"2010-03-07T12:09:38Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Documentation/git-column.txt |   40 ++++++++++++++++\n Makefile                     |    1 +\n builtin.h                    |    1 +\n builtin/column.c             |   42 +++++++++++++++++\n git.c                        |    1 +\n t/t9002-column.sh            |  101 ++++++++++++++++++++++++++++++++++++++++++\n 6 files changed, 186 insertions(+), 0 deletions(-)\n create mode 100644 Documentation/git-column.txt\n create mode 100644 builtin/column.c\n create mode 100755 t/t9002-column.sh\n\ndiff --git a/Documentation/git-column.txt b/Documentation/git-column.txt\nnew file mode 100644\nindex 0000000..3ee887f\n--- /dev/null\n+++ b/Documentation/git-column.txt\n@@ -0,0 +1,40 @@\n+git-column(1)\n+=============\n+\n+NAME\n+----\n+git-column - Columnate lists\n+\n+SYNOPSIS\n+--------\n+[verse]\n+'git column' [--mode=<mode>] [--width=<width>] [--left-space=<N>] [--right-space=<N>]\n+\n+DESCRIPTION\n+-----------\n+This command formats its input into multiple columns. Rows are filled before\n+columns.\n+\n+OPTIONS\n+-------\n+--width=<width>::\n+\tSpecify the terminal width. By default 'git column' will detect the\n+\tterminal width, or fall back to 80 if it is unable to do so.\n+\n+--left-space=<N>::\n+\tPrepend a number of spaces on the first column.\n+\n+--right-space=<N>::\n+\tAppend a number of spaces after the last column.\n+\n+--mode=<mode>::\n+\tWhich layout mode to use. Supported modes are 'row' (default mode,\n+\tfill rows first) and 'column' (fill columns first)\n+\n+Author\n+------\n+Written by Nguyen Thai Ngoc Duy <pclouds@gmail.com>\n+\n+GIT\n+---\n+Part of the linkgit:git[1] suite\ndiff --git a/Makefile b/Makefile\nindex 337f5bf..53686a2 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -640,6 +640,7 @@ BUILTIN_OBJS += builtin/checkout-index.o\n BUILTIN_OBJS += builtin/checkout.o\n BUILTIN_OBJS += builtin/clean.o\n BUILTIN_OBJS += builtin/clone.o\n+BUILTIN_OBJS += builtin/column.o\n BUILTIN_OBJS += builtin/commit-tree.o\n BUILTIN_OBJS += builtin/commit.o\n BUILTIN_OBJS += builtin/config.o\ndiff --git a/builtin.h b/builtin.h\nindex cdf9847..c68c758 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -39,6 +39,7 @@ extern int cmd_cherry(int argc, const char **argv, const char *prefix);\n extern int cmd_cherry_pick(int argc, const char **argv, const char *prefix);\n extern int cmd_clone(int argc, const char **argv, const char *prefix);\n extern int cmd_clean(int argc, const char **argv, const char *prefix);\n+extern int cmd_column(int argc, const char **argv, const char *prefix);\n extern int cmd_commit(int argc, const char **argv, const char *prefix);\n extern int cmd_commit_tree(int argc, const char **argv, const char *prefix);\n extern int cmd_count_objects(int argc, const char **argv, const char *prefix);\ndiff --git a/builtin/column.c b/builtin/column.c\nnew file mode 100644\nindex 0000000..d5d7f80\n--- /dev/null\n+++ b/builtin/column.c\n@@ -0,0 +1,42 @@\n+#include \"cache.h\"\n+#include \"strbuf.h\"\n+#include \"parse-options.h\"\n+#include \"column.h\"\n+\n+static const char * const builtin_column_usage[] = {\n+\t\"git column [--mode=<mode>] [--width=<width>] [--left-space=<N>] [--right-space=<N>]\",\n+\tNULL\n+};\n+\n+int cmd_column(int argc, const char **argv, const char *prefix)\n+{\n+\tstruct columnizer cp;\n+\tconst char *mode = NULL;\n+\tstruct strbuf sb = STRBUF_INIT;\n+\tstruct option options[] = {\n+\t\tOPT_INTEGER(0, \"width\", &cp.terminal_width, \"Maximum width\"),\n+\t\tOPT_INTEGER(0, \"left-space\", &cp.left_space, \"Padding space on left border\"),\n+\t\tOPT_INTEGER(0, \"right-space\", &cp.right_space, \"Padding space on right border\"),\n+\t\tOPT_STRING(0, \"mode\", &mode, \"mode\", \"Which layout mode to use\"),\n+\t\tOPT_END()\n+\t};\n+\n+\tmemset(&cp, 0, sizeof(cp));\n+\tcp.space = 1;\n+\tcp.detach = free;\n+\n+\targc = parse_options(argc, argv, prefix, options, builtin_column_usage, 0);\n+\n+\tif (!mode || !strcmp(mode, \"column\"))\n+\t\tcp.flags = COLUMNIZER_COLUMN_FIRST | COLUMNIZER_HAVE_ANSI | COLUMNIZER_HOMOGENEOUS;\n+\telse if (!strcmp(mode, \"row\"))\n+\t\tcp.flags = COLUMNIZER_ROW_FIRST | COLUMNIZER_HAVE_ANSI | COLUMNIZER_HOMOGENEOUS;\n+\telse\n+\t\tdie(\"Invalid mode '%s'\", mode);\n+\n+\twhile (!strbuf_getline(&sb, stdin, '\\n'))\n+\t\tfeed_columnizer(&cp, strbuf_detach(&sb, NULL));\n+\n+\tfeed_columnizer(&cp, NULL);\n+\treturn 0;\n+}\ndiff --git a/git.c b/git.c\nindex 6bae305..8dc6fdd 100644\n--- a/git.c\n+++ b/git.c\n@@ -301,6 +301,7 @@ static void handle_internal_command(int argc, const char **argv)\n \t\t{ \"cherry-pick\", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },\n \t\t{ \"clone\", cmd_clone },\n \t\t{ \"clean\", cmd_clean, RUN_SETUP | NEED_WORK_TREE },\n+\t\t{ \"column\", cmd_column },\n \t\t{ \"commit\", cmd_commit, RUN_SETUP | NEED_WORK_TREE },\n \t\t{ \"commit-tree\", cmd_commit_tree, RUN_SETUP },\n \t\t{ \"config\", cmd_config },\ndiff --git a/t/t9002-column.sh b/t/t9002-column.sh\nnew file mode 100755\nindex 0000000..b5b46fc\n--- /dev/null\n+++ b/t/t9002-column.sh\n@@ -0,0 +1,101 @@\n+#!/bin/sh\n+\n+test_description='git column'\n+. ./test-lib.sh\n+\n+cat >lista <<\\EOF\n+one\n+two\n+three\n+four\n+five\n+six\n+seven\n+eight\n+nine\n+ten\n+EOF\n+\n+cat >expected <<\\EOF\n+one   two   three four  five  six   seven eight nine  ten   \n+EOF\n+test_expect_success '80 columns' '\n+\tCOLUMNS=80 git column < lista > actual &&\n+\ttest_cmp expected actual\n+'\n+\n+cat >expected <<\\EOF\n+one\n+two\n+three\n+four\n+five\n+six\n+seven\n+eight\n+nine\n+ten\n+EOF\n+test_expect_success '1 column' '\n+\tCOLUMNS=1 git column < lista > actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success '1 column (--width)' '\n+\tgit column --width=1 < lista > actual &&\n+\ttest_cmp expected actual\n+'\n+\n+COLUMNS=20\n+export COLUMNS\n+\n+cat >expected <<\\EOF\n+one   five  nine\n+two   six   ten\n+three seven \n+four  eight \n+EOF\n+test_expect_success '20 columns' '\n+\tgit column < lista > actual &&\n+\ttest_cmp expected actual\n+'\n+\n+cat >expected <<\\EOF\n+one   two   three\n+four  five  six\n+seven eight nine\n+ten   \n+EOF\n+test_expect_success '20 columns, row mode' '\n+\tgit column --mode=row < lista > actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'unsupported mode' '\n+\ttest_must_fail git column --mode=foo\n+'\n+\n+cat >expected <<\\EOF\n+  one   five  nine\n+  two   six   ten\n+  three seven \n+  four  eight \n+EOF\n+test_expect_success '20 columns, left indented' '\n+\tgit column --left-space=2 < lista > actual &&\n+\ttest_cmp expected actual\n+'\n+\n+cat >expected <<\\EOF\n+one     six\n+two     seven\n+three   eight\n+four    nine\n+five    ten\n+EOF\n+test_expect_success '20 columns, right indented' '\n+\tgit column --right-space=3 < lista > actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_done\n-- \n1.7.0.1.370.gd3c5\n"},{"id":"136305","messageId":"1267963785-473-7-git-send-email-pclouds@gmail.com","threadId":"22938","inReplyTo":"1267963785-473-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 06/12] Add helpers to redirect stdout to \"git column\"","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-03-07T12:09:39Z","receivedAt":"2010-03-07T12:09:39Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"While the columnizer can be used directly, it requires output code\nchange. The helpers instead redirect all output to \"git column\" and\nlet \"git column\" do all the layout work. This keeps code change\nminimum. All we need is:\n\nstart_columnizer();\n/* do some complex computation and output to stdout */\nstop_columnizer();\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n column.h |    2 +\n pager.c  |   63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 65 insertions(+), 0 deletions(-)\n\ndiff --git a/column.h b/column.h\nindex 28122e0..6eb19e3 100644\n--- a/column.h\n+++ b/column.h\n@@ -21,3 +21,5 @@ struct columnizer {\n };\n \n extern int feed_columnizer(struct columnizer *cp, char *cell);\n+extern int start_columnizer(const char **argv);\n+extern int stop_columnizer();\ndiff --git a/pager.c b/pager.c\nindex ad447cf..9df727d 100644\n--- a/pager.c\n+++ b/pager.c\n@@ -13,6 +13,8 @@\n \n static int spawned_pager;\n static int max_columns;\n+static int fd_out = -1;\n+static struct child_process column_process;\n \n #ifndef WIN32\n static void pager_preexec(void)\n@@ -148,3 +150,64 @@ int term_columns()\n #endif\n \treturn 80;\n }\n+\n+int start_columnizer(const char **argv)\n+{\n+\tint new_argc, argc = 0;\n+\tconst char **column_argv;\n+\tchar columns_param[32];\n+\n+\tif (fd_out != -1)\n+\t\treturn -1;\n+\n+\tif (argv) {\n+\t\twhile (argv[argc])\n+\t\t\targc++;\n+\t}\n+\tnew_argc = argc + 1; /* argv[0] = \"column\" */\n+\tif (spawned_pager && max_columns) {\n+\t\tsprintf(columns_param, \"--width=%d\", max_columns);\n+\t\tnew_argc++;\n+\t}\n+\n+\tcolumn_argv = xmalloc(sizeof(*column_argv)*(new_argc+1));\n+\tcolumn_argv[0] = \"column\";\n+\tif (spawned_pager && max_columns)\n+\t\tcolumn_argv[1] = columns_param;\n+\tif (argv)\n+\t\tmemcpy(column_argv + (new_argc-argc), argv, argc*sizeof(*argv));\n+\tcolumn_argv[new_argc] = NULL;\n+\n+\tfflush(stdout);\n+\tmemset(&column_process, 0, sizeof(column_process));\n+\tcolumn_process.in = -1;\n+\tcolumn_process.out = dup(1);\n+\tcolumn_process.git_cmd = 1;\n+\tcolumn_process.argv = column_argv;\n+\n+\tif (start_command(&column_process)) {\n+\t\tfree(column_argv);\n+\t\treturn -2;\n+\t}\n+\tfree(column_argv);\n+\n+\tfd_out = dup(1);\n+\tclose(1);\n+\tdup2(column_process.in, 1);\n+\tclose(column_process.in);\n+\treturn 0;\n+}\n+\n+int stop_columnizer()\n+{\n+\tif (fd_out == -1)\n+\t\treturn -1;\n+\n+\tfflush(stdout);\n+\tclose(1);\n+\tfinish_command(&column_process);\n+\tdup2(fd_out, 1);\n+\tclose(fd_out);\n+\tfd_out = -1;\n+\treturn 0;\n+}\n-- \n1.7.0.1.370.gd3c5\n"},{"id":"136303","messageId":"1267963785-473-8-git-send-email-pclouds@gmail.com","threadId":"22938","inReplyTo":"1267963785-473-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 07/12] add core.columns","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-03-07T12:09:40Z","receivedAt":"2010-03-07T12:09:40Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Documentation/config.txt |    8 ++++++++\n cache.h                  |    1 +\n config.c                 |    6 ++++++\n environment.c            |    1 +\n 4 files changed, 16 insertions(+), 0 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex c80262b..d299eaf 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -533,6 +533,14 @@ core.sparseCheckout::\n \tEnable \"sparse checkout\" feature. See section \"Sparse checkout\" in\n \tlinkgit:git-read-tree[1] for more information.\n \n+core.columns::\n+\tSpecify whether a command should output in columns. Only commands\n+\tthat support `--columns` will be affected by this. This variable can\n+\ttake either `never` (do not output in columns), `auto` (output in\n+\tcolumns if the output is to a terminal) or `always` (always output in\n+\tcolumns). Setting `--columns` or `--no-columns` will override this\n+\tvariable. This option defaults to never.\n+\n add.ignore-errors::\n \tTells 'git add' to continue adding files when some files cannot be\n \tadded due to indexing errors. Equivalent to the '--ignore-errors'\ndiff --git a/cache.h b/cache.h\nindex 124f100..84211d2 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -549,6 +549,7 @@ extern int read_replace_refs;\n extern int fsync_object_files;\n extern int core_preload_index;\n extern int core_apply_sparse_checkout;\n+extern int core_column_output;\n \n enum safe_crlf {\n \tSAFE_CRLF_FALSE = 0,\ndiff --git a/config.c b/config.c\nindex 6963fbe..602c4f6 100644\n--- a/config.c\n+++ b/config.c\n@@ -7,6 +7,7 @@\n  */\n #include \"cache.h\"\n #include \"exec_cmd.h\"\n+#include \"color.h\"\n \n #define MAXNAME (256)\n \n@@ -523,6 +524,11 @@ static int git_default_core_config(const char *var, const char *value)\n \t\treturn 0;\n \t}\n \n+\tif (!strcmp(var, \"core.columns\")) {\n+\t\tcore_column_output = git_config_colorbool(var, value, -1);\n+\t\treturn 0;\n+\t}\n+\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 876c5e5..4329435 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -52,6 +52,7 @@ enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;\n char *notes_ref_name;\n int grafts_replace_parents = 1;\n int core_apply_sparse_checkout;\n+int core_column_output;\n \n /* Parallel index stat data preload? */\n int core_preload_index = 0;\n-- \n1.7.0.1.370.gd3c5\n"},{"id":"136310","messageId":"1267963785-473-9-git-send-email-pclouds@gmail.com","threadId":"22938","inReplyTo":"1267963785-473-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 08/12] tag: support column output with --columns","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-03-07T12:09:41Z","receivedAt":"2010-03-07T12:09:41Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Documentation/git-tag.txt |   11 ++++++++++-\n builtin/tag.c             |   17 ++++++++++++++---\n 2 files changed, 24 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt\nindex 31c78a8..1ef8df2 100644\n--- a/Documentation/git-tag.txt\n+++ b/Documentation/git-tag.txt\n@@ -12,7 +12,8 @@ SYNOPSIS\n 'git tag' [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>]\n \t<tagname> [<commit> | <object>]\n 'git tag' -d <tagname>...\n-'git tag' [-n[<num>]] -l [--contains <commit>] [<pattern>]\n+'git tag' [-n[<num>]] -l [--columns | --no-columns]\n+\t[--contains <commit>] [<pattern>]\n 'git tag' -v <tagname>...\n \n DESCRIPTION\n@@ -71,6 +72,14 @@ OPTIONS\n \tList tags with names that match the given pattern (or all if no pattern is given).\n \tTyping \"git tag\" without arguments, also lists all tags.\n \n+--columns::\n+\tShow tags in columns. This option is only applicable if `git tag` is\n+\tused to list tags.\n+\n+--no-columns::\n+\tShow tags in a single list. This option is used to override core.columns\n+\tif set. This option is only applicable if `git tag` is used to list tags.\n+\n --contains <commit>::\n \tOnly list tags which contain the specified commit.\n \ndiff --git a/builtin/tag.c b/builtin/tag.c\nindex 4ef1c4f..1304bec 100644\n--- a/builtin/tag.c\n+++ b/builtin/tag.c\n@@ -12,6 +12,7 @@\n #include \"tag.h\"\n #include \"run-command.h\"\n #include \"parse-options.h\"\n+#include \"column.h\"\n \n static const char * const git_tag_usage[] = {\n \t\"git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]\",\n@@ -369,7 +370,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \tstruct ref_lock *lock;\n \n \tint annotate = 0, sign = 0, force = 0, lines = -1,\n-\t\tlist = 0, delete = 0, verify = 0;\n+\t\tlist = 0, delete = 0, verify = 0, column_output = 0;\n \tconst char *msgfile = NULL, *keyid = NULL;\n \tstruct msg_arg msg = { 0, STRBUF_INIT };\n \tstruct commit_list *with_commit = NULL;\n@@ -391,6 +392,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \t\tOPT_STRING('u', NULL, &keyid, \"key-id\",\n \t\t\t\t\t\"use another key to sign the tag\"),\n \t\tOPT_BOOLEAN('f', \"force\", &force, \"replace the tag if exists\"),\n+\t\tOPT_BOOLEAN(0, \"columns\", &column_output, \"show tag list in columns\"),\n \n \t\tOPT_GROUP(\"Tag listing options\"),\n \t\t{\n@@ -403,6 +405,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \t};\n \n \tgit_config(git_tag_config, NULL);\n+\tcolumn_output = core_column_output;\n \n \targc = parse_options(argc, argv, prefix, options, git_tag_usage, 0);\n \n@@ -421,9 +424,17 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \n \tif (list + delete + verify > 1)\n \t\tusage_with_options(git_tag_usage, options);\n-\tif (list)\n-\t\treturn list_tags(argv[0], lines == -1 ? 0 : lines,\n+\tif (list) {\n+\t\tint ret;\n+\n+\t\tif (column_output)\n+\t\t\tstart_columnizer(NULL);\n+\t\tret =  list_tags(argv[0], lines == -1 ? 0 : lines,\n \t\t\t\t with_commit);\n+\t\tif (column_output)\n+\t\t\tstop_columnizer();\n+\t\treturn ret;\n+\t}\n \tif (lines != -1)\n \t\tdie(\"-n option is only allowed with -l.\");\n \tif (with_commit)\n-- \n1.7.0.1.370.gd3c5\n"},{"id":"136309","messageId":"1267963785-473-10-git-send-email-pclouds@gmail.com","threadId":"22938","inReplyTo":"1267963785-473-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 09/12] branch: support column output with --columns","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-03-07T12:09:42Z","receivedAt":"2010-03-07T12:09:42Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Documentation/git-branch.txt |    8 ++++++++\n builtin/branch.c             |   18 +++++++++++++++---\n 2 files changed, 23 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt\nindex 903a690..3d1d600 100644\n--- a/Documentation/git-branch.txt\n+++ b/Documentation/git-branch.txt\n@@ -9,6 +9,7 @@ SYNOPSIS\n --------\n [verse]\n 'git branch' [--color[=<when>] | --no-color] [-r | -a]\n+\t[--columns | --no-columns]\n \t[-v [--abbrev=<length> | --no-abbrev]]\n \t[(--merged | --no-merged | --contains) [<commit>]]\n 'git branch' [--set-upstream | --track | --no-track] [-l] [-f] <branchname> [<start-point>]\n@@ -93,6 +94,13 @@ OPTIONS\n \tdefault to color output.\n \tSame as `--color=never`.\n \n+--columns::\n+\tShow branches in columns. This option is ignored in verbose mode.\n+\n+--no-columns::\n+\tShow branches in a single list. This option is used to override\n+\tcore.columns if set.\n+\n -r::\n \tList or delete (if used with -d) the remote-tracking branches.\n \ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex 6cf7e72..16273cb 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -15,6 +15,7 @@\n #include \"branch.h\"\n #include \"diff.h\"\n #include \"revision.h\"\n+#include \"column.h\"\n \n static const char * const builtin_branch_usage[] = {\n \t\"git branch [options] [-r | -a] [--merged | --no-merged]\",\n@@ -598,7 +599,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n {\n \tint delete = 0, rename = 0, force_create = 0;\n \tint verbose = 0, abbrev = DEFAULT_ABBREV, detached = 0;\n-\tint reflog = 0;\n+\tint reflog = 0, column_output = 0;\n \tenum branch_track track;\n \tint kinds = REF_LOCAL_BRANCH;\n \tstruct commit_list *with_commit = NULL;\n@@ -648,10 +649,12 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \t\t\tPARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG,\n \t\t\topt_parse_merge_filter, (intptr_t) \"HEAD\",\n \t\t},\n+\t\tOPT_BOOLEAN(0, \"columns\", &column_output, \"list branches in columns\"),\n \t\tOPT_END(),\n \t};\n \n \tgit_config(git_branch_config, NULL);\n+\tcolumn_output = core_column_output;\n \n \tif (branch_use_color == -1)\n \t\tbranch_use_color = git_use_color_default;\n@@ -678,8 +681,17 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \n \tif (delete)\n \t\treturn delete_branches(argc, argv, delete > 1, kinds);\n-\telse if (argc == 0)\n-\t\tprint_ref_list(kinds, detached, verbose, abbrev, with_commit);\n+\telse if (argc == 0) {\n+\t\tif (verbose)\n+\t\t\tprint_ref_list(kinds, detached, verbose, abbrev, with_commit);\n+\t\telse {\n+\t\t\tif (column_output)\n+\t\t\t\tstart_columnizer(NULL);\n+\t\t\tprint_ref_list(kinds, detached, verbose, abbrev, with_commit);\n+\t\t\tif (column_output)\n+\t\t\t\tstop_columnizer();\n+\t\t}\n+\t}\n \telse if (rename && (argc == 1))\n \t\trename_branch(head, argv[0], rename > 1);\n \telse if (rename && (argc == 2))\n-- \n1.7.0.1.370.gd3c5\n"},{"id":"136311","messageId":"1267963785-473-11-git-send-email-pclouds@gmail.com","threadId":"22938","inReplyTo":"1267963785-473-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 10/12] ls-files: support column output with --columns","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-03-07T12:09:43Z","receivedAt":"2010-03-07T12:09:43Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin/ls-files.c |   10 ++++++++++\n 1 files changed, 10 insertions(+), 0 deletions(-)\n\ndiff --git a/builtin/ls-files.c b/builtin/ls-files.c\nindex b065061..10cb057 100644\n--- a/builtin/ls-files.c\n+++ b/builtin/ls-files.c\n@@ -13,6 +13,7 @@\n #include \"parse-options.h\"\n #include \"resolve-undo.h\"\n #include \"string-list.h\"\n+#include \"column.h\"\n \n static int abbrev;\n static int show_deleted;\n@@ -33,6 +34,7 @@ static int error_unmatch;\n static char *ps_matched;\n static const char *with_tree;\n static int exc_given;\n+static int show_colums = 0;\n \n static const char *tag_cached = \"\";\n static const char *tag_unmerged = \"\";\n@@ -514,6 +516,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)\n \t\t\t\"if any <file> is not in the index, treat this as an error\"),\n \t\tOPT_STRING(0, \"with-tree\", &with_tree, \"tree-ish\",\n \t\t\t\"pretend that paths removed since <tree-ish> are still present\"),\n+\t\tOPT_BOOLEAN(0, \"columns\", &show_colums, \"show files in columns\"),\n \t\tOPT__ABBREV(&abbrev),\n \t\tOPT_END()\n \t};\n@@ -589,6 +592,10 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)\n \t\t\tdie(\"ls-files --with-tree is incompatible with -s or -u\");\n \t\toverlay_tree_on_cache(with_tree, prefix);\n \t}\n+\n+\tif (show_colums)\n+\t\tstart_columnizer(NULL);\n+\n \tshow_files(&dir, prefix);\n \tif (show_resolve_undo)\n \t\tshow_ru_info(prefix);\n@@ -602,5 +609,8 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)\n \t\treturn bad ? 1 : 0;\n \t}\n \n+\tif (show_colums)\n+\t\tstop_columnizer();\n+\n \treturn 0;\n }\n-- \n1.7.0.1.370.gd3c5\n"},{"id":"136308","messageId":"1267963785-473-12-git-send-email-pclouds@gmail.com","threadId":"22938","inReplyTo":"1267963785-473-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 11/12] grep: do not return early in cmd_grep() if there is no error","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-03-07T12:09:44Z","receivedAt":"2010-03-07T12:09:44Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin/grep.c |   39 +++++++++++++++++----------------------\n 1 files changed, 17 insertions(+), 22 deletions(-)\n\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex 40b9a93..b8a1d5c 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -568,7 +568,6 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)\n \t\tif (hit && opt->status_only)\n \t\t\tbreak;\n \t}\n-\tfree_grep_patterns(opt);\n \treturn hit;\n }\n \n@@ -969,7 +968,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \t}\n \n \tif (!use_index) {\n-\t\tint hit;\n \t\tif (cached)\n \t\t\tdie(\"--cached cannot be used with --no-index.\");\n \t\tif (list.nr)\n@@ -977,35 +975,32 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \t\thit = grep_directory(&opt, paths);\n \t\tif (use_threads)\n \t\t\thit |= wait_all();\n-\t\treturn !hit;\n \t}\n-\n-\tif (!list.nr) {\n-\t\tint hit;\n+\telse if (!list.nr) {\n \t\tif (!cached)\n \t\t\tsetup_work_tree();\n-\n \t\thit = grep_cache(&opt, paths, cached);\n \t\tif (use_threads)\n \t\t\thit |= wait_all();\n-\t\treturn !hit;\n+\t\tfree_grep_patterns(&opt);\n \t}\n-\n-\tif (cached)\n-\t\tdie(\"both --cached and trees are given.\");\n-\n-\tfor (i = 0; i < list.nr; i++) {\n-\t\tstruct object *real_obj;\n-\t\treal_obj = deref_tag(list.objects[i].item, NULL, 0);\n-\t\tif (grep_object(&opt, paths, real_obj, list.objects[i].name)) {\n-\t\t\thit = 1;\n-\t\t\tif (opt.status_only)\n-\t\t\t\tbreak;\n+\telse {\n+\t\tif (cached)\n+\t\t\tdie(\"both --cached and trees are given.\");\n+\n+\t\tfor (i = 0; i < list.nr; i++) {\n+\t\t\tstruct object *real_obj;\n+\t\t\treal_obj = deref_tag(list.objects[i].item, NULL, 0);\n+\t\t\tif (grep_object(&opt, paths, real_obj, list.objects[i].name)) {\n+\t\t\t\thit = 1;\n+\t\t\t\tif (opt.status_only)\n+\t\t\t\t\tbreak;\n+\t\t\t}\n \t\t}\n+\t\tif (use_threads)\n+\t\t\thit |= wait_all();\n+\t\tfree_grep_patterns(&opt);\n \t}\n \n-\tif (use_threads)\n-\t\thit |= wait_all();\n-\tfree_grep_patterns(&opt);\n \treturn !hit;\n }\n-- \n1.7.0.1.370.gd3c5\n"},{"id":"136312","messageId":"1267963785-473-13-git-send-email-pclouds@gmail.com","threadId":"22938","inReplyTo":"1267963785-473-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 12/12] grep: support column output with --columns","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-03-07T12:09:45Z","receivedAt":"2010-03-07T12:09:45Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Documentation/git-grep.txt |   10 ++++++++++\n builtin/grep.c             |    9 +++++++++\n 2 files changed, 19 insertions(+), 0 deletions(-)\n\ndiff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt\nindex 4b32322..7bd6a4f 100644\n--- a/Documentation/git-grep.txt\n+++ b/Documentation/git-grep.txt\n@@ -18,6 +18,7 @@ SYNOPSIS\n \t   [-c | --count] [--all-match] [-q | --quiet]\n \t   [--max-depth <depth>]\n \t   [--color[=<when>] | --no-color]\n+\t   [--columns | --no-columns]\n \t   [-A <post-context>] [-B <pre-context>] [-C <context>]\n \t   [-f <file>] [-e] <pattern>\n \t   [--and|--or|--not|(|)|-e <pattern>...]\n@@ -123,6 +124,15 @@ OPTIONS\n \tgives the default to color output.\n \tSame as `--color=never`.\n \n+--columns::\n+\tShow matched files in columns. This option is only applicable when\n+\tused with --name-only or --files-without-match.\n+\n+--no-columns::\n+\tShow matched files in a single list.  This option is used to\n+\toverride core.columns if set. This option is only applicable\n+\twhen used with --name-only or --files-without-match.\n+\n -[ABC] <context>::\n \tShow `context` trailing (`A` -- after), or leading (`B`\n \t-- before), or both (`C` -- context) lines, and place a\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex b8a1d5c..48c8c57 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -15,6 +15,7 @@\n #include \"grep.h\"\n #include \"quote.h\"\n #include \"dir.h\"\n+#include \"column.h\"\n \n #ifndef NO_PTHREADS\n #include \"thread-utils.h\"\n@@ -759,6 +760,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \tint cached = 0;\n \tint seen_dashdash = 0;\n \tint external_grep_allowed__ignored;\n+\tint column_output = 0;\n \tstruct grep_opt opt;\n \tstruct object_array list = { 0, 0, NULL };\n \tconst char **paths = NULL;\n@@ -849,6 +851,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \t\t\t    \"allow calling of grep(1) (ignored by this build)\"),\n \t\t{ OPTION_CALLBACK, 0, \"help-all\", &options, NULL, \"show usage\",\n \t\t  PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, help_callback },\n+\t\tOPT_BOOLEAN(0, \"columns\", &column_output, \"show match files in columns\"),\n \t\tOPT_END()\n \t};\n \n@@ -876,6 +879,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \tgit_config(grep_config, &opt);\n \tif (opt.color == -1)\n \t\topt.color = git_use_color_default;\n+\tcolumn_output = core_column_output;\n \n \t/*\n \t * If there is no -- then the paths must exist in the working\n@@ -967,6 +971,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \t\tpaths[1] = NULL;\n \t}\n \n+\tif (opt.name_only && column_output)\n+\t\tstart_columnizer(NULL);\n+\n \tif (!use_index) {\n \t\tif (cached)\n \t\t\tdie(\"--cached cannot be used with --no-index.\");\n@@ -1002,5 +1009,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \t\tfree_grep_patterns(&opt);\n \t}\n \n+\tif (opt.name_only && column_output)\n+\t\tstop_columnizer();\n \treturn !hit;\n }\n-- \n1.7.0.1.370.gd3c5\n"},{"id":"136391","messageId":"4B9504C9.5000703@lsrfire.ath.cx","threadId":"22938","inReplyTo":"1267963785-473-1-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH 00/12] Support columinized output in tag/branch/ls-files/grep","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2010-03-08T14:08:09Z","receivedAt":"2010-03-08T14:08:09Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Am 07.03.2010 13:09, schrieb Nguyễn Thái Ngọc Duy:\n> This adds support to show columnized output in the mentioned commands.\n\nThat's a good idea.\n\nI'm not so sure about the interface, though.  Does the task really\nwarrant adding a new git command?\n\nIf a --column parameter is added, I think it should expose the full\nrange of options, i.e. fill columns first (ls -C style), fill rows first\n(ls -x style) as well as off (ls -1 style) and auto.\n\nShouldn't the columnizer use utf8_width() instead of strlen(), like\nstrbuf_add_wrapped_text() in utf8.c?\n\nRené\n"},{"id":"136392","messageId":"fcaeb9bf1003080632o622c8c79x85b816edcf893bc3@mail.gmail.com","threadId":"22938","inReplyTo":"4B9504C9.5000703@lsrfire.ath.cx","subject":"Re: [PATCH 00/12] Support columinized output in tag/branch/ls-files/grep","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-03-08T14:32:43Z","receivedAt":"2010-03-08T14:32:43Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On 3/8/10, René Scharfe <rene.scharfe@lsrfire.ath.cx> wrote:\n> Am 07.03.2010 13:09, schrieb Nguyễn Thái Ngọc Duy:\n>\n> > This adds support to show columnized output in the mentioned commands.\n>\n>\n> That's a good idea.\n>\n>  I'm not so sure about the interface, though.  Does the task really\n>  warrant adding a new git command?\n\nSeveral reasons:\n - Can be reused outside of git (I was surprised Solaris did not have \"column\")\n - Easier to test\n - Minimum code change in modifed commands\n - I can play with more complicated column layout, with minimum code\nchange in git (ok, that's the third reason).\n\n>  If a --column parameter is added, I think it should expose the full\n>  range of options, i.e. fill columns first (ls -C style), fill rows first\n>  (ls -x style) as well as off (ls -1 style) and auto.\n\nMaybe an env variable would be better, so you can pass abitrary\narguments to git-column. \"--column=auto\" should be supported, of\ncourse.\n\n>  Shouldn't the columnizer use utf8_width() instead of strlen(), like\n>  strbuf_add_wrapped_text() in utf8.c?\n\nRight. I missed that.\n-- \nDuy\n"},{"id":"136435","messageId":"7vmxyijts1.fsf@alter.siamese.dyndns.org","threadId":"22938","inReplyTo":"4B9504C9.5000703@lsrfire.ath.cx","subject":"Re: [PATCH 00/12] Support columinized output in tag/branch/ls-files/grep","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-03-08T23:08:46Z","receivedAt":"2010-03-08T23:08:46Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"René Scharfe <rene.scharfe@lsrfire.ath.cx> writes:\n\n> Am 07.03.2010 13:09, schrieb Nguyễn Thái Ngọc Duy:\n>> This adds support to show columnized output in the mentioned commands.\n>\n> That's a good idea.\n>\n> I'm not so sure about the interface, though.  Does the task really\n> warrant adding a new git command?\n>\n> If a --column parameter is added, I think it should expose the full\n> range of options, i.e. fill columns first (ls -C style), fill rows first\n> (ls -x style) as well as off (ls -1 style) and auto.\n>\n> Shouldn't the columnizer use utf8_width() instead of strlen(), like\n> strbuf_add_wrapped_text() in utf8.c?\n\nI agree with all the above.  Also I think it should not be able to change\nthe behaviour of these commands so much without being explicitly asked\nfrom the command line, especially for plumbing commands like ls-files.\nIOW, introduction of the configuration variable without thinking things\nthrough is a bad idea.\n"},{"id":"136431","messageId":"fcaeb9bf1003081806y13da4a1au80a925e9febcd8ca@mail.gmail.com","threadId":"22938","inReplyTo":"7vmxyijts1.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 00/12] Support columinized output in tag/branch/ls-files/grep","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-03-09T02:06:30Z","receivedAt":"2010-03-09T02:06:30Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Tue, Mar 9, 2010 at 6:08 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Also I think it should not be able to change\n> the behaviour of these commands so much without being explicitly asked\n> from the command line, especially for plumbing commands like ls-files.\n> IOW, introduction of the configuration variable without thinking things\n> through is a bad idea.\n\nHmm.. ls-files does not take core.columns into account. Command line\nparameter --columns is the only way to turn column layout on in\nls-files.\n-- \nDuy\n"},{"id":"136440","messageId":"7vvdd6ckbw.fsf@alter.siamese.dyndns.org","threadId":"22938","inReplyTo":"fcaeb9bf1003081806y13da4a1au80a925e9febcd8ca@mail.gmail.com","subject":"Re: [PATCH 00/12] Support columinized output in tag/branch/ls-files/grep","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-03-09T02:14:43Z","receivedAt":"2010-03-09T02:14:43Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyen Thai Ngoc Duy <pclouds@gmail.com> writes:\n\n> Hmm.. ls-files does not take core.columns into account. Command line\n> parameter --columns is the only way to turn column layout on in\n> ls-files.\n\nOk, then that's good.\n\nBy the way, I didn't single out ls-files as something special that must be\nkept (i.e. \"it is ok to touch any other things as long as you never\ntouched ls-files\" is not what I meant) but mentioned it as an example of\nplumbing.\n"},{"id":"136454","messageId":"4B967C36.90309@lsrfire.ath.cx","threadId":"22938","inReplyTo":"fcaeb9bf1003080632o622c8c79x85b816edcf893bc3@mail.gmail.com","subject":"Re: [PATCH 00/12] Support columinized output in tag/branch/ls-files/grep","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2010-03-09T16:49:58Z","receivedAt":"2010-03-09T16:49:58Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Am 08.03.2010 15:32, schrieb Nguyen Thai Ngoc Duy:\n> On 3/8/10, René Scharfe <rene.scharfe@lsrfire.ath.cx> wrote:\n>>  I'm not so sure about the interface, though.  Does the task really\n>>  warrant adding a new git command?\n> \n> Several reasons:\n>  - Can be reused outside of git (I was surprised Solaris did not have \"column\")\n\nGranted, we have a precedent: git stripspace.  But I don't like that\none, either. ;)  If it's not specific to git, then it should not be a\ngit command.\n\nPerhaps name it git-column--helper, so that it can still be used by git\ncommands that are implemented as scripts?\n\n>  - Easier to test\n\nName it test-column?\n\n>  - Minimum code change in modifed commands\n\nOK, forking out is easy, but replacing printf() calls with calls to feed\nthe columnizer shouldn't be _that_ intrusive, either.\n\n>  - I can play with more complicated column layout, with minimum code\n> change in git (ok, that's the third reason).\n\nThis is possible regardless of the way how the columnizer is invoked if\nits full functionality is exposed through the command line parameter.\n\nWith \"more complicated\", do you perhaps mean what GNU ls does, namely\nhaving non-uniform column widths?  I never consciously noticed that it\nactually goes out of its way to cram as may columns on the screen as\npossible, it just feels so natural. :)\n\n>>  If a --column parameter is added, I think it should expose the full\n>>  range of options, i.e. fill columns first (ls -C style), fill rows first\n>>  (ls -x style) as well as off (ls -1 style) and auto.\n> \n> Maybe an env variable would be better, so you can pass abitrary\n> arguments to git-column. \"--column=auto\" should be supported, of\n> course.\n\nI don't see any benefit of an environment variable over config options.\n\nRené\n"},{"id":"136482","messageId":"fcaeb9bf1003091627p65ad6e60u4bbae2eb4e859f13@mail.gmail.com","threadId":"22938","inReplyTo":"4B967C36.90309@lsrfire.ath.cx","subject":"Re: [PATCH 00/12] Support columinized output in tag/branch/ls-files/grep","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-03-10T00:27:10Z","receivedAt":"2010-03-10T00:27:10Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On 3/9/10, René Scharfe <rene.scharfe@lsrfire.ath.cx> wrote:\n> Am 08.03.2010 15:32, schrieb Nguyen Thai Ngoc Duy:\n>\n> > On 3/8/10, René Scharfe <rene.scharfe@lsrfire.ath.cx> wrote:\n>\n> >>  I'm not so sure about the interface, though.  Does the task really\n>  >>  warrant adding a new git command?\n>  >\n>  > Several reasons:\n>  >  - Can be reused outside of git (I was surprised Solaris did not have \"column\")\n>\n>\n> Granted, we have a precedent: git stripspace.  But I don't like that\n>  one, either. ;)  If it's not specific to git, then it should not be a\n>  git command.\n>\n>  Perhaps name it git-column--helper, so that it can still be used by git\n>  commands that are implemented as scripts?\n\nOK.\n\n>\n>  >  - Easier to test\n>\n>  Name it test-column?\n\nIf it turns out no external process is needed for column layout.\n\n>  >  - Minimum code change in modifed commands\n>\n>\n> OK, forking out is easy, but replacing printf() calls with calls to feed\n>  the columnizer shouldn't be _that_ intrusive, either.\n\nWell, also fwrite() and write(). If disliked \"if (blah) feed_it();\nelse printf(as normal);\" construct. But we can wrap it to\nfeed_or_printf(). We may also need to buffer printf() results until a\nfull line is received. Let me try and see how intrusive it is.\n\n>  >  - I can play with more complicated column layout, with minimum code\n>  > change in git (ok, that's the third reason).\n>\n>\n> This is possible regardless of the way how the columnizer is invoked if\n>  its full functionality is exposed through the command line parameter.\n>\n>  With \"more complicated\", do you perhaps mean what GNU ls does, namely\n>  having non-uniform column widths?  I never consciously noticed that it\n>  actually goes out of its way to cram as may columns on the screen as\n>  possible, it just feels so natural. :)\n\nThat. And aligned grep output like this\n\npclouds@do ~/w/git/builtin $ git grep -n 38\ncount-objects.c  |  35 |                if (cp - ent->d_name != 38)\ncount-objects.c  |  39 |                        memcpy(path + len + 3,\nent->d_name, 38);\ncount-objects.c  |  59 |                memcpy(hex+2, ent->d_name, 38);\nfsck.c           | 405 |                if (strlen(de->d_name) == 38) {\ngc.c             | 112 |                if (strspn(ent->d_name,\n\"0123456789abcdef\") != 38 ||\ngc.c             | 113 |                    ent->d_name[38] != '\\0')\nprune-packed.c   |  24 |                if (strlen(de->d_name) != 38)\nprune-packed.c   |  26 |                memcpy(hex+2, de->d_name, 38);\nprune-packed.c   |  31 |                memcpy(pathname + len, de->d_name, 38);\nprune.c          |  64 |                if (strlen(de->d_name) == 38) {\nreceive-pack.c   | 588 |        char hdr_arg[38];\nupload-archive.c |  86 |        char buf[16384];\n\n>  >>  If a --column parameter is added, I think it should expose the full\n>  >>  range of options, i.e. fill columns first (ls -C style), fill rows first\n>  >>  (ls -x style) as well as off (ls -1 style) and auto.\n>  >\n>  > Maybe an env variable would be better, so you can pass abitrary\n>  > arguments to git-column. \"--column=auto\" should be supported, of\n>  > course.\n>\n>\n> I don't see any benefit of an environment variable over config options.\n\nCurrently we may pass --column=<foo> from a porcelain to \"git column\n--mode=<foo>\", <foo> could be column first, or row first, or either\nwith non-uniform columns (not implemented yet). We can also pass other\nthings to \"git column\". Putting everything in \"<foo>\" is OK, although\nlooks ugly. In my private tree, I also have \"git column\n--min-rows/--max-items\" that forces the columnizer to one column mode\nif:\n - there will be only one or two rows after columnized, too wide\nscreen for example (--min-rows)\n - too many lines and the layout has not been fixed, so nothing gets\nprinted (--max-items). Forcing back to one column mode to stop wait\ntime.\n-- \nDuy\n"},{"id":"136501","messageId":"4B974998.5030708@viscovery.net","threadId":"22938","inReplyTo":"fcaeb9bf1003091627p65ad6e60u4bbae2eb4e859f13@mail.gmail.com","subject":"Re: [PATCH 00/12] Support columinized output in tag/branch/ls-files/grep","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2010-03-10T07:26:16Z","receivedAt":"2010-03-10T07:26:16Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Nguyen Thai Ngoc Duy schrieb:\n> On 3/9/10, René Scharfe <rene.scharfe@lsrfire.ath.cx> wrote:\n>> OK, forking out is easy, but replacing printf() calls with calls to feed\n>>  the columnizer shouldn't be _that_ intrusive, either.\n> \n> Well, also fwrite() and write(). If disliked \"if (blah) feed_it();\n> else printf(as normal);\" construct. But we can wrap it to\n> feed_or_printf().\n\nHow about merging this into color_fprintf and friends?\n\n-- Hannes\n\n-- \n\"Atomic objects are neither active nor radioactive.\" --\nDoc.No N3035 (Working Draft, Standard for Programming Language C++)\n"},{"id":"136497","messageId":"fcaeb9bf1003100412x7c08a312o4df114f91ebd7e8c@mail.gmail.com","threadId":"22938","inReplyTo":"4B974998.5030708@viscovery.net","subject":"Re: [PATCH 00/12] Support columinized output in tag/branch/ls-files/grep","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-03-10T12:12:23Z","receivedAt":"2010-03-10T12:12:23Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On 3/10/10, Johannes Sixt <j.sixt@viscovery.net> wrote:\n> Nguyen Thai Ngoc Duy schrieb:\n>\n> > On 3/9/10, René Scharfe <rene.scharfe@lsrfire.ath.cx> wrote:\n>\n> >> OK, forking out is easy, but replacing printf() calls with calls to feed\n>  >>  the columnizer shouldn't be _that_ intrusive, either.\n>  >\n>  > Well, also fwrite() and write(). If disliked \"if (blah) feed_it();\n>  > else printf(as normal);\" construct. But we can wrap it to\n>  > feed_or_printf().\n>\n>\n> How about merging this into color_fprintf and friends?\n\nGood idea.\n-- \nDuy\n"},{"id":"136621","messageId":"4B995D0C.2090000@lsrfire.ath.cx","threadId":"22938","inReplyTo":"fcaeb9bf1003091627p65ad6e60u4bbae2eb4e859f13@mail.gmail.com","subject":"Re: [PATCH 00/12] Support columinized output in tag/branch/ls-files/grep","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2010-03-11T21:13:48Z","receivedAt":"2010-03-11T21:13:48Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Am 10.03.2010 01:27, schrieb Nguyen Thai Ngoc Duy:\n> On 3/9/10, René Scharfe <rene.scharfe@lsrfire.ath.cx> wrote:\n>>  With \"more complicated\", do you perhaps mean what GNU ls does, namely\n>>  having non-uniform column widths?  I never consciously noticed that it\n>>  actually goes out of its way to cram as may columns on the screen as\n>>  possible, it just feels so natural. :)\n> \n> That. And aligned grep output like this\n> \n> pclouds@do ~/w/git/builtin $ git grep -n 38\n> count-objects.c  |  35 |                if (cp - ent->d_name != 38)\n> count-objects.c  |  39 |                        memcpy(path + len + 3,\n> ent->d_name, 38);\n> count-objects.c  |  59 |                memcpy(hex+2, ent->d_name, 38);\n> fsck.c           | 405 |                if (strlen(de->d_name) == 38) {\n> gc.c             | 112 |                if (strspn(ent->d_name,\n> \"0123456789abcdef\") != 38 ||\n> gc.c             | 113 |                    ent->d_name[38] != '\\0')\n> prune-packed.c   |  24 |                if (strlen(de->d_name) != 38)\n> prune-packed.c   |  26 |                memcpy(hex+2, de->d_name, 38);\n> prune-packed.c   |  31 |                memcpy(pathname + len, de->d_name, 38);\n> prune.c          |  64 |                if (strlen(de->d_name) == 38) {\n> receive-pack.c   | 588 |        char hdr_arg[38];\n> upload-archive.c |  86 |        char buf[16384];\n\nHmm, I'm not sure that this columnizing is very useful in this instance.\n You can more easily compare the line numbers and the indent level of\nthe hits, but both pieces of information are only useful in the context\nof the file, so this easier comparison doesn't buy you much.\n\nAnother possible use might be the list of untracked files shown by\nstatus and commit, by the way.\n\n>> I don't see any benefit of an environment variable over config options.\n> \n> Currently we may pass --column=<foo> from a porcelain to \"git column\n> --mode=<foo>\", <foo> could be column first, or row first, or either\n> with non-uniform columns (not implemented yet). We can also pass other\n> things to \"git column\". Putting everything in \"<foo>\" is OK, although\n> looks ugly. In my private tree, I also have \"git column\n> --min-rows/--max-items\" that forces the columnizer to one column mode\n> if:\n>  - there will be only one or two rows after columnized, too wide\n> screen for example (--min-rows)\n\nWell, I can't imagine when I would want to use this option.  If I'm OK\nwith n + 100 items being displayed in x columns, I'd certainly be OK\nwith n items being displayed the same way, even if they only take up a\nsingle row.\n\n>  - too many lines and the layout has not been fixed, so nothing gets\n> printed (--max-items). Forcing back to one column mode to stop wait\n> time.\n\nInteresting idea, but I'm not sure if I'd want to use it, too.  Best\neffort pretty-printing combines fast output and optimized display at\nfirst glance.  However, if there are lots of items then the user would\nbenefit the most from having them columnized.\n\nIf it takes too long to show the first line of output (since the\ncolumnizer needs to wait for all items to be generated) then the command\nshould only columnize on request.\n\nRené\n"},{"id":"136635","messageId":"fcaeb9bf1003112022md32ababv3e4ace04752f8f56@mail.gmail.com","threadId":"22938","inReplyTo":"4B995D0C.2090000@lsrfire.ath.cx","subject":"Re: [PATCH 00/12] Support columinized output in tag/branch/ls-files/grep","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-03-12T04:22:26Z","receivedAt":"2010-03-12T04:22:26Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Fri, Mar 12, 2010 at 4:13 AM, René Scharfe\n<rene.scharfe@lsrfire.ath.cx> wrote:\n> Am 10.03.2010 01:27, schrieb Nguyen Thai Ngoc Duy:\n>> On 3/9/10, René Scharfe <rene.scharfe@lsrfire.ath.cx> wrote:\n>>>  With \"more complicated\", do you perhaps mean what GNU ls does, namely\n>>>  having non-uniform column widths?  I never consciously noticed that it\n>>>  actually goes out of its way to cram as may columns on the screen as\n>>>  possible, it just feels so natural. :)\n>>\n>> That. And aligned grep output like this\n>>\n>> pclouds@do ~/w/git/builtin $ git grep -n 38\n>> count-objects.c  |  35 |                if (cp - ent->d_name != 38)\n>> count-objects.c  |  39 |                        memcpy(path + len + 3,\n>> ent->d_name, 38);\n>> count-objects.c  |  59 |                memcpy(hex+2, ent->d_name, 38);\n>> fsck.c           | 405 |                if (strlen(de->d_name) == 38) {\n>> gc.c             | 112 |                if (strspn(ent->d_name,\n>> \"0123456789abcdef\") != 38 ||\n>> gc.c             | 113 |                    ent->d_name[38] != '\\0')\n>> prune-packed.c   |  24 |                if (strlen(de->d_name) != 38)\n>> prune-packed.c   |  26 |                memcpy(hex+2, de->d_name, 38);\n>> prune-packed.c   |  31 |                memcpy(pathname + len, de->d_name, 38);\n>> prune.c          |  64 |                if (strlen(de->d_name) == 38) {\n>> receive-pack.c   | 588 |        char hdr_arg[38];\n>> upload-archive.c |  86 |        char buf[16384];\n>\n> Hmm, I'm not sure that this columnizing is very useful in this instance.\n>  You can more easily compare the line numbers and the indent level of\n> the hits, but both pieces of information are only useful in the context\n> of the file, so this easier comparison doesn't buy you much.\n\nIt's useful when I need to look at the beginning of matched lines.\nWith current output, all lines are not aligned, so it's hard too see\nwhere lines begin.\n\n> Another possible use might be the list of untracked files shown by\n> status and commit, by the way.\n\nThanks.\n\n>>> I don't see any benefit of an environment variable over config options.\n>>\n>> Currently we may pass --column=<foo> from a porcelain to \"git column\n>> --mode=<foo>\", <foo> could be column first, or row first, or either\n>> with non-uniform columns (not implemented yet). We can also pass other\n>> things to \"git column\". Putting everything in \"<foo>\" is OK, although\n>> looks ugly. In my private tree, I also have \"git column\n>> --min-rows/--max-items\" that forces the columnizer to one column mode\n>> if:\n>>  - there will be only one or two rows after columnized, too wide\n>> screen for example (--min-rows)\n>\n> Well, I can't imagine when I would want to use this option.  If I'm OK\n> with n + 100 items being displayed in x columns, I'd certainly be OK\n> with n items being displayed the same way, even if they only take up a\n> single row.\n\nIt's probably just me. With 279 character-wide terminal, I find it\nmuch easier to look vertically than 16 items on a single row.\n\n>>  - too many lines and the layout has not been fixed, so nothing gets\n>> printed (--max-items). Forcing back to one column mode to stop wait\n>> time.\n>\n> Interesting idea, but I'm not sure if I'd want to use it, too.  Best\n> effort pretty-printing combines fast output and optimized display at\n> first glance.  However, if there are lots of items then the user would\n> benefit the most from having them columnized.\n>\n> If it takes too long to show the first line of output (since the\n> columnizer needs to wait for all items to be generated) then the command\n> should only columnize on request.\n\nYeah. That's the idea of \"core.columns = auto\". If you specify\n--[no-]columns on command line, then it must do as you wish. However,\nif you set \"core.columns = auto\" without additional command line\narguments, then it only shows column layout when it's good to do.\n-- \nDuy\n"}]}