git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/9] column output v3
@ 2011-03-20 12:57 Nguyễn Thái Ngọc Duy
  2011-03-20 12:57 ` [PATCH 1/9] Move term_columns() to pager.c and save terminal width before pager Nguyễn Thái Ngọc Duy
                   ` (8 more replies)
  0 siblings, 9 replies; 13+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-03-20 12:57 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

Compared to v2 [1]. It's quite ready for consumption:

 - dense mode works better (and consumes more cpu cycles, but not much)
 - there should be no impact when it's not activated (i.e. no
   output buffering)
 - column.ui is used for default settings. Not sure if I should go for
   column.branch and column.tag
 - --[no-]column can be used to override column.ui

[1] http://mid.gmane.org/1297254284-3729-1-git-send-email-pclouds@gmail.com

Nguyễn Thái Ngọc Duy (9):
  Move term_columns() to pager.c and save terminal width before pager
  Add display_columns() to display in columnar layout
  column: add functions to parse column settings
  display_columns: add COL_MODE_{COLUMN,ROW} mode
  display_columns: add COL_DENSE to do unequal column layout
  column: add column.ui for default column output settings
  help: reuse display_columns() for help -a
  tag: add --column
  branch: add --column

 .gitignore                   |    1 +
 Documentation/config.txt     |   24 +++
 Documentation/git-branch.txt |    9 +
 Documentation/git-tag.txt    |   11 +-
 Makefile                     |    3 +
 builtin/branch.c             |   23 ++-
 builtin/tag.c                |   21 ++-
 column.c                     |  378 ++++++++++++++++++++++++++++++++++++++++++
 column.h                     |   22 +++
 help.c                       |   53 +-----
 pager.c                      |   33 ++++
 parse-options.h              |    2 +
 t/t9002-column.sh            |  135 +++++++++++++++
 test-column.c                |   39 +++++
 14 files changed, 701 insertions(+), 53 deletions(-)
 create mode 100644 column.c
 create mode 100644 column.h
 create mode 100755 t/t9002-column.sh
 create mode 100644 test-column.c

-- 
1.7.4.74.g639db

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/9] Move term_columns() to pager.c and save terminal width before pager
  2011-03-20 12:57 [PATCH 0/9] column output v3 Nguyễn Thái Ngọc Duy
@ 2011-03-20 12:57 ` Nguyễn Thái Ngọc Duy
  2011-03-20 12:57 ` [PATCH 2/9] Add display_columns() to display in columnar layout Nguyễn Thái Ngọc Duy
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-03-20 12:57 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

term_columns() checks for terminal width via ioctl(2). After
redirecting, stdin is no longer terminal to get terminal width.

Check terminal width and save it before redirect stdin in setup_pager()
and let term_columns() reuse the value.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Makefile |    1 +
 column.h |    6 ++++++
 help.c   |   23 +----------------------
 pager.c  |   33 +++++++++++++++++++++++++++++++++
 4 files changed, 41 insertions(+), 22 deletions(-)
 create mode 100644 column.h

diff --git a/Makefile b/Makefile
index 775ee83..6007f68 100644
--- a/Makefile
+++ b/Makefile
@@ -1956,6 +1956,7 @@ builtin/prune.o builtin/reflog.o reachable.o: reachable.h
 builtin/commit.o builtin/revert.o wt-status.o: wt-status.h
 builtin/tar-tree.o archive-tar.o: tar.h
 connect.o transport.o http-backend.o: url.h
+help.o pager.o: column.h
 http-fetch.o http-walker.o remote-curl.o transport.o walker.o: walker.h
 http.o http-walker.o http-push.o http-fetch.o remote-curl.o: http.h url.h
 
diff --git a/column.h b/column.h
new file mode 100644
index 0000000..55d8067
--- /dev/null
+++ b/column.h
@@ -0,0 +1,6 @@
+#ifndef COLUMN_H
+#define COLUMN_H
+
+extern int term_columns(void);
+
+#endif
diff --git a/help.c b/help.c
index 7654f1b..768f64c 100644
--- a/help.c
+++ b/help.c
@@ -4,28 +4,7 @@
 #include "levenshtein.h"
 #include "help.h"
 #include "common-cmds.h"
