summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>2012-03-13 19:11:35 +0700
committerJunio C Hamano <gitster@pobox.com>2012-03-13 15:25:13 -0700
commitee8a84f773a289f777e4de1ad6d40f8f89987f2c (patch)
treed5bb2ba1cdeed37663e5ae3c936821d488a40d92
parent4169af651e01cd0b4e5448a040a22b0e86379fff (diff)
downloadgit-ee8a84f773a289f777e4de1ad6d40f8f89987f2c.tar.gz
column: support "denser" mode
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@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--column.c74
-rw-r--r--column.h1
2 files changed, 71 insertions, 4 deletions
diff --git a/column.c b/column.c
index 1e545a0b5c..80eefa0912 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 b6872fe34a..dbc5da2e51 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 */