All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org, Jonathan Niedier <jrnieder@gmail.com>
Cc: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH 04/16] display_columns: add COL_DENSE to do unequal column layout
Date: Wed,  9 Feb 2011 19:24:32 +0700	[thread overview]
Message-ID: <1297254284-3729-5-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <1297254284-3729-1-git-send-email-pclouds@gmail.com>

shrink_columns() calculate column width just enough to contain
text and padding.

relayout() uses shrink_columns() to try adding more columns after
columns are shrunk. However it only try that once.

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

diff --git a/column.c b/column.c
index d6e2d70..e7facf4 100644
--- a/column.c
+++ b/column.c
@@ -54,6 +54,68 @@ static void layout(const struct string_list *list,
 	*rows = DIV_ROUND_UP(list->nr, *cols);
 }
 
+/*
+ * Tighten columns just wide enough to fit its data and padding
+ * Return number of chars saved after shrinking.
+ */
+static int shrink_columns(const struct string_list *list, int mode,
+			   int *width, int padding, int rows, int cols)
+{
+	int x, y, i, len, item_len, spare = 0;
+	const char *s;
+
+	for (x = 0; x < cols; x++) {
+		for (y = len = 0; y < rows; y++) {
+			i = XY2SCALAR(mode, x, y, cols, rows);
+			if (i >= list->nr)
+				break;
+			s = list->items[i].string;
+			item_len = item_length(list, mode, s);
+			if (len < item_len)
+				len = item_len;
+		}
+		len += padding;
+
+		assert(len <= width[x]);
+		spare += width[x] - len;
+		width[x] = len;
+	}
+	return spare;
+}
+
+/* Try to tighten the layout and see if more columns can be added.*/
+static void relayout(const struct string_list *list,
+		     int mode, int original_width, int padding, int spare,
+		     int *initial_width, int **width, int *rows, int *cols)
+{
+	int new_rows, new_cols, new_initial_width;
+	int i, *new_width, new_spare, total_width;
+
+	/*
+	 * Assume all columns have same width, we would need
+	 * initial_width*cols. But then after shrinking, we have
+	 * "spare" more chars. Assume a new total_width with
+	 * additional chars, then re-shrink to see if it fits
+	 * c->width.
+	 */
+	total_width = (*initial_width)*(*cols) + spare;
+	layout(list, mode, total_width, padding,
+	       &new_initial_width, &new_rows, &new_cols);
+	new_width = xmalloc(sizeof(*new_width) * new_cols);
+	for (i = 0; i < new_cols; i++)
+		new_width[i] = new_initial_width;
+	new_spare = shrink_columns(list, mode, new_width, padding, new_rows, new_cols);
+
+	/* Does it fit? */
+	if (total_width - new_spare < original_width) {
+		free(*width);
+		*width = new_width;
+		*initial_width = new_initial_width;
+		*rows = new_rows;
+		*cols = new_cols;
+	}
+}
+
 /* Display without layout, COL_MODE_PLAIN */
 static void display_plain(const struct string_list *list, const char *indent)
 {
@@ -103,6 +165,14 @@ static void display_table(const struct string_list *list,
 	for (i = 0; i < cols; i++)
 		width[i] = initial_width;
 
+	if (mode & COL_DENSE) {
+		int spare = shrink_columns(list, mode, width, padding, rows, cols);
+		/* is it worth relayout? */
+		if (spare >= initial_width/2)
+			relayout(list, mode, total_width, padding, spare,
+				 &initial_width, &width, &rows, &cols);
+	}
+
 	empty_cell = xmalloc(initial_width + 1);
 	memset(empty_cell, ' ', initial_width);
 	empty_cell[initial_width] = '\0';
diff --git a/column.h b/column.h
index 3ed5731..cef354d 100644
--- a/column.h
+++ b/column.h
@@ -6,6 +6,7 @@
 #define COL_MODE_COLUMN        1   /* Fill columns before rows */
 #define COL_MODE_ROW           2   /* Fill rows before columns */
 #define COL_ANSI         (1 << 4) /* Remove ANSI escapes from string length */
+#define COL_DENSE        (1 << 5) /* Shrink columns when possible, making space for more columns */
 
 extern int term_columns(void);
 extern void display_columns(const struct string_list *list, int mode, int width, int padding, const char *indent);
-- 
1.7.2.2

  parent reply	other threads:[~2011-02-09 12:26 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-02-09 12:24 [PATCH 00/16] column output (v2) and git-ls Nguyễn Thái Ngọc Duy
2011-02-09 12:24 ` [PATCH 01/16] Move term_columns() to pager.c and save terminal width before pager Nguyễn Thái Ngọc Duy
2011-02-09 12:24 ` [PATCH 02/16] Add display_columns() to display in column layout Nguyễn Thái Ngọc Duy
2011-02-09 12:24 ` [PATCH 03/16] display_columns: add COL_MODE_{COLUMN,ROW} mode Nguyễn Thái Ngọc Duy
2011-02-09 12:24 ` Nguyễn Thái Ngọc Duy [this message]
2011-02-09 12:24 ` [PATCH 05/16] Add test-column for testing column layout Nguyễn Thái Ngọc Duy
2011-02-09 12:24 ` [PATCH 06/16] Add core.column Nguyễn Thái Ngọc Duy
2011-02-09 12:24 ` [PATCH 07/16] parseopt: OPT_COLUMN to set struct column_layout.mode Nguyễn Thái Ngọc Duy
2011-02-09 12:24 ` [PATCH 08/16] help: reuse display_columns() for help -a Nguyễn Thái Ngọc Duy
2011-02-09 12:24 ` [PATCH 09/16] tag: add --column Nguyễn Thái Ngọc Duy
2011-02-09 12:24 ` [PATCH 10/16] branch: " Nguyễn Thái Ngọc Duy
2011-02-09 12:24 ` [PATCH 11/16] Add ls command Nguyễn Thái Ngọc Duy
2011-02-09 12:24 ` [PATCH 12/16] ls: add --column Nguyễn Thái Ngọc Duy
2011-02-09 12:24 ` [PATCH 13/16] ls: add --recursive and turn default to non-recursive mode Nguyễn Thái Ngọc Duy
2011-02-09 12:24 ` [PATCH 14/16] ls: immitate UNIX ls output style Nguyễn Thái Ngọc Duy
2011-02-09 12:24 ` [PATCH 15/16] ls: strip common directory prefix from output Nguyễn Thái Ngọc Duy
2011-02-09 12:24 ` [PATCH 16/16] ls: color output Nguyễn Thái Ngọc Duy

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=1297254284-3729-5-git-send-email-pclouds@gmail.com \
    --to=pclouds@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=jrnieder@gmail.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.