-
-/* most GUI terminals set COLUMNS (although some don't export it) */
-static int term_columns(void)
-{
-	char *col_string = getenv("COLUMNS");
-	int n_cols;
-
-	if (col_string && (n_cols = atoi(col_string)) > 0)
-		return n_cols;
-
-#ifdef TIOCGWINSZ
-	{
-		struct winsize ws;
-		if (!ioctl(1, TIOCGWINSZ, &ws)) {
-			if (ws.ws_col)
-				return ws.ws_col;
-		}
-	}
-#endif
-
-	return 80;
-}
+#include "column.h"
 
 void add_cmdname(struct cmdnames *cmds, const char *name, int len)
 {
diff --git a/pager.c b/pager.c
index dac358f..dad6329 100644
--- a/pager.c
+++ b/pager.c
@@ -12,6 +12,19 @@
  */
 
 static int spawned_pager;
+static int max_columns;
+
+static int retrieve_terminal_width(void)
+{
+#ifdef TIOCGWINSZ
+	struct winsize ws;
+	if (ioctl(1, TIOCGWINSZ, &ws))  /* e.g., ENOSYS */
+		return 0;
+	return ws.ws_col;
+#else
+	return 0;
+#endif
+}
 
 #ifndef WIN32
 static void pager_preexec(void)
@@ -74,12 +87,17 @@ const char *git_pager(int stdout_is_tty)
 void setup_pager(void)
 {
 	const char *pager = git_pager(isatty(1));
+	int width;
 
 	if (!pager)
 		return;
 
 	spawned_pager = 1; /* means we are emitting to terminal */
 
+	width = retrieve_terminal_width();
+	if (width)
+		max_columns = width;
+
 	/* spawn the pager */
 	pager_argv[0] = pager;
 	pager_process.use_shell = 1;
@@ -116,3 +134,18 @@ int pager_in_use(void)
 	env = getenv("GIT_PAGER_IN_USE");
 	return env ? git_config_bool("GIT_PAGER_IN_USE", env) : 0;
 }
+
+int term_columns()
+{
+	char *col_string = getenv("COLUMNS");
+	int n_cols;
+
+	if (col_string && (n_cols = atoi(col_string)) > 0)
+		return n_cols;
+
+	if (spawned_pager && max_columns)
+		return max_columns;
+
+	n_cols = retrieve_terminal_width();
+	return n_cols ? n_cols : 80;
+}
-- 
1.7.4.74.g639db

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 2/9] Add display_columns() to display in columnar layout
  2011-03-20 12:57 [PATCH 0/9] column output v3 Nguyễn Thái Ngọc Duy
  2011-03-20 12:57 ` [PATCH 1/9] Move term_columns() to pager.c and save terminal width before pager Nguyễn Thái Ngọc Duy
@ 2011-03-20 12:57 ` Nguyễn Thái Ngọc Duy
  2011-03-20 12:57 ` [PATCH 3/9] column: add functions to parse column settings Nguyễn Thái Ngọc Duy
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-03-20 12:57 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

Currently it does not do that, just provide the API. In order to
output in columns, COL_ENABLED bit must be set. A nice consequence is
mode 0 is effectively no column mode.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Makefile |    3 ++-
 column.c |   37 +++++++++++++++++++++++++++++++++++++
 column.h |    5 +++++
 3 files changed, 44 insertions(+), 1 deletions(-)
 create mode 100644 column.c

diff --git a/Makefile b/Makefile
index 6007f68..94e1cf0 100644
--- a/Makefile
+++ b/Makefile
@@ -575,6 +575,7 @@ LIB_OBJS += branch.o
 LIB_OBJS += bundle.o
 LIB_OBJS += cache-tree.o
 LIB_OBJS += color.o
+LIB_OBJS += column.o
 LIB_OBJS += combine-diff.o
 LIB_OBJS += commit.o
 LIB_OBJS += config.o
@@ -1956,7 +1957,7 @@ builtin/prune.o builtin/reflog.o reachable.o: reachable.h
 builtin/commit.o builtin/revert.o wt-status.o: wt-status.h
 builtin/tar-tree.o archive-tar.o: tar.h
 connect.o transport.o http-backend.o: url.h
-help.o pager.o: column.h
+column.o help.o pager.o: column.h
 http-fetch.o http-walker.o remote-curl.o transport.o walker.o: walker.h
 http.o http-walker.o http-push.o http-fetch.o remote-curl.o: http.h url.h
 
diff --git a/column.c b/column.c
new file mode 100644
index 0000000..8422c89
--- /dev/null
+++ b/column.c
@@ -0,0 +1,37 @@
+#include "cache.h"
+#include "column.h"
+#include "string-list.h"
+
+#define MODE(mode) ((mode) & COL_MODE)
+
+struct string_list_item *add_to_columns(struct string_list *list, int mode,
+					const char *string)
+{
+	if (mode & COL_ENABLED)
+		return string_list_append(list, string);
+	printf("%s\n", string);
+	return NULL;
+}
+
+/* Display without layout when COL_ENABLED is not set */
+static void display_plain(const struct string_list *list, const char *indent)
+{
+	int i;
+
+	for (i = 0; i < list->nr; i++)
+		printf("%s%s\n", indent, list->items[i].string);
+}
+
+void display_columns(const struct string_list *list, int mode,
+		     int width, int padding, const char *indent)
+{
+	if (!list->nr)
+		return;
+	if (!indent)
+		indent = "";
+	if (width <= 1 || !(mode & COL_ENABLED)) {
+		display_plain(list, indent);
+		return;
+	}
+	die("BUG: invalid mode %d", MODE(mode));
+}
diff --git a/column.h b/column.h
index 55d8067..ffae87c 100644
--- a/column.h
+++ b/column.h
@@ -1,6 +1,11 @@
 #ifndef COLUMN_H
 #define COLUMN_H
 
+#define COL_MODE          0x000F
+#define COL_ENABLED      (1 << 4)
+
 extern int term_columns(void);
+extern struct string_list_item *add_to_columns(struct string_list *list, int mode, const char *string);
+extern void display_columns(const struct string_list *list, int mode, int width, int padding, const char *indent);
 
 #endif
-- 
1.7.4.74.g639db

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 3/9] column: add functions to parse column settings
  2011-03-20 12:57 [PATCH 0/9] column output v3 Nguyễn Thái Ngọc Duy
  2011-03-20 12:57 ` [PATCH 1/9] Move term_columns() to pager.c and save terminal width before pager Nguyễn Thái Ngọc Duy
  2011-03-20 12:57 ` [PATCH 2/9] Add display_columns() to display in columnar layout Nguyễn Thái Ngọc Duy
@ 2011-03-20 12:57 ` Nguyễn Thái Ngọc Duy
  2011-03-20 12:57 ` [PATCH 4/9] display_columns: add COL_MODE_{COLUMN,ROW} mode Nguyễn Thái Ngọc Duy
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-03-20 12:57 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

A column option string consists of many token separated by either
space of commas. A token belongs to one of three groups:

 - enabling: always, never and auto
 - layout mode: to be implemented
 - other tuning, which could be negated be prefix 'no'

A command line option without argument (e.g. --column) will enable
column output and reuse existing settings (layout mode and options..).
--no-column disables columnar output.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 .gitignore        |    1 +
 Makefile          |    1 +
 column.c          |  125 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 column.h          |    4 ++
 parse-options.h   |    2 +
 t/t9002-column.sh |   27 +++++++++++
 test-column.c     |   39 ++++++++++++++++
 7 files changed, 199 insertions(+), 0 deletions(-)
 create mode 100755 t/t9002-column.sh
 create mode 100644 test-column.c

diff --git a/.gitignore b/.gitignore
index 3dd6ef7..a1a1202 100644
--- a/.gitignore
+++ b/.gitignore
@@ -162,6 +162,7 @@
 /gitweb/gitweb.cgi
 /gitweb/static/gitweb.min.*
 /test-chmtime
+/test-column
 /test-ctype
 /test-date
 /test-delta
diff --git a/Makefile b/Makefile
index 94e1cf0..ba9944b 100644
--- a/Makefile
+++ b/Makefile
@@ -417,6 +417,7 @@ PROGRAM_OBJS += http-backend.o
 PROGRAMS += $(patsubst %.o,git-%$X,$(PROGRAM_OBJS))
 
 TEST_PROGRAMS_NEED_X += test-chmtime
+TEST_PROGRAMS_NEED_X += test-column
 TEST_PROGRAMS_NEED_X += test-ctype
 TEST_PROGRAMS_NEED_X += test-date
 TEST_PROGRAMS_NEED_X += test-delta
diff --git a/column.c b/column.c
index 8422c89..b32b9f9 100644
--- a/column.c
+++ b/column.c
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "column.h"
 #include "string-list.h"
+#include "parse-options.h"
 
 #define MODE(mode) ((mode) & COL_MODE)
 
@@ -35,3 +36,127 @@ void display_columns(const struct string_list *list, int mode,
 	}
 	die("BUG: invalid mode %d", MODE(mode));
 }
+
+struct colopt {
+	enum {
+		ENABLE,
+		MODE,
+		OPTION
+	} type;
+	const char *name;
+	int value;
+};
+
+/*
+ * Set COL_ENABLED and COL_ENABLED_SET. If 'set' is -1, check if
+ * stdout is tty.
+ */
+static int set_enable_bit(int *mode, int set, int stdout_is_tty)
+{
+	if (set < 0) {	/* auto */
+		if (stdout_is_tty < 0)
+			stdout_is_tty = isatty(1);
+		set = stdout_is_tty || (pager_in_use() && pager_use_color);
+	}
+	if (set)
+		*mode = *mode | COL_ENABLED | COL_ENABLED_SET;
+	else
+		*mode = (*mode & ~COL_ENABLED) | COL_ENABLED_SET;
+	return 0;
+}
+
+/*
+ * Set COL_MODE_*. mode is intially copied from column.ui. If
+ * COL_ENABLED_SET is not set, then neither 'always', 'never' nor
+ * 'auto' has been used. Default to 'always'.
+ */
+static int set_mode(int *mode, int value)
+{
+	*mode = (*mode & ~COL_MODE) | value;
+	if (!(*mode & COL_ENABLED_SET))
+		*mode |= COL_ENABLED | COL_ENABLED_SET;
+
+	return 0;
+}
+
+/* Set or unset other COL_* */
+static int set_option(int *mode, int opt, int set)
+{
+	if (set)
+		*mode |= opt;
+	else
+		*mode &= ~opt;
+	return 0;
+}
+
+static int parse_option(const char *arg, int len,
+			int *mode, int stdout_is_tty)
+{
+	struct colopt opts[] = {
+		{ ENABLE, "always",  1 },
+		{ ENABLE, "never",   0 },
+		{ ENABLE, "auto",   -1 },
+	};
+	int i, set, name_len;
+
+	for (i = 0; i < ARRAY_SIZE(opts); i++) {
+		if (opts[i].type == OPTION) {
+			if (len > 2 && !strncmp(arg, "no", 2)) {
+				arg += 2;
+				len -= 2;
+				set = 0;
+			}
+			else
+				set = 1;
+		}
+
+		name_len = strlen(opts[i].name);
+		if (len != name_len ||
+		    strncmp(arg, opts[i].name, name_len))
+			continue;
+
+		switch (opts[i].type) {
+		case ENABLE: return set_enable_bit(mode, opts[i].value,
+						   stdout_is_tty);
+		case MODE: return set_mode(mode, opts[i].value);
+		case OPTION: return set_option(mode, opts[i].value, set);
+		default: die("BUG: Unknown option type %d", opts[i].type);
+		}
+	}
+
+	return error("unsupported style '%s'", arg);
+}
+
+static int parse_string(int *mode, const char *value,
+			int stdout_is_tty)
+{
+	const char *sep = " ,";
+
+	while (*value) {
+		int len = strcspn(value, sep);
+		if (len) {
+			if (parse_option(value, len, mode, stdout_is_tty))
+				return -1;
+
+			value += len;
+		}
+		value += strspn(value, sep);
+	}
+	return 0;
+}
+
+int parseopt_column_callback(const struct option *opt,
+			     const char *arg, int unset)
+{
+	int *mode = opt->value;
+	if (unset) {
+		*mode = (*mode & ~COL_ENABLED) | COL_ENABLED_SET;
+		return 0;
+	}
+	if (arg)
+		return parse_string(mode, arg, -1);
+
+	/* no arg, turn it on */
+	*mode |= COL_ENABLED | COL_ENABLED_SET;
+	return 0;
+}
diff --git a/column.h b/column.h
index ffae87c..a8b24e8 100644
--- a/column.h
+++ b/column.h
@@ -3,9 +3,13 @@
 
 #define COL_MODE          0x000F
 #define COL_ENABLED      (1 << 4)
+#define COL_ENABLED_SET  (1 << 5)  /* Has COL_ENABLED been set? */
 
 extern int term_columns(void);
 extern struct string_list_item *add_to_columns(struct string_list *list, int mode, const char *string);
 extern void display_columns(const struct string_list *list, int mode, int width, int padding, const char *indent);
 
+struct option;
+extern int parseopt_column_callback(const struct option *opt, const char *arg, int unset);
+
 #endif
diff --git a/parse-options.h b/parse-options.h
index 31ec5d2..14816b6 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -220,5 +220,7 @@ extern int parse_opt_tertiary(const struct option *, const char *, int);
 	  PARSE_OPT_OPTARG, &parse_opt_abbrev_cb, 0 }
 #define OPT__COLOR(var, h) \
 	OPT_COLOR_FLAG(0, "color", (var), (h))
+#define OPT_COLUMN(s, l, v, h) \
+	{ OPTION_CALLBACK, (s), (l), (v), "style", (h), PARSE_OPT_OPTARG, parseopt_column_callback }
 
 #endif
diff --git a/t/t9002-column.sh b/t/t9002-column.sh
new file mode 100755
index 0000000..099a29f
--- /dev/null
+++ b/t/t9002-column.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+test_description='git column'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	cat >lista <<\EOF
+one
+two
+three
+four
+five
+six
+seven
+eight
+nine
+ten
+eleven
+EOF
+'
+
+test_expect_success 'never' '
+	test-column --mode=never <lista >actual &&
+	test_cmp lista actual
+'
+
+test_done
diff --git a/test-column.c b/test-column.c
new file mode 100644
index 0000000..d6321a4
--- /dev/null
+++ b/test-column.c
@@ -0,0 +1,39 @@
+#include "cache.h"
+#include "strbuf.h"
+#include "parse-options.h"
+#include "string-list.h"
+#include "column.h"
+
+static const char * const builtin_column_usage[] = {
+	"git column [--mode=<mode>] [--width=<width>] [--left-space=<N>] [--right-space=<N>]",
+	NULL
+};
+
+int main(int argc, const char **argv)
+{
+	struct string_list list = STRING_LIST_INIT_DUP;
+	int mode = 0;
+	struct strbuf sb = STRBUF_INIT;
+	int left_space = 0, right_space = 0, padding = 1;
+	int term_width = term_columns();
+	struct option options[] = {
+		OPT_INTEGER(0, "width", &term_width, "Maximum width"),
+		OPT_INTEGER(0, "left", &left_space, "Padding space on left border"),
+		OPT_INTEGER(0, "right", &right_space, "Padding space on right border"),
+		OPT_INTEGER(0, "padding", &padding, "Padding space between columns"),
+		OPT_COLUMN(0, "mode", &mode, "layout to use"),
+		OPT_END()
+	};
+
+	argc = parse_options(argc, argv, "", options, builtin_column_usage, 0);
+
+	while (!strbuf_getline(&sb, stdin, '\n'))
+		string_list_append(&list, sb.buf);
+
+	strbuf_setlen(&sb, left_space);
+	memset(sb.buf, ' ', left_space);
+	display_columns(&list, mode,
+			term_width - right_space - left_space,
+			padding, sb.buf);
+	return 0;
+}
-- 
1.7.4.74.g639db

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 4/9] display_columns: add COL_MODE_{COLUMN,ROW} mode
  2011-03-20 12:57 [PATCH 0/9] column output v3 Nguyễn Thái Ngọc Duy
                   ` (2 preceding siblings ...)
  2011-03-20 12:57 ` [PATCH 3/9] column: add functions to parse column settings Nguyễn Thái Ngọc Duy
@ 2011-03-20 12:57 ` Nguyễn Thái Ngọc Duy
  2011-03-20 12:57 ` [PATCH 5/9] display_columns: add COL_DENSE to do unequal column layout Nguyễn Thái Ngọc Duy
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-03-20 12:57 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

COL_MODE_COLUMN and COL_MODE_ROW fill column by column (or row by row
respectively), given the terminal width and how many space between
columns.

Strings are supposed to be in UTF-8. If strings contain ANSI escape strings,
COL_ANSI must be specified for correct length calculation.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 column.c          |  127 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 column.h          |    3 +
 t/t9002-column.sh |   86 ++++++++++++++++++++++++++++++++++++
 3 files changed, 215 insertions(+), 1 deletions(-)

diff --git a/column.c b/column.c
index b32b9f9..15f74a5 100644
--- a/column.c
+++ b/column.c
@@ -2,8 +2,65 @@
 #include "column.h"
 #include "string-list.h"
 #include "parse-options.h"
+#include "utf8.h"
 
 #define MODE(mode) ((mode) & COL_MODE)
+#define XY2LINEAR(d,x,y) (MODE((d)->mode) == COL_MODE_COLUMN ? \
+			  (x) * (d)->rows + (y) : \
+			  (y) * (d)->cols + (x))
+
+struct column_data {
+	const struct string_list *list; /* list of all cells */
+	int mode;			/* COL_MODE */
+	int total_width;		/* terminal width */
+	int padding;			/* cell padding */
+	const char *indent;		/* left most column indentation */
+
+	int rows, cols;
+	int *len;			/* cell length */
+};
+
+/* return length of 's' in letters, ANSI escapes stripped */
+static int item_length(int mode, const char *s)
+{
+	int len, i = 0;
+	struct strbuf str = STRBUF_INIT;
+
+	if (!(mode & COL_ANSI))
+		return utf8_strwidth(s);
+
+	strbuf_addstr(&str, s);
+	while ((s = strstr(str.buf + i, "\033[")) != NULL) {
+		int len = strspn(s + 2, "0123456789;");
+		i = s - str.buf;
+		strbuf_remove(&str, i, len + 3); /* \033[<len><func char> */
+	}
+	len = utf8_strwidth(str.buf);
+	strbuf_release(&str);
+	return len;
+}
+
+/*
+ * Calculate cell width, rows and cols for a table of equal cells, given
+ * table width and how many spaces between cells.
+ */
+static void layout(struct column_data *data, int *width)
+{
+	int i;
+
+	*width = 0;
+	for (i = 0; i < data->list->nr; i++)
+		if (*width < data->len[i])
+			*width = data->len[i];
+
+	*width += data->padding;
+
+	data->cols = (data->total_width - strlen(data->indent)) / *width;
+	if (data->cols == 0)
+		data->cols = 1;
+
+	data->rows = DIV_ROUND_UP(data->list->nr, data->cols);
+}
 
 struct string_list_item *add_to_columns(struct string_list *list, int mode,
 					const char *string)
@@ -23,6 +80,63 @@ static void display_plain(const struct string_list *list, const char *indent)
 		printf("%s%s\n", indent, list->items[i].string);
 }
 
+/* Print a cell to stdout with all necessary leading/traling space */
+static int display_cell(struct column_data *data, int initial_width,
+			const char *empty_cell, int x, int y)
+{
+	int i, len, newline;
+
+	i = XY2LINEAR(data, x, y);
+	if (i >= data->list->nr)
+		return -1;
+	len = data->len[i];
+	if (MODE(data->mode) == COL_MODE_COLUMN)
+		newline = i + data->rows >= data->list->nr;
+	else
+		newline = x == data->cols - 1 || i == data->list->nr - 1;
+
+	printf("%s%s%s",
+			x == 0 ? data->indent : "",
+			data->list->items[i].string,
+			newline ? "\n" : empty_cell + len);
+	return 0;
+}
+
+/* Display COL_MODE_COLUMN or COL_MODE_ROW */
+static void display_table(const struct string_list *list,
+			  int mode, int total_width,
+			  int padding, const char *indent)
+{
+	struct column_data data;
+	int x, y, i, initial_width;
+	char *empty_cell;
+
+	memset(&data, 0, sizeof(data));
+	data.list = list;
+	data.mode = mode;
+	data.total_width = total_width;
+	data.padding = padding;
+	data.indent = indent;
+
+	data.len = xmalloc(sizeof(*data.len) * list->nr);
+	for (i = 0; i < list->nr; i++)
+		data.len[i] = item_length(mode, list->items[i].string);
+
+	layout(&data, &initial_width);
+
+	empty_cell = xmalloc(initial_width + 1);
+	memset(empty_cell, ' ', initial_width);
+	empty_cell[initial_width] = '\0';
+	for (y = 0; y < data.rows; y++) {
+		for (x = 0; x < data.cols; x++)
+			if (display_cell(&data, initial_width, empty_cell, x, y))
+				break;
+	}
+
+	free(data.len);
+	free(empty_cell);
+}
+
 void display_columns(const struct string_list *list, int mode,
 		     int width, int padding, const char *indent)
 {
@@ -34,7 +148,16 @@ void display_columns(const struct string_list *list, int mode,
 		display_plain(list, indent);
 		return;
 	}
-	die("BUG: invalid mode %d", MODE(mode));
+
+	switch (MODE(mode)) {
+	case COL_MODE_ROW:
+	case COL_MODE_COLUMN:
+		display_table(list, mode, width, padding, indent);
+		break;
+
+	default:
+		die("BUG: invalid mode %d", MODE(mode));
+	}
 }
 
 struct colopt {
@@ -96,6 +219,8 @@ static int parse_option(const char *arg, int len,
 		{ ENABLE, "always",  1 },
 		{ ENABLE, "never",   0 },
 		{ ENABLE, "auto",   -1 },
+		{ MODE,   "column", COL_MODE_COLUMN },
+		{ MODE,   "row",    COL_MODE_ROW },
 	};
 	int i, set, name_len;
 
diff --git a/column.h b/column.h
index a8b24e8..4fb1004 100644
--- a/column.h
+++ b/column.h
@@ -2,8 +2,11 @@
 #define COLUMN_H
 
 #define COL_MODE          0x000F
+#define COL_MODE_COLUMN        0   /* Fill columns before rows */
+#define COL_MODE_ROW           1   /* Fill rows before columns */
 #define COL_ENABLED      (1 << 4)
 #define COL_ENABLED_SET  (1 << 5)  /* Has COL_ENABLED been set? */
+#define COL_ANSI         (1 << 6)  /* Remove ANSI escapes from string length */
 
 extern int term_columns(void);
 extern struct string_list_item *add_to_columns(struct string_list *list, int mode, const char *string);
diff --git a/t/t9002-column.sh b/t/t9002-column.sh
index 099a29f..f801190 100755
--- a/t/t9002-column.sh
+++ b/t/t9002-column.sh
@@ -24,4 +24,90 @@ test_expect_success 'never' '
 	test_cmp lista actual
 '
 
+test_expect_success '80 columns' '
+	cat >expected <<\EOF &&
+one    two    three  four   five   six    seven  eight  nine   ten    eleven
+EOF
+	COLUMNS=80 test-column --mode=column <lista >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'COLUMNS = 1' '
+	cat >expected <<\EOF &&
+one
+two
+three
+four
+five
+six
+seven
+eight
+nine
+ten
+eleven
+EOF
+	COLUMNS=1 test-column --mode=column <lista >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'width = 1' '
+	test-column --mode=column --width=1 <lista >actual &&
+	test_cmp expected actual
+'
+
+COLUMNS=20
+export COLUMNS
+
+test_expect_success '20 columns' '
+	cat >expected <<\EOF &&
+one    seven
+two    eight
+three  nine
+four   ten
+five   eleven
+six
+EOF
+	test-column --mode=column <lista >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success '20 columns, padding 2' '
+	cat >expected <<\EOF &&
+one     seven
+two     eight
+three   nine
+four    ten
+five    eleven
+six
+EOF
+	test-column --mode=column --padding 2 <lista >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success '20 columns, left indented' '
+	cat >expected <<\EOF &&
+  one    seven
+  two    eight
+  three  nine
+  four   ten
+  five   eleven
+  six
+EOF
+	test-column --mode=column --left=2 <lista >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success '20 columns, row first' '
+	cat >expected <<\EOF &&
+one    two
+three  four
+five   six
+seven  eight
+nine   ten
+eleven
+EOF
+	test-column --mode=row <lista >actual &&
+	test_cmp expected actual
+'
+
 test_done
-- 
1.7.4.74.g639db

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 5/9] display_columns: add COL_DENSE to do unequal column layout
  2011-03-20 12:57 [PATCH 0/9] column output v3 Nguyễn Thái Ngọc Duy
                   ` (3 preceding siblings ...)
  2011-03-20 12:57 ` [PATCH 4/9] display_columns: add COL_MODE_{COLUMN,ROW} mode Nguyễn Thái Ngọc Duy
@ 2011-03-20 12:57 ` Nguyễn Thái Ngọc Duy
  2011-03-20 12:57 ` [PATCH 6/9] column: add column.ui for default column output settings Nguyễn Thái Ngọc Duy
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-03-20 12:57 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 column.c          |   80 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 column.h          |    1 +
 t/t9002-column.sh |   22 ++++++++++++++
 3 files changed, 103 insertions(+), 0 deletions(-)

diff --git a/column.c b/column.c
index 15f74a5..69d42f8 100644
--- a/column.c
+++ b/column.c
@@ -18,6 +18,7 @@ struct column_data {
 
 	int rows, cols;
 	int *len;			/* cell length */
+	int *width;			/* index to the longest row in column */
 };
 
 /* return length of 's' in letters, ANSI escapes stripped */
@@ -62,6 +63,69 @@ static void layout(struct column_data *data, int *width)
 	data->rows = DIV_ROUND_UP(data->list->nr, data->cols);
 }
 
+static void compute_column_width(struct column_data *data)
+{
+	int i, x, y;
+	for (x = 0; x < data->cols; x++) {
+		data->width[x] = XY2LINEAR(data, x, 0);
+		for (y = 0; y < data->rows; y++) {
+			i = XY2LINEAR(data, x, y);
+			if (i >= data->list->nr)
+				continue;
+			if (data->len[data->width[x]] < data->len[i])
+				data->width[x] = i;
+		}
+	}
+}
+
+/*
+ * Shrink all columns by shortening them one row each time (and adding
+ * more columns along the way). Hopefully the longest cell will be
+ * moved to the next column, column is shrunk so we have more space
+ * for new columns. The process ends when the whole thing no longer
+ * fits in data->total_width.
+ */
+static void shrink_columns(struct column_data *data)
+{
+	int x, y, total_width, cols, rows;
+
+	data->width = xrealloc(data->width,
+			       sizeof(*data->width) * data->cols);
+	for (x = 0; x < data->cols; x++) {
+		data->width[x] = 0;
+		for (y = 0; y < data->rows; y++) {
+			int len1 = data->len[data->width[x]];
+			int len2 = data->len[XY2LINEAR(data, x, y)];
+			if (len1 < len2)
+				data->width[x] = y;
+		}
+	}
+
+	while (data->rows > 1) {
+		rows = data->rows;
+		cols = data->cols;
+
+		data->rows--;
+		data->cols = DIV_ROUND_UP(data->list->nr, data->rows);
+		if (data->cols != cols)
+			data->width = xrealloc(data->width, sizeof(*data->width) * data->cols);
+
+		compute_column_width(data);
+
+		total_width = strlen(data->indent);
+		for (x = 0; x < data->cols; x++) {
+			total_width += data->len[data->width[x]];
+			total_width += data->padding;
+		}
+		if (total_width > data->total_width) {
+			data->rows = rows;
+			data->cols = cols;
+			compute_column_width(data);
+			break;
+		}
+	}
+}
+
 struct string_list_item *add_to_columns(struct string_list *list, int mode,
 					const char *string)
 {
@@ -89,7 +153,18 @@ static int display_cell(struct column_data *data, int initial_width,
 	i = XY2LINEAR(data, x, y);
 	if (i >= data->list->nr)
 		return -1;
+
 	len = data->len[i];
+	if (data->width && data->len[data->width[x]] < initial_width) {
+		/*
+		 * empty_cell has initial_width chars, if real column
+		 * is narrower, increase len a bit so we fill less
+		 * space.
+		 */
+		len += initial_width - data->len[data->width[x]];
+		len -= data->padding;
+	}
+
 	if (MODE(data->mode) == COL_MODE_COLUMN)
 		newline = i + data->rows >= data->list->nr;
 	else
@@ -124,6 +199,9 @@ static void display_table(const struct string_list *list,
 
 	layout(&data, &initial_width);
 
+	if (mode & COL_DENSE)
+		shrink_columns(&data);
+
 	empty_cell = xmalloc(initial_width + 1);
 	memset(empty_cell, ' ', initial_width);
 	empty_cell[initial_width] = '\0';
@@ -134,6 +212,7 @@ static void display_table(const struct string_list *list,
 	}
 
 	free(data.len);
+	free(data.width);
 	free(empty_cell);
 }
 
@@ -221,6 +300,7 @@ static int parse_option(const char *arg, int len,
 		{ ENABLE, "auto",   -1 },
 		{ MODE,   "column", COL_MODE_COLUMN },
 		{ MODE,   "row",    COL_MODE_ROW },
+		{ OPTION, "dense",  COL_DENSE },
 	};
 	int i, set, name_len;
 
diff --git a/column.h b/column.h
index 4fb1004..48c6345 100644
--- a/column.h
+++ b/column.h
@@ -7,6 +7,7 @@
 #define COL_ENABLED      (1 << 4)
 #define COL_ENABLED_SET  (1 << 5)  /* Has COL_ENABLED been set? */
 #define COL_ANSI         (1 << 6)  /* Remove ANSI escapes from string length */
+#define COL_DENSE        (1 << 7)  /* Shrink columns when possible, making space for more columns */
 
 extern int term_columns(void);
 extern struct string_list_item *add_to_columns(struct string_list *list, int mode, const char *string);
diff --git a/t/t9002-column.sh b/t/t9002-column.sh
index f801190..07161a9 100755
--- a/t/t9002-column.sh
+++ b/t/t9002-column.sh
@@ -71,6 +71,17 @@ EOF
 	test_cmp expected actual
 '
 
+test_expect_success '20 columns, dense' '
+	cat >expected <<\EOF &&
+one   five  nine
+two   six   ten
+three seven eleven
+four  eight
+EOF
+	test-column --mode=column,dense < lista > actual &&
+	test_cmp expected actual
+'
+
 test_expect_success '20 columns, padding 2' '
 	cat >expected <<\EOF &&
 one     seven
@@ -110,4 +121,15 @@ EOF
 	test_cmp expected actual
 '
 
+test_expect_success '20 columns, row first, dense' '
+	cat >expected <<\EOF &&
+one   two    three
+four  five   six
+seven eight  nine
+ten   eleven
+EOF
+	test-column --mode=row,dense <lista >actual &&
+	test_cmp expected actual
+'
+
 test_done
-- 
1.7.4.74.g639db

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 6/9] column: add column.ui for default column output settings
  2011-03-20 12:57 [PATCH 0/9] column output v3 Nguyễn Thái Ngọc Duy
                   ` (4 preceding siblings ...)
  2011-03-20 12:57 ` [PATCH 5/9] display_columns: add COL_DENSE to do unequal column layout Nguyễn Thái Ngọc Duy
@ 2011-03-20 12:57 ` Nguyễn Thái Ngọc Duy
  2011-03-20 12:57 ` [PATCH 7/9] help: reuse display_columns() for help -a Nguyễn Thái Ngọc Duy
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-03-20 12:57 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/config.txt |   24 ++++++++++++++++++++++++
 column.c                 |   11 +++++++++++
 column.h                 |    3 +++
 3 files changed, 38 insertions(+), 0 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index c5e1835..7183712 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -805,6 +805,30 @@ color.ui::
 	terminal. When more specific variables of color.* are set, they always
 	take precedence over this setting. Defaults to false.
 
+column.ui::
+	Specify whether supported commands should output in columns.
+	This variable consists of a list of tokens separated by spaces
+	or commas:
++
+--
+`always`;;
+	always show in columns
+`never`;;
+	never show in columns
+`auto`;;
+	show in columns if the output is to the terminal
+`column`;;
+	fill columns before rows (default)
+`row`;;
+	fill rows before columns
+`dense`;;
+	make unequal size columns to utilize more space
+`nodense`;;
+	make equal size columns
+--
++
+	This option defaults to 'never'.
+
 commit.status::
 	A boolean to enable/disable inclusion of status information in the
 	commit message template when using an editor to prepare the commit
diff --git a/column.c b/column.c
index 69d42f8..7c1a6f1 100644
--- a/column.c
+++ b/column.c
@@ -2,6 +2,7 @@
 #include "column.h"
 #include "string-list.h"
 #include "parse-options.h"
+#include "color.h"
 #include "utf8.h"
 
 #define MODE(mode) ((mode) & COL_MODE)
@@ -21,6 +22,8 @@ struct column_data {
 	int *width;			/* index to the longest row in column */
 };
 
+int git_core_column;
+
 /* return length of 's' in letters, ANSI escapes stripped */
 static int item_length(int mode, const char *s)
 {
@@ -350,6 +353,14 @@ static int parse_string(int *mode, const char *value,
 	return 0;
 }
 
+int git_column_default_config(const char *var, const char *value, void *cb)
+{
+	if (!strcmp(var, "column.ui"))
+		return parse_string(&git_core_column, value, -1);
+
+	return git_color_default_config(var, value, cb);
+}
+
 int parseopt_column_callback(const struct option *opt,
 			     const char *arg, int unset)
 {
diff --git a/column.h b/column.h
index 48c6345..0f4190d 100644
--- a/column.h
+++ b/column.h
@@ -9,9 +9,12 @@
 #define COL_ANSI         (1 << 6)  /* Remove ANSI escapes from string length */
 #define COL_DENSE        (1 << 7)  /* Shrink columns when possible, making space for more columns */
 
+extern int git_core_column;
+
 extern int term_columns(void);
 extern struct string_list_item *add_to_columns(struct string_list *list, int mode, const char *string);
 extern void display_columns(const struct string_list *list, int mode, int width, int padding, const char *indent);
+extern int git_column_default_config(const char *var, const char *value, void *cb);
 
 struct option;
 extern int parseopt_column_callback(const struct option *opt, const char *arg, int unset);
-- 
1.7.4.74.g639db

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 7/9] help: reuse display_columns() for help -a
  2011-03-20 12:57 [PATCH 0/9] column output v3 Nguyễn Thái Ngọc Duy
                   ` (5 preceding siblings ...)
  2011-03-20 12:57 ` [PATCH 6/9] column: add column.ui for default column output settings Nguyễn Thái Ngọc Duy
@ 2011-03-20 12:57 ` Nguyễn Thái Ngọc Duy
  2011-03-20 16:04   ` Nguyễn Thái Ngọc Duy
  2011-03-20 12:57 ` [PATCH 8/9] tag: add --column Nguyễn Thái Ngọc Duy
  2011-03-20 12:57 ` [PATCH 9/9] branch: " Nguyễn Thái Ngọc Duy
  8 siblings, 1 reply; 13+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-03-20 12:57 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 help.c |   30 ++++++++----------------------
 1 files changed, 8 insertions(+), 22 deletions(-)

diff --git a/help.c b/help.c
index 768f64c..dcc8b81 100644
--- a/help.c
+++ b/help.c
@@ -4,6 +4,7 @@
 #include "levenshtein.h"
 #include "help.h"
 #include "common-cmds.h"
+#include "string-list.h"
 #include "column.h"
 
 void add_cmdname(struct cmdnames *cmds, const char *name, int len)
@@ -73,29 +74,14 @@ void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes)
 
 static void pretty_print_string_list(struct cmdnames *cmds, int longest)
 {
-	int cols = 1, rows;
-	int space = longest + 1; /* min 1 SP between words */
-	int max_cols = term_columns() - 1; /* don't print *on* the edge */
-	int i, j;
-
-	if (space < max_cols)
-		cols = max_cols / space;
-	rows = DIV_ROUND_UP(cmds->cnt, cols);
-
-	for (i = 0; i < rows; i++) {
-		printf("  ");
+	struct string_list list = STRING_LIST_INIT_NODUP;
+	int i;
 
-		for (j = 0; j < cols; j++) {
-			int n = j * rows + i;
-			int size = space;
-			if (n >= cmds->cnt)
-				break;
-			if (j == cols-1 || n + rows >= cmds->cnt)
-				size = 1;
-			printf("%-*s", size, cmds->names[n]->name);
-		}
-		putchar('\n');
-	}
+	for (i = 0; i < cmds->cnt; i++)
+		string_list_append(&list, cmds->names[i]->name);
+	display_columns(&list, COL_MODE_COLUMN | COL_ENABLED,
+			term_columns(), 1, "  ");
+	string_list_clear(&list, 0);
 }
 
 static int is_executable(const char *name)
-- 
1.7.4.74.g639db

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 8/9] tag: add --column
  2011-03-20 12:57 [PATCH 0/9] column output v3 Nguyễn Thái Ngọc Duy
                   ` (6 preceding siblings ...)
  2011-03-20 12:57 ` [PATCH 7/9] help: reuse display_columns() for help -a Nguyễn Thái Ngọc Duy
@ 2011-03-20 12:57 ` Nguyễn Thái Ngọc Duy
  2011-03-20 12:57 ` [PATCH 9/9] branch: " Nguyễn Thái Ngọc Duy
  8 siblings, 0 replies; 13+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-03-20 12:57 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/git-tag.txt |   11 ++++++++++-
 Makefile                  |    2 +-
 builtin/tag.c             |   21 +++++++++++++++++----
 3 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
index 8b169e3..0260eea 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -12,7 +12,8 @@ SYNOPSIS
 'git tag' [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>]
 	<tagname> [<commit> | <object>]
 'git tag' -d <tagname>...
-'git tag' [-n[<num>]] -l [--contains <commit>] [<pattern>]
+'git tag' [-n[<num>]] -l [--column[=<options>] | --no-column]
+	[--contains <commit>] [<pattern>]
 'git tag' -v <tagname>...
 
 DESCRIPTION
@@ -71,6 +72,14 @@ OPTIONS
 	List tags with names that match the given pattern (or all if no pattern is given).
 	Typing "git tag" without arguments, also lists all tags.
 
+--column[=<options>]::
+--no-column::
+	Override column.ui settings. See linkgit:git-config.txt[1] for
+	syntax. `--column` and `--no-column` without options are
+	equivalent to 'always' and 'never' respectively. This option
+	is only applicable if `git tag` is used to list tags without
+	annotation lines.
+
 --contains <commit>::
 	Only list tags which contain the specified commit.
 
diff --git a/Makefile b/Makefile
index ba9944b..e1823dd 100644
--- a/Makefile
+++ b/Makefile
@@ -1958,7 +1958,7 @@ builtin/prune.o builtin/reflog.o reachable.o: reachable.h
 builtin/commit.o builtin/revert.o wt-status.o: wt-status.h
 builtin/tar-tree.o archive-tar.o: tar.h
 connect.o transport.o http-backend.o: url.h
-column.o help.o pager.o: column.h
+builtin/tag.o column.o help.o pager.o: column.h
 http-fetch.o http-walker.o remote-curl.o transport.o walker.o: walker.h
 http.o http-walker.o http-push.o http-fetch.o remote-curl.o: http.h url.h
 
diff --git a/builtin/tag.c b/builtin/tag.c
index aa1f87d..cdf0f74 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -12,6 +12,8 @@
 #include "tag.h"
 #include "run-command.h"
 #include "parse-options.h"
+#include "string-list.h"
+#include "column.h"
 
 static const char * const git_tag_usage[] = {
 	"git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]",
@@ -22,6 +24,8 @@ static const char * const git_tag_usage[] = {
 };
 
 static char signingkey[1000];
+static struct string_list output = STRING_LIST_INIT_DUP;
+static int column_mode;
 
 struct tag_filter {
 	const char *pattern;
@@ -52,7 +56,7 @@ static int show_reference(const char *refname, const unsigned char *sha1,
 		}
 
 		if (!filter->lines) {
-			printf("%s\n", refname);
+			add_to_columns(&output, column_mode, refname);
 			return 0;
 		}
 		printf("%-15s ", refname);
@@ -233,7 +237,7 @@ static int git_tag_config(const char *var, const char *value, void *cb)
 		return 0;
 	}
 
-	return git_default_config(var, value, cb);
+	return git_column_default_config(var, value, cb);
 }
 
 static void write_tag_body(int fd, const unsigned char *sha1)
@@ -383,6 +387,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		OPT_STRING('u', NULL, &keyid, "key-id",
 					"use another key to sign the tag"),
 		OPT__FORCE(&force, "replace the tag if exists"),
+		OPT_COLUMN(0, "column", &column_mode, "show tag list in columns" ),
 
 		OPT_GROUP("Tag listing options"),
 		{
@@ -395,6 +400,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 	};
 
 	git_config(git_tag_config, NULL);
+	column_mode = git_core_column;
 
 	argc = parse_options(argc, argv, prefix, options, git_tag_usage, 0);
 
@@ -413,9 +419,16 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 
 	if (list + delete + verify > 1)
 		usage_with_options(git_tag_usage, options);
-	if (list)
-		return list_tags(argv[0], lines == -1 ? 0 : lines,
+	if (list) {
+		int ret;
+
+		if (lines != -1)
+			column_mode = 0;
+		ret =  list_tags(argv[0], lines == -1 ? 0 : lines,
 				 with_commit);
+		display_columns(&output, column_mode, term_columns(), 2, "");
+		return ret;
+	}
 	if (lines != -1)
 		die("-n option is only allowed with -l.");
 	if (with_commit)
-- 
1.7.4.74.g639db

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 9/9] branch: add --column
  2011-03-20 12:57 [PATCH 0/9] column output v3 Nguyễn Thái Ngọc Duy
                   ` (7 preceding siblings ...)
  2011-03-20 12:57 ` [PATCH 8/9] tag: add --column Nguyễn Thái Ngọc Duy
@ 2011-03-20 12:57 ` Nguyễn Thái Ngọc Duy
  2011-03-20 19:52   ` Teemu Likonen
  8 siblings, 1 reply; 13+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-03-20 12:57 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/git-branch.txt |    9 +++++++++
 Makefile                     |    2 +-
 builtin/branch.c             |   23 +++++++++++++++++++----
 3 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index 9106d38..a7bf4a8 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -9,6 +9,7 @@ SYNOPSIS
 --------
 [verse]
 'git branch' [--color[=<when>] | --no-color] [-r | -a]
+	[--column[=<options>] | --no-column]
 	[-v [--abbrev=<length> | --no-abbrev]]
 	[(--merged | --no-merged | --contains) [<commit>]]
 'git branch' [--set-upstream | --track | --no-track] [-l] [-f] <branchname> [<start-point>]
@@ -99,6 +100,14 @@ OPTIONS
 	default to color output.
 	Same as `--color=never`.
 
+--column[=<options>]::
+--no-column::
+	Override column.ui settings. See linkgit:git-config.txt[1] for
+	syntax. `--column` and `--no-column` without options are
+	equivalent to 'always' and 'never' respectively. This option
+	is only applicable if `git tag` is used to list tags without
+	annotation lines.
+
 -r::
 	List or delete (if used with -d) the remote-tracking branches.
 
diff --git a/Makefile b/Makefile
index e1823dd..92c49ac 100644
--- a/Makefile
+++ b/Makefile
@@ -1958,7 +1958,7 @@ builtin/prune.o builtin/reflog.o reachable.o: reachable.h
 builtin/commit.o builtin/revert.o wt-status.o: wt-status.h
 builtin/tar-tree.o archive-tar.o: tar.h
 connect.o transport.o http-backend.o: url.h
-builtin/tag.o column.o help.o pager.o: column.h
+builtin/branch.o builtin/tag.o column.o help.o pager.o: column.h
 http-fetch.o http-walker.o remote-curl.o transport.o walker.o: walker.h
 http.o http-walker.o http-push.o http-fetch.o remote-curl.o: http.h url.h
 
diff --git a/builtin/branch.c b/builtin/branch.c
index 9e546e4..ff94192 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -15,6 +15,8 @@
 #include "branch.h"
 #include "diff.h"
 #include "revision.h"
+#include "string-list.h"
+#include "column.h"
 
 static const char * const builtin_branch_usage[] = {
 	"git branch [options] [-r | -a] [--merged | --no-merged]",
@@ -53,6 +55,9 @@ static enum merge_filter {
 } merge_filter;
 static unsigned char merge_filter_ref[20];
 
+static struct string_list output = STRING_LIST_INIT_DUP;
+static int column_mode;
+
 static int parse_branch_color_slot(const char *var, int ofs)
 {
 	if (!strcasecmp(var+ofs, "plain"))
@@ -83,7 +88,7 @@ static int git_branch_config(const char *var, const char *value, void *cb)
 		color_parse(value, var, branch_colors[slot]);
 		return 0;
 	}
-	return git_color_default_config(var, value, cb);
+	return git_column_default_config(var, value, cb);
 }
 
 static const char *branch_get_color(enum color_branch ix)
@@ -451,7 +456,7 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
 		strbuf_release(&stat);
 		strbuf_release(&subject);
 	}
-	printf("%s\n", out.buf);
+	add_to_columns(&output, column_mode, out.buf);
 	strbuf_release(&name);
 	strbuf_release(&out);
 }
@@ -660,6 +665,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG,
 			opt_parse_merge_filter, (intptr_t) "HEAD",
 		},
+		OPT_COLUMN(0, "column", &column_mode, "list branches in columns" ),
 		OPT_END(),
 	};
 
@@ -686,6 +692,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 	}
 	hashcpy(merge_filter_ref, head_sha1);
 
+	column_mode = git_core_column | COL_ANSI;
+
 	argc = parse_options(argc, argv, prefix, options, builtin_branch_usage,
 			     0);
 	if (!!delete + !!rename + !!force_create > 1)
@@ -693,8 +701,15 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 
 	if (delete)
 		return delete_branches(argc, argv, delete > 1, kinds);
-	else if (argc == 0)
-		return print_ref_list(kinds, detached, verbose, abbrev, with_commit);
+	else if (argc == 0) {
+		int ret;
+		if (verbose)
+			column_mode = 0;
+
+		ret = print_ref_list(kinds, detached, verbose, abbrev, with_commit);
+		display_columns(&output, column_mode, term_columns(), 1, "");
+		return ret;
+	}
 	else if (rename && (argc == 1))
 		rename_branch(head, argv[0], rename > 1);
 	else if (rename && (argc == 2))
-- 
1.7.4.74.g639db

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 7/9] help: reuse display_columns() for help -a
  2011-03-20 12:57 ` [PATCH 7/9] help: reuse display_columns() for help -a Nguyễn Thái Ngọc Duy
