git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Cc: "Junio C Hamano" <gitster@pobox.com>,
	"Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH v6 05/11] column: support columns with different widths
Date: Sat, 25 Feb 2012 18:41:12 +0700	[thread overview]
Message-ID: <1330170078-29353-6-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <1330170078-29353-1-git-send-email-pclouds@gmail.com>

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

diff --git a/column.c b/column.c
index 6dca3b8..3c77997 100644
--- a/column.c
+++ b/column.c
@@ -19,6 +19,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 */
@@ -63,6 +64,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;
+		}
+	}
+}
+
 /* Display without layout when COL_ENABLED is not set */
 static void display_plain(const struct string_list *list,
 			  const char *indent, const char *nl)
@@ -82,7 +146,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
@@ -119,6 +194,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';
@@ -129,6 +207,7 @@ static void display_table(const struct string_list *list,
 	}
 
 	free(data.len);
+	free(data.width);
 	free(empty_cell);
 }
 
@@ -227,6 +306,7 @@ static int parse_option(const char *arg, int len,
 		{ MODE,   "column", COL_MODE_COLUMN },
 		{ MODE,   "row",    COL_MODE_ROW },
 		{ OPTION, "color",  COL_ANSI },
+		{ OPTION, "dense",  COL_DENSE },
 	};
 	int i;
 
diff --git a/column.h b/column.h
index d9d27c6..eb03c6c 100644
--- a/column.h
+++ b/column.h
@@ -7,6 +7,8 @@
 #define COL_ENABLED      (1 << 4)
 #define COL_ENABLED_SET  (1 << 5)  /* Has COL_ENABLED been set by config? */
 #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 */
 #define COL_PARSEOPT     (1 << 8)  /* --column is given */
 
 #define explicitly_enable_column(c) \
diff --git a/t/t9002-column.sh b/t/t9002-column.sh
index cffb029..fe7a30e 100755
--- a/t/t9002-column.sh
+++ b/t/t9002-column.sh
@@ -71,6 +71,30 @@ EOF
 	test_cmp expected actual
 '
 
+test_expect_success '20 columns, nodense' '
+	cat >expected <<\EOF &&
+one    seven
+two    eight
+three  nine
+four   ten
+five   eleven
+six
+EOF
+	git column --mode=column,nodense < lista > actual &&
+	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
+	git column --mode=column,dense < lista > actual &&
+	test_cmp expected actual
+'
+
 test_expect_success '20 columns, padding 2' '
 	cat >expected <<\EOF &&
 one     seven
@@ -110,4 +134,28 @@ EOF
 	test_cmp expected actual
 '
 
+test_expect_success '20 columns, row first, nodense' '
+	cat >expected <<\EOF &&
+one    two
+three  four
+five   six
+seven  eight
+nine   ten
+eleven
+EOF
+	git column --mode=row,nodense <lista >actual &&
+	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
+	git column --mode=row,dense <lista >actual &&
+	test_cmp expected actual
+'
+
 test_done
-- 
1.7.8.36.g69ee2

  parent reply	other threads:[~2012-02-25 11:39 UTC|newest]

