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 03/16] display_columns: add COL_MODE_{COLUMN,ROW} mode
Date: Wed, 9 Feb 2011 19:24:31 +0700 [thread overview]
Message-ID: <1297254284-3729-4-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <1297254284-3729-1-git-send-email-pclouds@gmail.com>
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 in UTF-8. If strings contain ANSI escape strings,
COL_ANSI must be specified.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
column.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
column.h | 3 ++
2 files changed, 110 insertions(+), 0 deletions(-)
diff --git a/column.c b/column.c
index c7d9a84..d6e2d70 100644
--- a/column.c
+++ b/column.c
@@ -1,8 +1,58 @@
#include "cache.h"
#include "column.h"
+#include "parse-options.h"
#include "string-list.h"
+#include "utf8.h"
#define MODE(mode) ((mode) & COL_MODE)
+#define XY2SCALAR(mode,x,y,cols,rows) (MODE(mode) == COL_MODE_COLUMN ? (x) * (rows) + (y) : (y) * (cols) + (x))
+
+/* return length of 's' in letters, ANSI escapes stripped */
+static int item_length(const struct string_list *list, 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(const struct string_list *list,
+ int mode, int total_width, int padding,
+ int *width, int *rows, int *cols)
+{
+ int i;
+
+ *width = 0;
+ /* Find maximum column width */
+ for (i = 0; i < list->nr; i++) {
+ const char *s = list->items[i].string;
+ int len = item_length(list, mode, s);
+ if (*width < len)
+ *width = len;
+ }
+ *width += padding;
+
+ *cols = total_width / *width;
+ if (*cols == 0)
+ *cols = 1;
+
+ *rows = DIV_ROUND_UP(list->nr, *cols);
+}
/* Display without layout, COL_MODE_PLAIN */
static void display_plain(const struct string_list *list, const char *indent)
@@ -13,6 +63,58 @@ static void display_plain(const struct string_list *list, const char *indent)
printf("%s%s\n", indent, list->items[i].string);
}
+static int display_cell(const struct string_list *list, int mode,
+ int *width, int initial_width,
+ const char *indent, const char *empty_cell,
+ int x, int y, int cols, int rows)
+{
+ const char *s;
+ int i, len, newline;
+
+ i = XY2SCALAR(mode, x, y, cols, rows);
+ if (i >= list->nr)
+ return -1;
+ s = list->items[i].string;
+ len = item_length(list, mode, s);
+ if (width[x] < initial_width)
+ len += initial_width - width[x];
+ if (MODE(mode) == COL_MODE_COLUMN)
+ newline = i + rows >= list->nr;
+ else
+ newline = x == cols - 1 || i == list->nr - 1;
+
+ printf("%s%s%s",
+ x == 0 ? indent : "",
+ 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)
+{
+ int x, y, i, cols, rows, initial_width, *width;
+ char *empty_cell;
+
+ layout(list, mode, total_width, padding, &initial_width, &rows, &cols);
+ width = xmalloc(sizeof(*width) * cols);
+ for (i = 0; i < cols; i++)
+ width[i] = initial_width;
+
+ empty_cell = xmalloc(initial_width + 1);
+ memset(empty_cell, ' ', initial_width);
+ empty_cell[initial_width] = '\0';
+ for (y = 0; y < rows; y++) {
+ for (x = 0; x < cols; x++)
+ if (display_cell(list, mode, width,
+ initial_width, indent, empty_cell,
+ x, y, cols, rows))
+ break;
+ }
+}
+
void display_columns(const struct string_list *list, int mode, int width, int padding, const char *indent)
{
int real_mode = MODE(mode);
@@ -25,6 +127,11 @@ void display_columns(const struct string_list *list, int mode, int width, int pa
display_plain(list, indent);
break;
+ case COL_MODE_ROW:
+ case COL_MODE_COLUMN:
+ display_table(list, mode, width, padding, indent);
+ break;
+
default:
die("BUG: invalid mode %d", MODE(mode));
}
diff --git a/column.h b/column.h
index da0bf9a..3ed5731 100644
--- a/column.h
+++ b/column.h
@@ -3,6 +3,9 @@
#define COL_MODE 0x000F
#define COL_MODE_PLAIN 0 /* Single column */
+#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 */
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
next prev 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 ` Nguyễn Thái Ngọc Duy [this message]
2011-02-09 12:24 ` [PATCH 04/16] display_columns: add COL_DENSE to do unequal " Nguyễn Thái Ngọc Duy
2011-02-09 12:24 ` [PATCH 05/16] Add test-column for testing " 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-4-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 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).