@ 2011-03-20 16:04   ` Nguyễn Thái Ngọc Duy
  0 siblings, 0 replies; 13+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-03-20 16:04 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 This one is better. Because 'longest' is no longer used, all support
 code may be removed as well.

 help.c |   45 +++++++++++----------------------------------
 1 files changed, 11 insertions(+), 34 deletions(-)

diff --git a/help.c b/help.c
index 768f64c..92150ea 100644
--- a/help.c
+++ b/help.c
@@ -4,6 +4,7 @@
 #include "levenshtein.h"
 #include "help.h"
 #include "common-cmds.h"
+#include "string-list.h"
 #include "column.h"
 
 void add_cmdname(struct cmdnames *cmds, const char *name, int len)
@@ -71,31 +72,16 @@ void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes)
 	cmds->cnt = cj;
 }
 
-static void pretty_print_string_list(struct cmdnames *cmds, int longest)
+static void pretty_print_string_list(struct cmdnames *cmds)
 {
-	int cols = 1, rows;
-	int space = longest + 1; /* min 1 SP between words */
-	int max_cols = term_columns() - 1; /* don't print *on* the edge */
-	int i, j;
-
-	if (space < max_cols)
-		cols = max_cols / space;
-	rows = DIV_ROUND_UP(cmds->cnt, cols);
-
-	for (i = 0; i < rows; i++) {
-		printf("  ");
+	struct string_list list = STRING_LIST_INIT_NODUP;
+	int i;
 
-		for (j = 0; j < cols; j++) {
-			int n = j * rows + i;
-			int size = space;
-			if (n >= cmds->cnt)
-				break;
-			if (j == cols-1 || n + rows >= cmds->cnt)
-				size = 1;
-			printf("%-*s", size, cmds->names[n]->name);
-		}
-		putchar('\n');
-	}
+	for (i = 0; i < cmds->cnt; i++)
+		string_list_append(&list, cmds->names[i]->name);
+	display_columns(&list, COL_MODE_COLUMN | COL_ENABLED,
+			term_columns(), 1, "  ");
+	string_list_clear(&list, 0);
 }
 
 static int is_executable(const char *name)
@@ -204,22 +190,13 @@ void load_command_list(const char *prefix,
 void list_commands(const char *title, struct cmdnames *main_cmds,
 		   struct cmdnames *other_cmds)
 {
-	int i, longest = 0;
-
-	for (i = 0; i < main_cmds->cnt; i++)
-		if (longest < main_cmds->names[i]->len)
-			longest = main_cmds->names[i]->len;
-	for (i = 0; i < other_cmds->cnt; i++)
-		if (longest < other_cmds->names[i]->len)
-			longest = other_cmds->names[i]->len;
-
 	if (main_cmds->cnt) {
 		const char *exec_path = git_exec_path();
 		printf("available %s in '%s'\n", title, exec_path);
 		printf("----------------");
 		mput_char('-', strlen(title) + strlen(exec_path));
 		putchar('\n');
-		pretty_print_string_list(main_cmds, longest);
+		pretty_print_string_list(main_cmds);
 		putchar('\n');
 	}
 
@@ -228,7 +205,7 @@ void list_commands(const char *title, struct cmdnames *main_cmds,
 		printf("---------------------------------------");
 		mput_char('-', strlen(title));
 		putchar('\n');
-		pretty_print_string_list(other_cmds, longest);
+		pretty_print_string_list(other_cmds);
 		putchar('\n');
 	}
 }
-- 
1.7.4.74.g639db

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 9/9] branch: add --column
  2011-03-20 12:57 ` [PATCH 9/9] branch: " Nguyễn Thái Ngọc Duy