Thread overview: 66+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-02-25 11:41 [PATCH v6 00/11] Column display Nguyễn Thái Ngọc Duy
2012-02-25 11:41 ` [PATCH v6 01/11] column: add API to print items in columns Nguyễn Thái Ngọc Duy
2012-02-25 11:41 ` [PATCH v6 02/11] Add git-column and column mode parsing Nguyễn Thái Ngọc Duy
2012-02-27 20:09   ` Ramsay Jones
2012-02-28 11:00     ` Nguyen Thai Ngoc Duy
2012-02-25 11:41 ` [PATCH v6 03/11] Stop starting pager recursively Nguyễn Thái Ngọc Duy
2012-02-25 11:41 ` [PATCH v6 04/11] column: add columnar layout Nguyễn Thái Ngọc Duy
2012-02-25 11:41 ` Nguyễn Thái Ngọc Duy [this message]
2012-02-26 23:12   ` [PATCH v6 05/11] column: support columns with different widths Junio C Hamano
2012-02-25 11:41 ` [PATCH v6 06/11] column: add column.ui for default column output settings Nguyễn Thái Ngọc Duy
2012-02-27  6:20   ` Junio C Hamano
2012-02-27  7:04     ` Nguyen Thai Ngoc Duy
2012-02-25 11:41 ` [PATCH v6 07/11] help: reuse print_columns() for help -a Nguyễn Thái Ngọc Duy
2012-02-25 11:41 ` [PATCH v6 08/11] branch: add --column Nguyễn Thái Ngọc Duy
2012-02-25 11:41 ` [PATCH v6 09/11] status: " Nguyễn Thái Ngọc Duy
2012-02-25 11:41 ` [PATCH v6 10/11] column: support piping stdout to external git-column process Nguyễn Thái Ngọc Duy
2012-02-25 11:41 ` [PATCH v6 11/11] tag: add --column Nguyễn Thái Ngọc Duy
2012-02-26 23:02 ` [PATCH v6 00/11] Column display Junio C Hamano
2012-02-27  0:40   ` Nguyen Thai Ngoc Duy
2012-02-27  1:37     ` Junio C Hamano
2012-02-27  7:46       ` Junio C Hamano
2012-02-27  8:14         ` Nguyen Thai Ngoc Duy
2012-02-28 11:58 ` [PATCH v7 00/10] " Nguyễn Thái Ngọc Duy
2012-02-28 11:58   ` [PATCH v7 01/10] Add git-column for columnar display Nguyễn Thái Ngọc Duy
2012-02-28 18:10     ` Junio C Hamano
2012-03-02 12:36       ` Nguyen Thai Ngoc Duy
2012-02-28 11:58   ` [PATCH v7 02/10] Stop starting pager recursively Nguyễn Thái Ngọc Duy
2012-02-28 18:13     ` Junio C Hamano
2012-02-28 19:10       ` Junio C Hamano
2012-02-29  1:54         ` Nguyen Thai Ngoc Duy
2012-02-29  3:37           ` Junio C Hamano
2012-02-29  3:40             ` Nguyen Thai Ngoc Duy
2012-02-29  4:51               ` Junio C Hamano
2012-02-28 11:58   ` [PATCH v7 03/10] column: add columnar layout Nguyễn Thái Ngọc Duy
2012-02-28 18:22     ` Junio C Hamano
2012-02-28 11:58   ` [PATCH v7 04/10] column: add dense layout support Nguyễn Thái Ngọc Duy
2012-02-28 18:27     ` Junio C Hamano
2012-03-02 12:47       ` Nguyen Thai Ngoc Duy
2012-03-02 17:37         ` Junio C Hamano
2012-02-28 11:58   ` [PATCH v7 05/10] column: add column.ui for default column output settings Nguyễn Thái Ngọc Duy
2012-02-28 18:44     ` Junio C Hamano
2012-02-28 11:58   ` [PATCH v7 06/10] help: reuse print_columns() for help -a Nguyễn Thái Ngọc Duy
2012-02-28 11:58   ` [PATCH v7 07/10] branch: add --column Nguyễn Thái Ngọc Duy
2012-02-28 11:58   ` [PATCH v7 08/10] status: " Nguyễn Thái Ngọc Duy
2012-02-28 11:58   ` [PATCH v7 09/10] column: support piping stdout to external git-column process Nguyễn Thái Ngọc Duy
2012-02-28 11:58   ` [PATCH v7 10/10] tag: add --column Nguyễn Thái Ngọc Duy
2012-03-02 11:25   ` [PATCH v7 00/10] Column display Thomas Rast
2012-03-11  7:02     ` Nguyen Thai Ngoc Duy
2012-03-12  6:02       ` Junio C Hamano
2012-03-13 12:09   ` [PATCH v7 00/9] " Nguyễn Thái Ngọc Duy
2012-03-13 12:08     ` Nguyen Thai Ngoc Duy
2012-03-13 12:09     ` [PATCH v7 01/9] Add column layout skeleton and git-column Nguyễn Thái Ngọc Duy
2012-03-13 12:09       ` [PATCH v7 02/9] Stop starting pager recursively Nguyễn Thái Ngọc Duy
2012-03-13 12:09         ` [PATCH v7 03/9] column: add columnar layout Nguyễn Thái Ngọc Duy
2012-03-13 12:09           ` [PATCH v7 04/9] column: add dense layout support Nguyễn Thái Ngọc Duy
2012-03-13 12:09             ` [PATCH v7 05/9] help: reuse print_columns() for help -a Nguyễn Thái Ngọc Duy
2012-03-13 12:09               ` [PATCH v7 06/9] branch: add --column Nguyễn Thái Ngọc Duy
2012-03-13 12:09                 ` [PATCH v7 07/9] status: " Nguyễn Thái Ngọc Duy
2012-03-13 12:09                   ` [PATCH v7 08/9] column: support piping stdout to external git-column process Nguyễn Thái Ngọc Duy
2012-03-13 12:09                     ` [PATCH v7 09/9] tag: add --column Nguyễn Thái Ngọc Duy
2012-03-13 12:11                       ` [PATCH v7 10/9] ls-files: support --column Nguyễn Thái Ngọc Duy
2012-03-13 12:11                         ` [PATCH v7 11/9] column: support "denser" mode Nguyễn Thái Ngọc Duy
2012-03-13 12:11                           ` [PATCH v7 12/9] column: support grouping entries Nguyễn Thái Ngọc Duy
2012-03-13 22:24       ` [PATCH v7 01/9] Add column layout skeleton and git-column Junio C Hamano
2012-03-14 11:17         ` Nguyen Thai Ngoc Duy
2012-03-14 18:29           ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1330170078-29353-6-git-send-email-pclouds@gmail.com \
    --to=pclouds@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).