[PATCH v7 11/9] column: support "denser" mode

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Sometimes a few long entries in the listing would stretch out columns,
wasting space. If these entries are cut out, the columns could become
smaller, hence more columns.

This new mode does that by looking for the longest entry, if cutting the
list before that entry results in much denser layout, then the entry
will be cut out and printed in a separate line. The remaining will put
in a new layout.

Multiple tables with different column width might be unpleasant to
look at, especially if the tables are really short. But on the other
hand it could be quite handy. For example,
"COLUMNS=80 ./git ls-files --column=dense -- '*.[ch]'" takes 415
lines, while "denser" only takes 223 because it break the layout at
contrib/credential/osxkeychain/git-credential-osxkeychain.c
and relayout again:

abspath.c                  builtin/rm.c
advice.c                   builtin/send-pack.c
<snip>
builtin/rev-parse.c        connected.h
builtin/revert.c           contrib/convert-objects/convert-objects.c

contrib/credential/osxkeychain/git-credential-osxkeychain.c

contrib/examples/builtin-fetch--tool.c refs.c                   xdiff/xutils.c
contrib/svn-fe/svn-fe.c                refs.h                   xdiff/xutils.h
convert.c                              remote-curl.c            zlib.c
convert.h                              remote.c
<snip>
reflog-walk.c                          xdiff/xprepare.h
reflog-walk.h                          xdiff/xtypes.h

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx>
---
 column.c |   74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 column.h |    1 +
 2 files changed, 71 insertions(+), 4 deletions(-)

diff --git a/column.c b/column.c
index 1e545a0..80eefa0 100644
--- a/column.c
+++ b/column.c
@@ -152,10 +152,55 @@ static int display_cell(struct column_data *data, int initial_width,
 	return 0;
 }
 
+/*
+ * Attempt to put the longest cell into a separate line, see if it
+ * improves the layout
+ */
+static int break_long_line(const struct column_data *old_data)
+{
+	struct column_data data;
+	struct string_list faked_list;
+	int initial_width, x, y, i, item = 0, row1, row2;
+	char *empty_cell;
+
+	memcpy(&data, old_data, sizeof(data));
+	for (i = 0; i < data.list->nr; i++)
+		if (data.len[i] > data.len[item])
+			item = i;
+	data.list = &faked_list;
+	data.width = NULL;
+	faked_list = *old_data->list;
+
+	faked_list.nr = item + 1;
+	layout(&data, &initial_width);
+	shrink_columns(&data);
+	row1 = data.rows;
+
+	faked_list.nr = item;
+	layout(&data, &initial_width);
+	shrink_columns(&data);
+	row2 = data.rows;
+
+	if (row1 - row2 < 3)
+		return -1;
+
+	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.width);
+	free(empty_cell);
+	return item;
+}
+
 /* Display COL_COLUMN or COL_ROW */
-static void display_table(const struct string_list *list,
-			  unsigned int colopts,
-			  const struct column_options *opts)
+static int display_table(const struct string_list *list,
+			 unsigned int colopts,
+			 const struct column_options *opts)
 {
 	struct column_data data;
 	int x, y, i, initial_width;
@@ -174,6 +219,19 @@ static void display_table(const struct string_list *list,
 
 	if (colopts & COL_DENSE)
 		shrink_columns(&data);
+	if (colopts & COL_DENSER) {
+		i = break_long_line(&data);
+		if (i != -1) {
+			printf("%s%s" "%s%s%s" "%s%s",
+			       indent, nl,
+			       indent, list->items[i].string, nl,
+			       indent, nl);
+			free(data.len);
+			free(data.width);
+			return i + 1;
+		}
+		shrink_columns(&data);
+	}
 
 	empty_cell = xmalloc(initial_width + 1);
 	memset(empty_cell, ' ', initial_width);
@@ -187,12 +245,15 @@ static void display_table(const struct string_list *list,
 	free(data.len);
 	free(data.width);
 	free(empty_cell);
+	return list->nr;
 }
 
 void print_columns(const struct string_list *list, unsigned int colopts,
 		   const struct column_options *opts)
 {
 	struct column_options nopts;
+	int processed;
+	struct string_list l = *list;
 
 	if (!list->nr)
 		return;
@@ -213,7 +274,11 @@ void print_columns(const struct string_list *list, unsigned int colopts,
 		break;
 	case COL_ROW:
 	case COL_COLUMN:
-		display_table(list, colopts, &nopts);
+		while (l.nr &&
+		       (processed = display_table(&l, colopts, &nopts)) < l.nr) {
+			l.items += processed;
+			l.nr -= processed;
+		}
 		break;
 	default:
 		die("BUG: invalid layout mode %d", COL_LAYOUT(colopts));
@@ -252,6 +317,7 @@ static int parse_option(const char *arg, int len, unsigned int *colopts,
 		{ "column", COL_COLUMN,   COL_LAYOUT_MASK },
 		{ "row",    COL_ROW,      COL_LAYOUT_MASK },
 		{ "dense",  COL_DENSE,    0 },
+		{ "denser", COL_DENSER,   0 },
 	};
 	int i;
 
diff --git a/column.h b/column.h
index b6872fe..dbc5da2 100644
--- a/column.h
+++ b/column.h
@@ -6,6 +6,7 @@
 #define COL_PARSEOPT      0x0040   /* --column is given from cmdline */
 #define COL_DENSE         0x0080   /* Shrink columns when possible,
 				      making space for more columns */
+#define COL_DENSER        0x0100
 
 #define COL_ENABLE(c) ((c) & COL_ENABLE_MASK)
 #define COL_DISABLED      0x0000   /* must be zero */
-- 
1.7.8.36.g69ee2

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]