@ 2011-03-20 19:52   ` Teemu Likonen
  2011-03-20 23:26     ` Nguyễn Thái Ngọc Duy
  0 siblings, 1 reply; 13+ messages in thread
From: Teemu Likonen @ 2011-03-20 19:52 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: git

* 2011-03-20 19:57 (+0700), Nguyễn Thái Ngọc Duy wrote:

> diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
> index 9106d38..a7bf4a8 100644
> --- a/Documentation/git-branch.txt
> +++ b/Documentation/git-branch.txt

> +--column[=<options>]::
> +--no-column::
> +	Override column.ui settings. See linkgit:git-config.txt[1] for
> +	syntax. `--column` and `--no-column` without options are
> +	equivalent to 'always' and 'never' respectively. This option
> +	is only applicable if `git tag` is used to list tags without
> +	annotation lines.
> +
                                
I admit that I have not been following the development of this feature
but I'll confirm this anyway: Do you really mean to speak of "git tag"
in the man page of "git branch"?

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 9/9] branch: add --column
  2011-03-20 19:52   ` Teemu Likonen
@ 2011-03-20 23:26     ` Nguyễn Thái Ngọc Duy
  0 siblings, 0 replies; 13+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-03-20 23:26 UTC (permalink / raw)
  To: git, Teemu Likonen; +Cc: Nguyễn Thái Ngọc Duy


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 2011/3/21 Teemu Likonen <tlikonen@iki.fi>:
 > I admit that I have not been following the development of this feature
 > but I'll confirm this anyway: Do you really mean to speak of "git tag"
 > in the man page of "git branch"?
 >

 Copy/paste error. Fixed

 Documentation/git-branch.txt |    8 ++++++++
 Makefile                     |    2 +-
 builtin/branch.c             |   23 +++++++++++++++++++----
 3 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index 9106d38..f129339 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -9,6 +9,7 @@ SYNOPSIS
 --------
 [verse]
 'git branch' [--color[=<when>] | --no-color] [-r | -a]
+	[--column[=<options>] | --no-column]
 	[-v [--abbrev=<length> | --no-abbrev]]
 	[(--merged | --no-merged | --contains) [<commit>]]
 'git branch' [--set-upstream | --track | --no-track] [-l] [-f] <branchname> [<start-point>]
@@ -99,6 +100,13 @@ OPTIONS
 	default to color output.
 	Same as `--color=never`.
 
+--column[=<options>]::
+--no-column::
+	Override column.ui settings. See linkgit:git-config.txt[1] for
+	syntax. `--column` and `--no-column` without options are
+	equivalent to 'always' and 'never' respectively. This option
+	is only applicable in non-verbose mode.
+
 -r::
 	List or delete (if used with -d) the remote-tracking branches.
 
diff --git a/Makefile b/Makefile
index e1823dd..92c49ac 100644
--- a/Makefile
+++ b/Makefile
@@ -1958,7 +1958,7 @@ builtin/prune.o builtin/reflog.o reachable.o: reachable.h
 builtin/commit.o builtin/revert.o wt-status.o: wt-status.h
 builtin/tar-tree.o archive-tar.o: tar.h
 connect.o transport.o http-backend.o: url.h
-builtin/tag.o column.o help.o pager.o: column.h
+builtin/branch.o builtin/tag.o column.o help.o pager.o: column.h
 http-fetch.o http-walker.o remote-curl.o transport.o walker.o: walker.h
 http.o http-walker.o http-push.o http-fetch.o remote-curl.o: http.h url.h
 
diff --git a/builtin/branch.c b/builtin/branch.c
index 9e546e4..ff94192 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -15,6 +15,8 @@
 #include "branch.h"
 #include "diff.h"
 #include "revision.h"
+#include "string-list.h"
+#include "column.h"
 
 static const char * const builtin_branch_usage[] = {
 	"git branch [options] [-r | -a] [--merged | --no-merged]",
@@ -53,6 +55,9 @@ static enum merge_filter {
 } merge_filter;
 static unsigned char merge_filter_ref[20];
 
+static struct string_list output = STRING_LIST_INIT_DUP;
+static int column_mode;
+
 static int parse_branch_color_slot(const char *var, int ofs)
 {
 	if (!strcasecmp(var+ofs, "plain"))
@@ -83,7 +88,7 @@ static int git_branch_config(const char *var, const char *value, void *cb)
 		color_parse(value, var, branch_colors[slot]);
 		return 0;
 	}
-	return git_color_default_config(var, value, cb);
+	return git_column_default_config(var, value, cb);
 }
 
 static const char *branch_get_color(enum color_branch ix)
@@ -451,7 +456,7 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
 		strbuf_release(&stat);
 		strbuf_release(&subject);
 	}
-	printf("%s\n", out.buf);
+	add_to_columns(&output, column_mode, out.buf);
 	strbuf_release(&name);
 	strbuf_release(&out);
 }
@@ -660,6 +665,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG,
 			opt_parse_merge_filter, (intptr_t) "HEAD",
 		},
+		OPT_COLUMN(0, "column", &column_mode, "list branches in columns" ),
 		OPT_END(),
 	};
 
@@ -686,6 +692,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 	}
 	hashcpy(merge_filter_ref, head_sha1);
 
+	column_mode = git_core_column | COL_ANSI;
+
 	argc = parse_options(argc, argv, prefix, options, builtin_branch_usage,
 			     0);
 	if (!!delete + !!rename + !!force_create > 1)
@@ -693,8 +701,15 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 
 	if (delete)
 		return delete_branches(argc, argv, delete > 1, kinds);
-	else if (argc == 0)
-		return print_ref_list(kinds, detached, verbose, abbrev, with_commit);
+	else if (argc == 0) {
+		int ret;
+		if (verbose)
+			column_mode = 0;
+
+		ret = print_ref_list(kinds, detached, verbose, abbrev, with_commit);
+		display_columns(&output, column_mode, term_columns(), 1, "");
+		return ret;
+	}
 	else if (rename && (argc == 1))
 		rename_branch(head, argv[0], rename > 1);
 	else if (rename && (argc == 2))
-- 
1.7.4.74.g639db

^ permalink raw reply related	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2011-03-20 23:26 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-03-20 12:57 [PATCH 0/9] column output v3 Nguyễn Thái Ngọc Duy
2011-03-20 12:57 ` [PATCH 1/9] Move term_columns() to pager.c and save terminal width before pager Nguyễn Thái Ngọc Duy
2011-03-20 12:57 ` [PATCH 2/9] Add display_columns() to display in columnar layout Nguyễn Thái Ngọc Duy
2011-03-20 12:57 ` [PATCH 3/9] column: add functions to parse column settings Nguyễn Thái Ngọc Duy
2011-03-20 12:57 ` [PATCH 4/9] display_columns: add COL_MODE_{COLUMN,ROW} mode Nguyễn Thái Ngọc Duy
2011-03-20 12:57 ` [PATCH 5/9] display_columns: add COL_DENSE to do unequal column layout Nguyễn Thái Ngọc Duy
2011-03-20 12:57 ` [PATCH 6/9] column: add column.ui for default column output settings Nguyễn Thái Ngọc Duy
2011-03-20 12:57 ` [PATCH 7/9] help: reuse display_columns() for help -a Nguyễn Thái Ngọc Duy
2011-03-20 16:04   ` Nguyễn Thái Ngọc Duy
2011-03-20 12:57 ` [PATCH 8/9] tag: add --column Nguyễn Thái Ngọc Duy
2011-03-20 12:57 ` [PATCH 9/9] branch: " Nguyễn Thái Ngọc Duy
2011-03-20 19:52   ` Teemu Likonen
2011-03-20 23:26     ` Nguyễn Thái Ngọc Duy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).