* [PATCH 00/16] column output (v2) and git-ls
@ 2011-02-09 12:24 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
` (15 more replies)
0 siblings, 16 replies; 17+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-02-09 12:24 UTC (permalink / raw)
To: git, Jonathan Niedier; +Cc: Nguyễn Thái Ngọc Duy
I have fixed most of things Jonathan mentioned in the previous series,
but that's not the focus. I resend column output series because it's
required for git-ls patches, a more interesting command.
Column output patches:
Move term_columns() to pager.c and save terminal width before pager
Add display_columns() to display in column layout
display_columns: add COL_MODE_{COLUMN,ROW} mode
display_columns: add COL_DENSE to do unequal column layout
Add test-column for testing column layout
Add core.column
parseopt: OPT_COLUMN to set struct column_layout.mode
help: reuse display_columns() for help -a
tag: add --column
branch: add --column
Changes:
- struct column_layout is gone.
- core.column and --column takes a list of options separated by
space/comma, so you can customize your display.
Remaining problems:
- perhaps column.<cmd> config is better than core.column.
- ansi_length() might misunderstand utf-8/ansi escapes
- the heuristics to make dense layout
- --column can also take auto/never/always
- tests
git-ls patches:
Add ls command
ls: add --column
ls: add --recursive and turn default to non-recursive mode
ls: immitate UNIX ls output style
ls: strip common directory prefix from output
ls: color output
In short, git-ls is supposed to work as close as possible to UNIX ls,
while still takes advantages of git-ls-files.
I split this into many patches for easier discussion. The code itself
is still WIP-quality. The design may not be 100% right.
Oh and I'm not sure how to do the color part right. Reading $LS_COLORS
is scary and does not really fit Git.
.gitignore | 2 +
Documentation/config.txt | 11 ++
Documentation/git-branch.txt | 6 +
Documentation/git-tag.txt | 9 +-
Makefile | 3 +
builtin.h | 1 +
builtin/branch.c | 23 +++-
builtin/ls-files.c | 295 +++++++++++++++++++++++++++++++++++++++++-
builtin/tag.c | 21 +++-
cache.h | 1 +
column.c | 287 ++++++++++++++++++++++++++++++++++++++++
column.h | 18 +++
command-list.txt | 1 +
config.c | 4 +
environment.c | 1 +
git.c | 1 +
help.c | 52 +------
pager.c | 33 +++++
parse-options.h | 2 +
t/t9002-column.sh | 108 +++++++++++++++
test-column.c | 57 ++++++++
21 files changed, 879 insertions(+), 57 deletions(-)
create mode 100644 column.c
create mode 100644 column.h
create mode 100755 t/t9002-column.sh
create mode 100644 test-column.c
--
1.7.2.2
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 01/16] Move term_columns() to pager.c and save terminal width before pager
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 ` 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
` (14 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-02-09 12:24 UTC (permalink / raw)
To: git, Jonathan Niedier; +Cc: Nguyễn Thái Ngọc Duy
term_columns() checks for terminal width via ioctl(2). After
redirecting, stdin is no longer terminal to get terminal width.
Check terminal width and save it before redirect stdin in setup_pager()
and let term_columns() reuse the value.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
Makefile | 1 +
column.h | 6 ++++++
help.c | 23 +----------------------
| 33 +++++++++++++++++++++++++++++++++
4 files changed, 41 insertions(+), 22 deletions(-)
create mode 100644 column.h
diff --git a/Makefile b/Makefile
index 775ee83..ed9e94b 100644
--- a/Makefile
+++ b/Makefile
@@ -1956,6 +1956,7 @@ builtin/prune.o builtin/reflog.o reachable.o: reachable.h
builtin/commit.o builtin/revert.o wt-status.o: wt-status.h
builtin/tar-tree.o archive-tar.o: tar.h
connect.o transport.o http-backend.o: url.h
+pager.o help.o: column.h
http-fetch.o http-walker.o remote-curl.o transport.o walker.o: walker.h
http.o http-walker.o http-push.o http-fetch.o remote-curl.o: http.h url.h
diff --git a/column.h b/column.h
new file mode 100644
index 0000000..55d8067
--- /dev/null
+++ b/column.h
@@ -0,0 +1,6 @@
+#ifndef COLUMN_H
+#define COLUMN_H
+
+extern int term_columns(void);
+
+#endif
diff --git a/help.c b/help.c
index 7654f1b..768f64c 100644
--- a/help.c
+++ b/help.c
@@ -4,28 +4,7 @@
#include "levenshtein.h"
#include "help.h"
#include "common-cmds.h"
-
-/* most GUI terminals set COLUMNS (although some don't export it) */
-static int term_columns(void)
-{
- char *col_string = getenv("COLUMNS");
- int n_cols;
-
- if (col_string && (n_cols = atoi(col_string)) > 0)
- return n_cols;
-
-#ifdef TIOCGWINSZ
- {
- struct winsize ws;
- if (!ioctl(1, TIOCGWINSZ, &ws)) {
- if (ws.ws_col)
- return ws.ws_col;
- }
- }
-#endif
-
- return 80;
-}
+#include "column.h"
void add_cmdname(struct cmdnames *cmds, const char *name, int len)
{
--git a/pager.c b/pager.c
index dac358f..dad6329 100644
--- a/pager.c
+++ b/pager.c
@@ -12,6 +12,19 @@
*/
static int spawned_pager;
+static int max_columns;
+
+static int retrieve_terminal_width(void)
+{
+#ifdef TIOCGWINSZ
+ struct winsize ws;
+ if (ioctl(1, TIOCGWINSZ, &ws)) /* e.g., ENOSYS */
+ return 0;
+ return ws.ws_col;
+#else
+ return 0;
+#endif
+}
#ifndef WIN32
static void pager_preexec(void)
@@ -74,12 +87,17 @@ const char *git_pager(int stdout_is_tty)
void setup_pager(void)
{
const char *pager = git_pager(isatty(1));
+ int width;
if (!pager)
return;
spawned_pager = 1; /* means we are emitting to terminal */
+ width = retrieve_terminal_width();
+ if (width)
+ max_columns = width;
+
/* spawn the pager */
pager_argv[0] = pager;
pager_process.use_shell = 1;
@@ -116,3 +134,18 @@ int pager_in_use(void)
env = getenv("GIT_PAGER_IN_USE");
return env ? git_config_bool("GIT_PAGER_IN_USE", env) : 0;
}
+
+int term_columns()
+{
+ char *col_string = getenv("COLUMNS");
+ int n_cols;
+
+ if (col_string && (n_cols = atoi(col_string)) > 0)
+ return n_cols;
+
+ if (spawned_pager && max_columns)
+ return max_columns;
+
+ n_cols = retrieve_terminal_width();
+ return n_cols ? n_cols : 80;
+}
--
1.7.2.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 02/16] Add display_columns() to display in column layout
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 ` 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
` (13 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-02-09 12:24 UTC (permalink / raw)
To: git, Jonathan Niedier; +Cc: Nguyễn Thái Ngọc Duy
Currently it does not do that, just provide the API.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
Makefile | 3 ++-
column.c | 31 +++++++++++++++++++++++++++++++
column.h | 4 ++++
3 files changed, 37 insertions(+), 1 deletions(-)
create mode 100644 column.c
diff --git a/Makefile b/Makefile
index ed9e94b..88e20de 100644
--- a/Makefile
+++ b/Makefile
@@ -575,6 +575,7 @@ LIB_OBJS += branch.o
LIB_OBJS += bundle.o
LIB_OBJS += cache-tree.o
LIB_OBJS += color.o
+LIB_OBJS += column.o
LIB_OBJS += combine-diff.o
LIB_OBJS += commit.o
LIB_OBJS += config.o
@@ -1956,7 +1957,7 @@ builtin/prune.o builtin/reflog.o reachable.o: reachable.h
builtin/commit.o builtin/revert.o wt-status.o: wt-status.h
builtin/tar-tree.o archive-tar.o: tar.h
connect.o transport.o http-backend.o: url.h
-pager.o help.o: column.h
+column.o pager.o help.o: column.h
http-fetch.o http-walker.o remote-curl.o transport.o walker.o: walker.h
http.o http-walker.o http-push.o http-fetch.o remote-curl.o: http.h url.h
diff --git a/column.c b/column.c
new file mode 100644
index 0000000..c7d9a84
--- /dev/null
+++ b/column.c
@@ -0,0 +1,31 @@
+#include "cache.h"
+#include "column.h"
+#include "string-list.h"
+
+#define MODE(mode) ((mode) & COL_MODE)
+
+/* Display without layout, COL_MODE_PLAIN */
+static void display_plain(const struct string_list *list, const char *indent)
+{
+ int i;
+
+ for (i = 0; i < list->nr; i++)
+ printf("%s%s\n", indent, list->items[i].string);
+}
+
+void display_columns(const struct string_list *list, int mode, int width, int padding, const char *indent)
+{
+ int real_mode = MODE(mode);
+ if (!indent)
+ indent = "";
+ if (width <= 1)
+ real_mode = COL_MODE_PLAIN;
+ switch (real_mode) {
+ case COL_MODE_PLAIN:
+ display_plain(list, indent);
+ break;
+
+ default:
+ die("BUG: invalid mode %d", MODE(mode));
+ }
+}
diff --git a/column.h b/column.h
index 55d8067..da0bf9a 100644
--- a/column.h
+++ b/column.h
@@ -1,6 +1,10 @@
#ifndef COLUMN_H
#define COLUMN_H
+#define COL_MODE 0x000F
+#define COL_MODE_PLAIN 0 /* Single column */
+
extern int term_columns(void);
+extern void display_columns(const struct string_list *list, int mode, int width, int padding, const char *indent);
#endif
--
1.7.2.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 03/16] display_columns: add COL_MODE_{COLUMN,ROW} mode
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
2011-02-09 12:24 ` [PATCH 04/16] display_columns: add COL_DENSE to do unequal column layout Nguyễn Thái Ngọc Duy
` (12 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-02-09 12:24 UTC (permalink / raw)
To: git, Jonathan Niedier; +Cc: Nguyễn Thái Ngọc Duy
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
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 04/16] display_columns: add COL_DENSE to do unequal column layout
2011-02-09 12:24 [PATCH 00/16] column output (v2) and git-ls Nguyễn Thái Ngọc Duy
` (2 preceding siblings ...)
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
2011-02-09 12:24 ` [PATCH 05/16] Add test-column for testing " Nguyễn Thái Ngọc Duy
` (11 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-02-09 12:24 UTC (permalink / raw)
To: git, Jonathan Niedier; +Cc: Nguyễn Thái Ngọc Duy
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
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 05/16] Add test-column for testing column layout
2011-02-09 12:24 [PATCH 00/16] column output (v2) and git-ls Nguyễn Thái Ngọc Duy
` (3 preceding siblings ...)
2011-02-09 12:24 ` [PATCH 04/16] display_columns: add COL_DENSE to do unequal column layout Nguyễn Thái Ngọc Duy
@ 2011-02-09 12:24 ` 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
` (10 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-02-09 12:24 UTC (permalink / raw)
To: git, Jonathan Niedier; +Cc: Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
.gitignore | 1 +
Makefile | 1 +
t/t9002-column.sh | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++
test-column.c | 57 ++++++++++++++++++++++++++++
4 files changed, 167 insertions(+), 0 deletions(-)
create mode 100755 t/t9002-column.sh
create mode 100644 test-column.c
diff --git a/.gitignore b/.gitignore
index 3dd6ef7..a1a1202 100644
--- a/.gitignore
+++ b/.gitignore
@@ -162,6 +162,7 @@
/gitweb/gitweb.cgi
/gitweb/static/gitweb.min.*
/test-chmtime
+/test-column
/test-ctype
/test-date
/test-delta
diff --git a/Makefile b/Makefile
index 88e20de..a687e73 100644
--- a/Makefile
+++ b/Makefile
@@ -417,6 +417,7 @@ PROGRAM_OBJS += http-backend.o
PROGRAMS += $(patsubst %.o,git-%$X,$(PROGRAM_OBJS))
TEST_PROGRAMS_NEED_X += test-chmtime
+TEST_PROGRAMS_NEED_X += test-column
TEST_PROGRAMS_NEED_X += test-ctype
TEST_PROGRAMS_NEED_X += test-date
TEST_PROGRAMS_NEED_X += test-delta
diff --git a/t/t9002-column.sh b/t/t9002-column.sh
new file mode 100755
index 0000000..1d030b0
--- /dev/null
+++ b/t/t9002-column.sh
@@ -0,0 +1,108 @@
+#!/bin/sh
+
+test_description='git column'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ cat >lista <<\EOF
+one
+two
+three
+four
+five
+six
+seven
+eight
+nine
+ten
+eleven
+EOF
+'
+
+test_expect_success '80 columns' '
+ cat >expected <<\EOF &&
+one two three four five six seven eight nine ten eleven
+EOF
+ COLUMNS=80 test-column < lista > actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'COLUMNS = 1' '
+ cat >expected <<\EOF &&
+one
+two
+three
+four
+five
+six
+seven
+eight
+nine
+ten
+eleven
+EOF
+ COLUMNS=1 test-column < lista > actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'width = 1' '
+ test-column --width=1 < lista > actual &&
+ test_cmp expected actual
+'
+
+COLUMNS=20
+export COLUMNS
+
+test_expect_success '20 columns' '
+ cat >expected <<\EOF &&
+one seven
+two eight
+three nine
+four ten
+five eleven
+six
+EOF
+ test-column < lista > actual &&
+ test_cmp expected actual
+'
+
+test_expect_success '20 columns, densed' '
+ cat >expected <<\EOF &&
+one seven
+two eight
+three nine
+four ten
+five eleven
+six
+EOF
+ test-column --mode=column,dense < lista > actual &&
+ test_cmp expected actual
+'
+
+test_expect_success '20 columns, padding 2' '
+ cat >expected <<\EOF &&
+one seven
+two eight
+three nine
+four ten
+five eleven
+six
+EOF
+ test-column --padding 2 < lista > actual &&
+ test_cmp expected actual
+'
+
+test_expect_success '20 columns, left indented' '
+ cat >expected <<\EOF &&
+ one seven
+ two eight
+ three nine
+ four ten
+ five eleven
+ six
+EOF
+ test-column --left=2 < lista > actual &&
+ test_cmp expected actual
+'
+
+test_done
diff --git a/test-column.c b/test-column.c
new file mode 100644
index 0000000..b9a5d4b
--- /dev/null
+++ b/test-column.c
@@ -0,0 +1,57 @@
+#include "cache.h"
+#include "strbuf.h"
+#include "parse-options.h"
+#include "string-list.h"
+#include "column.h"
+
+static const char * const builtin_column_usage[] = {
+ "git column [--mode=<mode>] [--width=<width>] [--left-space=<N>] [--right-space=<N>]",
+ NULL
+};
+
+int main(int argc, const char **argv)
+{
+ struct string_list list = STRING_LIST_INIT_DUP;
+ const char *modestr = NULL;
+ int mode = 0;
+ struct strbuf sb = STRBUF_INIT;
+ int left_space = 0, right_space = 0, padding = 1;
+ int term_width = term_columns();
+ struct option options[] = {
+ OPT_INTEGER(0, "width", &term_width, "Maximum width"),
+ OPT_INTEGER(0, "left", &left_space, "Padding space on left border"),
+ OPT_INTEGER(0, "right", &right_space, "Padding space on right border"),
+ OPT_INTEGER(0, "padding", &padding, "Padding space between columns"),
+ OPT_STRING(0, "mode", &modestr, "mode", "Which layout mode to use"),
+ OPT_END()
+ };
+
+ argc = parse_options(argc, argv, "", options, builtin_column_usage, 0);
+
+ while (modestr && *modestr) {
+ int len = strcspn(modestr, ",");
+ if (len == 6 && !strncmp(modestr, "column", len))
+ mode |= COL_MODE_COLUMN;
+ else if (len == 5 && !strncmp(modestr, "dense", len))
+ mode |= COL_DENSE;
+ else if (len == 4 && !strncmp(modestr, "ansi", len))
+ mode |= COL_ANSI;
+ else
+ die("Unknown modestr %s", modestr);
+ modestr += len;
+ while (*modestr == ',')
+ modestr++;
+ }
+ if (!mode)
+ mode = COL_MODE_COLUMN;
+ if ((mode & COL_MODE) == 0)
+ die("Invalid mode '%s'", modestr);
+
+ while (!strbuf_getline(&sb, stdin, '\n'))
+ string_list_append(&list, sb.buf);
+
+ strbuf_setlen(&sb, left_space);
+ memset(sb.buf, ' ', left_space);
+ display_columns(&list, mode, term_width - right_space - left_space, padding, sb.buf);
+ return 0;
+}
--
1.7.2.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 06/16] Add core.column
2011-02-09 12:24 [PATCH 00/16] column output (v2) and git-ls Nguyễn Thái Ngọc Duy
` (4 preceding siblings ...)
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 ` 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
` (9 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-02-09 12:24 UTC (permalink / raw)
To: git, Jonathan Niedier; +Cc: Nguyễn Thái Ngọc Duy
FIXME: should probably go as color.* (i.e. column.*)
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
Documentation/config.txt | 11 ++++++++
cache.h | 1 +
column.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++
column.h | 1 +
config.c | 4 +++
environment.c | 1 +
6 files changed, 82 insertions(+), 0 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index c5e1835..45b5f5b 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -567,6 +567,17 @@ core.sparseCheckout::
Enable "sparse checkout" feature. See section "Sparse checkout" in
linkgit:git-read-tree[1] for more information.
+core.column::
+ Specify whether a command should output in columns. Only commands
+ that support `--column` will be affected by this. This variable
+ consists of a list of tokens separated by either spaces or commas:
+ `never` (do not output in columns), `auto` (output in columns if
+ the output is to a terminal), `always` (always output in
+ columns), `column` (fill column before row), `row` (fill row
+ before column), `dense` (unequal column width).
+ Setting `--column` or `--no-column` will override this
+ variable. This option defaults to never.
+
add.ignore-errors::
add.ignoreErrors::
Tells 'git add' to continue adding files when some files cannot be
diff --git a/cache.h b/cache.h
index d83d68c..b370657 100644
--- a/cache.h
+++ b/cache.h
@@ -559,6 +559,7 @@ extern int read_replace_refs;
extern int fsync_object_files;
extern int core_preload_index;
extern int core_apply_sparse_checkout;
+extern int core_column;
enum safe_crlf {
SAFE_CRLF_FALSE = 0,
diff --git a/column.c b/column.c
index e7facf4..615a698 100644
--- a/column.c
+++ b/column.c
@@ -206,3 +206,67 @@ void display_columns(const struct string_list *list, int mode, int width, int pa
die("BUG: invalid mode %d", MODE(mode));
}
}
+
+static int parse_column_option(const char *arg, int len, int *mode)
+{
+ int negate = !strncmp(arg, "no", 2);
+
+ if (negate)
+ arg += 2;
+
+ if (!negate && !strncmp(arg, "column", 6)) {
+ *mode &= ~COL_MODE;
+ *mode |= COL_MODE_COLUMN;
+ return 0;
+ }
+ else if (!negate && !strncmp(arg, "row", 3)) {
+ *mode &= ~COL_MODE;
+ *mode |= COL_MODE_ROW;
+ return 0;
+ }
+ else if (!strncmp(arg, "dense", 5)) {
+ if (negate)
+ *mode &= ~COL_DENSE;
+ else
+ *mode |= COL_DENSE;
+ return 0;
+ }
+ else
+ return error("unsupported style '%s'", arg);
+ return 0;
+}
+
+int git_config_column(const char *var, const char *value, int stdout_is_tty)
+{
+ const char *sep = " ,";
+ int enable = 0;
+
+ while (*value) {
+ int len = strcspn(value, sep);
+ if (len) {
+ if (!strncasecmp(value, "never", 5))
+ enable = 0;
+ else if (!strncasecmp(value, "always", 6))
+ enable = 1;
+ else if (!strncasecmp(value, "auto", 4)) {
+ if (stdout_is_tty < 0)
+ stdout_is_tty = isatty(1);
+ if (stdout_is_tty || (pager_in_use() && pager_use_color))
+ enable = 1;
+ }
+ else if (!parse_column_option(value, len, &core_column))
+ ;
+ else
+ return -1;
+
+ value += len;
+ }
+ value += strspn(value, sep);
+ }
+ if (!enable)
+ core_column = 0;
+ else if (MODE(core_column) == COL_MODE_PLAIN)
+ core_column |= COL_MODE_COLUMN;
+
+ return 0;
+}
diff --git a/column.h b/column.h
index cef354d..0749793 100644
--- a/column.h
+++ b/column.h
@@ -10,5 +10,6 @@
extern int term_columns(void);
extern void display_columns(const struct string_list *list, int mode, int width, int padding, const char *indent);
+extern int git_config_column(const char *var, const char *value, int stdout_is_tty);
#endif
diff --git a/config.c b/config.c
index 625e051..68a432a 100644
--- a/config.c
+++ b/config.c
@@ -9,6 +9,7 @@
#include "exec_cmd.h"
#include "strbuf.h"
#include "quote.h"
+#include "column.h"
#define MAXNAME (256)
@@ -660,6 +661,9 @@ static int git_default_core_config(const char *var, const char *value)
return 0;
}
+ if (!strcmp(var, "core.column"))
+ return git_config_column(var, value, -1);
+
/* Add other config variables here and to Documentation/config.txt. */
return 0;
}
diff --git a/environment.c b/environment.c
index 9564475..b420ea2 100644
--- a/environment.c
+++ b/environment.c
@@ -56,6 +56,7 @@ char *notes_ref_name;
int grafts_replace_parents = 1;
int core_apply_sparse_checkout;
struct startup_info *startup_info;
+int core_column;
/* Parallel index stat data preload? */
int core_preload_index = 0;
--
1.7.2.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 07/16] parseopt: OPT_COLUMN to set struct column_layout.mode
2011-02-09 12:24 [PATCH 00/16] column output (v2) and git-ls Nguyễn Thái Ngọc Duy
` (5 preceding siblings ...)
2011-02-09 12:24 ` [PATCH 06/16] Add core.column Nguyễn Thái Ngọc Duy
@ 2011-02-09 12:24 ` 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
` (8 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-02-09 12:24 UTC (permalink / raw)
To: git, Jonathan Niedier; +Cc: Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
column.c | 15 +++++++++++++++
column.h | 3 +++
parse-options.h | 2 ++
3 files changed, 20 insertions(+), 0 deletions(-)
diff --git a/column.c b/column.c
index 615a698..c08a885 100644
--- a/column.c
+++ b/column.c
@@ -270,3 +270,18 @@ int git_config_column(const char *var, const char *value, int stdout_is_tty)
return 0;
}
+
+int parseopt_column_callback(const struct option *opt, const char *arg, int unset)
+{
+ int *mode = opt->value;
+ if (unset) {
+ *mode = COL_MODE_PLAIN;
+ return 0;
+ }
+ if (!arg) {
+ if (!MODE(*mode))
+ *mode |= COL_MODE_COLUMN;
+ return 0;
+ }
+ return parse_column_option(arg, strlen(arg), mode);
+}
diff --git a/column.h b/column.h
index 0749793..99ec848 100644
--- a/column.h
+++ b/column.h
@@ -12,4 +12,7 @@ extern int term_columns(void);
extern void display_columns(const struct string_list *list, int mode, int width, int padding, const char *indent);
extern int git_config_column(const char *var, const char *value, int stdout_is_tty);
+struct option;
+extern int parseopt_column_callback(const struct option *opt, const char *arg, int unset);
+
#endif
diff --git a/parse-options.h b/parse-options.h
index 31ec5d2..2fed453 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -145,6 +145,8 @@ struct option {
#define OPT_COLOR_FLAG(s, l, v, h) \
{ OPTION_CALLBACK, (s), (l), (v), "when", (h), PARSE_OPT_OPTARG, \
parse_opt_color_flag_cb, (intptr_t)"always" }
+#define OPT_COLUMN(s, l, v, h) \
+ { OPTION_CALLBACK, (s), (l), (v), "style", (h), PARSE_OPT_OPTARG, parseopt_column_callback }
/* parse_options() will filter out the processed options and leave the
--
1.7.2.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 08/16] help: reuse display_columns() for help -a
2011-02-09 12:24 [PATCH 00/16] column output (v2) and git-ls Nguyễn Thái Ngọc Duy
` (6 preceding siblings ...)
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 ` 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
` (7 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-02-09 12:24 UTC (permalink / raw)
To: git, Jonathan Niedier; +Cc: Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
help.c | 29 +++++++----------------------
1 files changed, 7 insertions(+), 22 deletions(-)
diff --git a/help.c b/help.c
index 768f64c..81942f9 100644
--- a/help.c
+++ b/help.c
@@ -4,6 +4,7 @@
#include "levenshtein.h"
#include "help.h"
#include "common-cmds.h"
+#include "string-list.h"
#include "column.h"
void add_cmdname(struct cmdnames *cmds, const char *name, int len)
@@ -73,29 +74,13 @@ void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes)
static void pretty_print_string_list(struct cmdnames *cmds, int longest)
{
- int cols = 1, rows;
- int space = longest + 1; /* min 1 SP between words */
- int max_cols = term_columns() - 1; /* don't print *on* the edge */
- int i, j;
-
- if (space < max_cols)
- cols = max_cols / space;
- rows = DIV_ROUND_UP(cmds->cnt, cols);
-
- for (i = 0; i < rows; i++) {
- printf(" ");
+ struct string_list list = STRING_LIST_INIT_NODUP;
+ int i;
- for (j = 0; j < cols; j++) {
- int n = j * rows + i;
- int size = space;
- if (n >= cmds->cnt)
- break;
- if (j == cols-1 || n + rows >= cmds->cnt)
- size = 1;
- printf("%-*s", size, cmds->names[n]->name);
- }
- putchar('\n');
- }
+ for (i = 0; i < cmds->cnt; i++)
+ string_list_append(&list, cmds->names[i]->name);
+ display_columns(&list, COL_MODE_COLUMN, term_columns(), 1, " ");
+ string_list_clear(&list, 0);
}
static int is_executable(const char *name)
--
1.7.2.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 09/16] tag: add --column
2011-02-09 12:24 [PATCH 00/16] column output (v2) and git-ls Nguyễn Thái Ngọc Duy
` (7 preceding siblings ...)
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 ` Nguyễn Thái Ngọc Duy
2011-02-09 12:24 ` [PATCH 10/16] branch: " Nguyễn Thái Ngọc Duy
` (6 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-02-09 12:24 UTC (permalink / raw)
To: git, Jonathan Niedier; +Cc: Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
Documentation/git-tag.txt | 9 ++++++++-
Makefile | 2 +-
builtin/tag.c | 21 +++++++++++++++++----
3 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
index 8b169e3..89c55fb 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -12,7 +12,8 @@ SYNOPSIS
'git tag' [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>]
<tagname> [<commit> | <object>]
'git tag' -d <tagname>...
-'git tag' [-n[<num>]] -l [--contains <commit>] [<pattern>]
+'git tag' [-n[<num>]] -l [--column[=<options>] | --no-column]
+ [--contains <commit>] [<pattern>]
'git tag' -v <tagname>...
DESCRIPTION
@@ -71,6 +72,12 @@ OPTIONS
List tags with names that match the given pattern (or all if no pattern is given).
Typing "git tag" without arguments, also lists all tags.
+--column::
+--no-column::
+ Whether show tags in columns. This option is only applicable if `git
+ tag` is used to list tags without annotation lines. See core.column
+ for options.
+
--contains <commit>::
Only list tags which contain the specified commit.
diff --git a/Makefile b/Makefile
index a687e73..c9fd9aa 100644
--- a/Makefile
+++ b/Makefile
@@ -1958,7 +1958,7 @@ builtin/prune.o builtin/reflog.o reachable.o: reachable.h
builtin/commit.o builtin/revert.o wt-status.o: wt-status.h
builtin/tar-tree.o archive-tar.o: tar.h
connect.o transport.o http-backend.o: url.h
-column.o pager.o help.o: column.h
+column.o pager.o help.o tag.o: column.h
http-fetch.o http-walker.o remote-curl.o transport.o walker.o: walker.h
http.o http-walker.o http-push.o http-fetch.o remote-curl.o: http.h url.h
diff --git a/builtin/tag.c b/builtin/tag.c
index aa1f87d..2b6cae9 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -12,6 +12,8 @@
#include "tag.h"
#include "run-command.h"
#include "parse-options.h"
+#include "string-list.h"
+#include "column.h"
static const char * const git_tag_usage[] = {
"git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]",
@@ -22,6 +24,7 @@ static const char * const git_tag_usage[] = {
};
static char signingkey[1000];
+static struct string_list output;
struct tag_filter {
const char *pattern;
@@ -52,7 +55,7 @@ static int show_reference(const char *refname, const unsigned char *sha1,
}
if (!filter->lines) {
- printf("%s\n", refname);
+ string_list_append(&output, refname);
return 0;
}
printf("%-15s ", refname);
@@ -361,7 +364,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
struct ref_lock *lock;
int annotate = 0, sign = 0, force = 0, lines = -1,
- list = 0, delete = 0, verify = 0;
+ list = 0, delete = 0, verify = 0, column_mode;
const char *msgfile = NULL, *keyid = NULL;
struct msg_arg msg = { 0, STRBUF_INIT };
struct commit_list *with_commit = NULL;
@@ -383,6 +386,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
OPT_STRING('u', NULL, &keyid, "key-id",
"use another key to sign the tag"),
OPT__FORCE(&force, "replace the tag if exists"),
+ OPT_COLUMN(0, "column", &column_mode, "show tag list in columns" ),
OPT_GROUP("Tag listing options"),
{
@@ -395,6 +399,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
};
git_config(git_tag_config, NULL);
+ column_mode = core_column;
+ output.strdup_strings = 1;
argc = parse_options(argc, argv, prefix, options, git_tag_usage, 0);
@@ -413,9 +419,16 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
if (list + delete + verify > 1)
usage_with_options(git_tag_usage, options);
- if (list)
- return list_tags(argv[0], lines == -1 ? 0 : lines,
+ if (list) {
+ int ret;
+
+ if (lines != -1)
+ column_mode = COL_MODE_PLAIN;
+ ret = list_tags(argv[0], lines == -1 ? 0 : lines,
with_commit);
+ display_columns(&output, column_mode, term_columns(), 2, "");
+ return ret;
+ }
if (lines != -1)
die("-n option is only allowed with -l.");
if (with_commit)
--
1.7.2.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 10/16] branch: add --column
2011-02-09 12:24 [PATCH 00/16] column output (v2) and git-ls Nguyễn Thái Ngọc Duy
` (8 preceding siblings ...)
2011-02-09 12:24 ` [PATCH 09/16] tag: add --column Nguyễn Thái Ngọc Duy
@ 2011-02-09 12:24 ` 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
` (5 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-02-09 12:24 UTC (permalink / raw)
To: git, Jonathan Niedier; +Cc: Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
Documentation/git-branch.txt | 6 ++++++
Makefile | 2 +-
builtin/branch.c | 23 +++++++++++++++++++----
3 files changed, 26 insertions(+), 5 deletions(-)
diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index 9106d38..8a05784 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -9,6 +9,7 @@ SYNOPSIS
--------
[verse]
'git branch' [--color[=<when>] | --no-color] [-r | -a]
+ [--column[=<options>] | --no-column]
[-v [--abbrev=<length> | --no-abbrev]]
[(--merged | --no-merged | --contains) [<commit>]]
'git branch' [--set-upstream | --track | --no-track] [-l] [-f] <branchname> [<start-point>]
@@ -99,6 +100,11 @@ OPTIONS
default to color output.
Same as `--color=never`.
+--column::
+--no-column::
+ Whether whow branches in columns. See core.column for options.
+ This option is ignored in verbose mode.
+
-r::
List or delete (if used with -d) the remote-tracking branches.
diff --git a/Makefile b/Makefile
index c9fd9aa..0e459e4 100644
--- a/Makefile
+++ b/Makefile
@@ -1958,7 +1958,7 @@ builtin/prune.o builtin/reflog.o reachable.o: reachable.h
builtin/commit.o builtin/revert.o wt-status.o: wt-status.h
builtin/tar-tree.o archive-tar.o: tar.h
connect.o transport.o http-backend.o: url.h
-column.o pager.o help.o tag.o: column.h
+branch.o column.o pager.o help.o tag.o: column.h
http-fetch.o http-walker.o remote-curl.o transport.o walker.o: walker.h
http.o http-walker.o http-push.o http-fetch.o remote-curl.o: http.h url.h
diff --git a/builtin/branch.c b/builtin/branch.c
index 9e546e4..d3eaa00 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -15,6 +15,8 @@
#include "branch.h"
#include "diff.h"
#include "revision.h"
+#include "string-list.h"
+#include "column.h"
static const char * const builtin_branch_usage[] = {
"git branch [options] [-r | -a] [--merged | --no-merged]",
@@ -53,6 +55,8 @@ static enum merge_filter {
} merge_filter;
static unsigned char merge_filter_ref[20];
+static struct string_list output;
+
static int parse_branch_color_slot(const char *var, int ofs)
{
if (!strcasecmp(var+ofs, "plain"))
@@ -451,7 +455,7 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
strbuf_release(&stat);
strbuf_release(&subject);
}
- printf("%s\n", out.buf);
+ string_list_append(&output, out.buf);
strbuf_release(&name);
strbuf_release(&out);
}
@@ -609,7 +613,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
{
int delete = 0, rename = 0, force_create = 0;
int verbose = 0, abbrev = DEFAULT_ABBREV, detached = 0;
- int reflog = 0;
+ int reflog = 0, column_mode;
enum branch_track track;
int kinds = REF_LOCAL_BRANCH;
struct commit_list *with_commit = NULL;
@@ -660,6 +664,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG,
opt_parse_merge_filter, (intptr_t) "HEAD",
},
+ OPT_COLUMN(0, "column", &column_mode, "list branches in columns" ),
OPT_END(),
};
@@ -686,6 +691,9 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
}
hashcpy(merge_filter_ref, head_sha1);
+ column_mode = core_column | COL_ANSI;
+ output.strdup_strings = 1;
+
argc = parse_options(argc, argv, prefix, options, builtin_branch_usage,
0);
if (!!delete + !!rename + !!force_create > 1)
@@ -693,8 +701,15 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
if (delete)
return delete_branches(argc, argv, delete > 1, kinds);
- else if (argc == 0)
- return print_ref_list(kinds, detached, verbose, abbrev, with_commit);
+ else if (argc == 0) {
+ int ret;
+ if (verbose)
+ column_mode = COL_MODE_PLAIN;
+
+ ret = print_ref_list(kinds, detached, verbose, abbrev, with_commit);
+ display_columns(&output, column_mode, term_columns(), 1, "");
+ return ret;
+ }
else if (rename && (argc == 1))
rename_branch(head, argv[0], rename > 1);
else if (rename && (argc == 2))
--
1.7.2.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 11/16] Add ls command
2011-02-09 12:24 [PATCH 00/16] column output (v2) and git-ls Nguyễn Thái Ngọc Duy
` (9 preceding siblings ...)
2011-02-09 12:24 ` [PATCH 10/16] branch: " Nguyễn Thái Ngọc Duy
@ 2011-02-09 12:24 ` 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
` (4 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-02-09 12:24 UTC (permalink / raw)
To: git, Jonathan Niedier; +Cc: Nguyễn Thái Ngọc Duy
The command is supposed to be git variant of UNIX ls. Currently
it's just a stripped down version of ls-files with some porcelain touch:
- auto refreshing index
- setup standard excludes
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
.gitignore | 1 +
Makefile | 2 +-
builtin.h | 1 +
builtin/ls-files.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
command-list.txt | 1 +
git.c | 1 +
6 files changed, 57 insertions(+), 1 deletions(-)
diff --git a/.gitignore b/.gitignore
index a1a1202..c090d21 100644
--- a/.gitignore
+++ b/.gitignore
@@ -66,6 +66,7 @@
/git-instaweb
/git-log
/git-lost-found
+/git-ls
/git-ls-files
/git-ls-remote
/git-ls-tree
diff --git a/Makefile b/Makefile
index 0e459e4..5efbb1c 100644
--- a/Makefile
+++ b/Makefile
@@ -1958,7 +1958,7 @@ builtin/prune.o builtin/reflog.o reachable.o: reachable.h
builtin/commit.o builtin/revert.o wt-status.o: wt-status.h
builtin/tar-tree.o archive-tar.o: tar.h
connect.o transport.o http-backend.o: url.h
-branch.o column.o pager.o help.o tag.o: column.h
+branch.o builtin/ls-files.o column.o pager.o help.o tag.o: column.h
http-fetch.o http-walker.o remote-curl.o transport.o walker.o: walker.h
http.o http-walker.o http-push.o http-fetch.o remote-curl.o: http.h url.h
diff --git a/builtin.h b/builtin.h
index 904e067..5aede6e 100644
--- a/builtin.h
+++ b/builtin.h
@@ -80,6 +80,7 @@ extern int cmd_index_pack(int argc, const char **argv, const char *prefix);
extern int cmd_init_db(int argc, const char **argv, const char *prefix);
extern int cmd_log(int argc, const char **argv, const char *prefix);
extern int cmd_log_reflog(int argc, const char **argv, const char *prefix);
+extern int cmd_ls(int argc, const char **argv, const char *prefix);
extern int cmd_ls_files(int argc, const char **argv, const char *prefix);
extern int cmd_ls_tree(int argc, const char **argv, const char *prefix);
extern int cmd_ls_remote(int argc, const char **argv, const char *prefix);
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index fb2d5f4..cab7a10 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -619,3 +619,55 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
return 0;
}
+
+int cmd_ls(int argc, const char **argv, const char *cmd_prefix)
+{
+ struct dir_struct dir;
+ struct option builtin_ls_files_options[] = {
+ OPT_BOOLEAN('c', "cached", &show_cached,
+ "show cached files in the output (default)"),
+ OPT_BOOLEAN('d', "deleted", &show_deleted,
+ "show deleted files in the output"),
+ OPT_BOOLEAN('m', "modified", &show_modified,
+ "show modified files in the output"),
+ OPT_BOOLEAN('o', "others", &show_others,
+ "show other files in the output"),
+ OPT_BIT('i', "ignored", &dir.flags,
+ "show ignored files in the output",
+ DIR_SHOW_IGNORED),
+ OPT_BOOLEAN('k', "killed", &show_killed,
+ "show files on the filesystem that need to be removed"),
+ OPT_END()
+ };
+
+ if (argc == 2 && !strcmp(argv[1], "-h"))
+ usage_with_options(ls_files_usage, builtin_ls_files_options);
+
+ memset(&dir, 0, sizeof(dir));
+ prefix = cmd_prefix;
+ if (prefix)
+ prefix_len = strlen(prefix);
+ git_config(git_default_config, NULL);
+
+ if (read_cache() < 0)
+ die("index file corrupt");
+
+ argc = parse_options(argc, argv, prefix, builtin_ls_files_options,
+ ls_files_usage, 0);
+
+ if (dir.flags & DIR_SHOW_IGNORED || show_others)
+ setup_standard_excludes(&dir);
+
+ pathspec = get_pathspec(prefix, argv);
+
+ if (show_modified)
+ refresh_index(&the_index, REFRESH_QUIET, pathspec, NULL, NULL);
+
+ /* With no flags, we default to showing the cached files */
+ if (!(show_stage | show_deleted | show_others | show_unmerged |
+ show_killed | show_modified | show_resolve_undo))
+ show_cached = 1;
+
+ show_files(&dir);
+ return 0;
+}
diff --git a/command-list.txt b/command-list.txt
index 95bf18c..15e6770 100644
--- a/command-list.txt
+++ b/command-list.txt
@@ -59,6 +59,7 @@ git-instaweb ancillaryinterrogators
gitk mainporcelain
git-log mainporcelain common
git-lost-found ancillarymanipulators deprecated
+git-ls mainporcelain
git-ls-files plumbinginterrogators
git-ls-remote plumbinginterrogators
git-ls-tree plumbinginterrogators
diff --git a/git.c b/git.c
index 68334f6..f8e20d2 100644
--- a/git.c
+++ b/git.c
@@ -357,6 +357,7 @@ static void handle_internal_command(int argc, const char **argv)
{ "init", cmd_init_db },
{ "init-db", cmd_init_db },
{ "log", cmd_log, RUN_SETUP },
+ { "ls", cmd_ls, RUN_SETUP | NEED_WORK_TREE },
{ "ls-files", cmd_ls_files, RUN_SETUP },
{ "ls-tree", cmd_ls_tree, RUN_SETUP },
{ "ls-remote", cmd_ls_remote, RUN_SETUP_GENTLY },
--
1.7.2.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 12/16] ls: add --column
2011-02-09 12:24 [PATCH 00/16] column output (v2) and git-ls Nguyễn Thái Ngọc Duy
` (10 preceding siblings ...)
2011-02-09 12:24 ` [PATCH 11/16] Add ls command Nguyễn Thái Ngọc Duy
@ 2011-02-09 12:24 ` 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
` (3 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-02-09 12:24 UTC (permalink / raw)
To: git, Jonathan Niedier; +Cc: Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
builtin/ls-files.c | 16 ++++++++++++++++
1 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index cab7a10..3195f75 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -13,6 +13,7 @@
#include "parse-options.h"
#include "resolve-undo.h"
#include "string-list.h"
+#include "column.h"
static int abbrev;
static int show_deleted;
@@ -45,8 +46,19 @@ static const char *tag_modified = "";
static const char *tag_skip_worktree = "";
static const char *tag_resolve_undo = "";
+static struct string_list output;
+static int column_mode;
+
static void write_name(const char* name, size_t len)
{
+ /* No quoting in column layout. It will be done by the end. */
+ if (column_mode & COL_MODE) {
+ struct strbuf sb = STRBUF_INIT;
+ strbuf_add(&sb, name, len);
+ string_list_append(&output, strbuf_detach(&sb, NULL));
+ return;
+ }
+
write_name_quoted_relative(name, len, prefix, prefix_len, stdout,
line_terminator);
}
@@ -637,6 +649,7 @@ int cmd_ls(int argc, const char **argv, const char *cmd_prefix)
DIR_SHOW_IGNORED),
OPT_BOOLEAN('k', "killed", &show_killed,
"show files on the filesystem that need to be removed"),
+ OPT_COLUMN(0, "column", &column_mode, "show files in columns" ),
OPT_END()
};
@@ -652,6 +665,8 @@ int cmd_ls(int argc, const char **argv, const char *cmd_prefix)
if (read_cache() < 0)
die("index file corrupt");
+ column_mode = core_column;
+
argc = parse_options(argc, argv, prefix, builtin_ls_files_options,
ls_files_usage, 0);
@@ -669,5 +684,6 @@ int cmd_ls(int argc, const char **argv, const char *cmd_prefix)
show_cached = 1;
show_files(&dir);
+ display_columns(&output, column_mode, term_columns(), 2, NULL);
return 0;
}
--
1.7.2.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 13/16] ls: add --recursive and turn default to non-recursive mode
2011-02-09 12:24 [PATCH 00/16] column output (v2) and git-ls Nguyễn Thái Ngọc Duy
` (11 preceding siblings ...)
2011-02-09 12:24 ` [PATCH 12/16] ls: add --column Nguyễn Thái Ngọc Duy
@ 2011-02-09 12:24 ` 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
` (2 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-02-09 12:24 UTC (permalink / raw)
To: git, Jonathan Niedier; +Cc: Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
This patch should be after 14/16. Otherwise the requirement in path_too_deep()
is just wrong. Too late to reorder the series for sending.
builtin/ls-files.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 52 insertions(+), 2 deletions(-)
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 3195f75..87ee728 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -27,6 +27,7 @@ static int show_killed;
static int show_valid_bit;
static int line_terminator = '\n';
static int debug_mode;
+static int depth_limit;
static const char *prefix;
static int max_prefix_len;
@@ -63,18 +64,54 @@ static void write_name(const char* name, size_t len)
line_terminator);
}
+static const char *path_too_deep(const char *name)
+{
+ int common = 0;
+ if (!depth_limit)
+ return NULL;
+
+ /* When depth_limit is set, pathspec contains exactly 1 item */
+ while (name[common] &&
+ name[common] == pathspec[0][common])
+ common++;
+ while (common && name[common] != '/')
+ common--;
+ if (name[common] == '/')
+ common++;
+ return strchr(name + common, '/');
+}
+
+static int already_shown(const char *name)
+{
+ const char *last_item;
+ int len;
+
+ if (!output.nr)
+ return 0;
+
+ last_item = output.items[output.nr-1].string;
+ len = strlen(last_item);
+ return !strncmp(last_item, name, len) && name[len] == '/';
+}
+
static void show_dir_entry(const char *tag, struct dir_entry *ent)
{
int len = max_prefix_len;
+ const char *too_deep;
if (len >= ent->len)
die("git ls-files: internal error - directory entry not superset of prefix");
+ if (already_shown(ent->name))
+ return;
+
+ too_deep = path_too_deep(ent->name);
if (!match_pathspec(pathspec, ent->name, ent->len, len, ps_matched))
return;
+ len = too_deep ? too_deep - ent->name : ent->len;
fputs(tag, stdout);
- write_name(ent->name, ent->len);
+ write_name(ent->name, len);
}
static void show_other_files(struct dir_struct *dir)
@@ -141,12 +178,19 @@ static void show_killed_files(struct dir_struct *dir)
static void show_ce_entry(const char *tag, struct cache_entry *ce)
{
int len = max_prefix_len;
+ const char *too_deep;
+ int namelen;
if (len >= ce_namelen(ce))
die("git ls-files: internal error - cache entry not superset of prefix");
+ if (already_shown(ce->name))
+ return;
+
+ too_deep = path_too_deep(ce->name);
if (!match_pathspec(pathspec, ce->name, ce_namelen(ce), len, ps_matched))
return;
+ namelen = too_deep ? too_deep - ce->name : ce_namelen(ce);
if (tag && *tag && show_valid_bit &&
(ce->ce_flags & CE_VALID)) {
@@ -174,7 +218,7 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce)
find_unique_abbrev(ce->sha1,abbrev),
ce_stage(ce));
}
- write_name(ce->name, ce_namelen(ce));
+ write_name(ce->name, namelen);
if (debug_mode) {
printf(" ctime: %d:%d\n", ce->ce_ctime.sec, ce->ce_ctime.nsec);
printf(" mtime: %d:%d\n", ce->ce_mtime.sec, ce->ce_mtime.nsec);
@@ -635,6 +679,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
int cmd_ls(int argc, const char **argv, const char *cmd_prefix)
{
struct dir_struct dir;
+ int recursive = 0;
struct option builtin_ls_files_options[] = {
OPT_BOOLEAN('c', "cached", &show_cached,
"show cached files in the output (default)"),
@@ -647,6 +692,8 @@ int cmd_ls(int argc, const char **argv, const char *cmd_prefix)
OPT_BIT('i', "ignored", &dir.flags,
"show ignored files in the output",
DIR_SHOW_IGNORED),
+ OPT_BOOLEAN('r', "recursive", &recursive,
+ "list recursively"),
OPT_BOOLEAN('k', "killed", &show_killed,
"show files on the filesystem that need to be removed"),
OPT_COLUMN(0, "column", &column_mode, "show files in columns" ),
@@ -683,6 +730,9 @@ int cmd_ls(int argc, const char **argv, const char *cmd_prefix)
show_killed | show_modified | show_resolve_undo))
show_cached = 1;
+ if (!recursive)
+ depth_limit = 1;
+
show_files(&dir);
display_columns(&output, column_mode, term_columns(), 2, NULL);
return 0;
--
1.7.2.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 14/16] ls: immitate UNIX ls output style
2011-02-09 12:24 [PATCH 00/16] column output (v2) and git-ls Nguyễn Thái Ngọc Duy
` (12 preceding siblings ...)
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 ` 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
15 siblings, 0 replies; 17+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-02-09 12:24 UTC (permalink / raw)
To: git, Jonathan Niedier; +Cc: Nguyễn Thái Ngọc Duy
Two points:
- When input is a mixed of directories and files, files will be
grouped and displayed first. Directory content will follow.
- GNU ls when examining a directory will output files relative to
that directory.
Index does not have directories. There nearest thing to that is
pathspecs that expand to more than one item. So in Git the rules become:
- Multiple match pathspecs is printed with a header, the pathspec,
then the content (its expansion). If there is only one pathspec, no
header will be printed.
- The common directory prefix of all files from a pathspec will be
stripped (not yet implemented)
- One-match pathspecs will be grouped and printed out first like
the result of a virtual multiple match pathspec.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
Mixing multiple entry types (others and cached) will result in
duplicates and unsorted output. The command is a porcelain now,
perhaps we should sort/uniq output?
one_match_pathspec() needs better impl.
builtin/ls-files.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 96 insertions(+), 5 deletions(-)
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 87ee728..22e0c87 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -676,10 +676,46 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
return 0;
}
+static int one_match_pathspec(const char *pathspec)
+{
+ struct stat st;
+ int len = strlen(pathspec);
+
+ if (show_cached) {
+ char *new_path;
+ int pos = index_name_pos(&the_index, pathspec, len);
+ if (pos >= 0)
+ return 1;
+
+ new_path = xmalloc(len+2);
+ memcpy(new_path, pathspec, len);
+ new_path[len++] = '/';
+ new_path[len] = 0;
+ pos = index_name_pos(&the_index, pathspec, len);
+ if (pos >= 0)
+ die("BUG: Wait there are directories in index??");
+ pos = -pos-1;
+
+ /* dir match */
+ if (!strncmp(the_index.cache[pos]->name, new_path, len)) {
+ free(new_path);
+ return 0;
+ }
+ free(new_path);
+ }
+
+ if (!stat(pathspec, &st) && !S_ISDIR(st.st_mode))
+ return 1;
+
+ return 0;
+}
+
int cmd_ls(int argc, const char **argv, const char *cmd_prefix)
{
+ int show_pathspec;
+ const char **pathspecs, **one_matches = NULL;
struct dir_struct dir;
- int recursive = 0;
+ int recursive = 0, src, dst, len;
struct option builtin_ls_files_options[] = {
OPT_BOOLEAN('c', "cached", &show_cached,
"show cached files in the output (default)"),
@@ -720,20 +756,75 @@ int cmd_ls(int argc, const char **argv, const char *cmd_prefix)
if (dir.flags & DIR_SHOW_IGNORED || show_others)
setup_standard_excludes(&dir);
- pathspec = get_pathspec(prefix, argv);
+ pathspecs = get_pathspec(prefix, argv);
if (show_modified)
- refresh_index(&the_index, REFRESH_QUIET, pathspec, NULL, NULL);
+ refresh_index(&the_index, REFRESH_QUIET, pathspecs, NULL, NULL);
+
+ if (!pathspecs) {
+ static const char *spec[2];
+ spec[0] = ".";
+ spec[1] = NULL;
+ pathspecs = get_pathspec(prefix, spec);
+ }
/* With no flags, we default to showing the cached files */
if (!(show_stage | show_deleted | show_others | show_unmerged |
show_killed | show_modified | show_resolve_undo))
show_cached = 1;
+ /*
+ * Group one-match pathspecs together. Shell expansion may
+ * turn foo* to fooa foob/ and fooc. List fooa and fooc, leave
+ * foob for later.
+ */
+ len = src = dst = 0;
+ while (pathspecs[src]) {
+ if (one_match_pathspec(pathspecs[src])) {
+ len++;
+ one_matches = xrealloc(one_matches, sizeof(*one_matches) * (len+1));
+ one_matches[len - 1] = pathspecs[src];
+ src++;
+ continue;
+ }
+ if (src != dst)
+ pathspecs[dst] = pathspecs[src];
+ src++;
+ dst++;
+ }
+ pathspecs[dst] = NULL;
+
if (!recursive)
depth_limit = 1;
- show_files(&dir);
- display_columns(&output, column_mode, term_columns(), 2, NULL);
+ if (len) {
+ one_matches[len] = NULL;
+ pathspec = one_matches;
+ show_files(&dir);
+ display_columns(&output, column_mode, term_columns(), 2, NULL);
+ string_list_clear(&output, 0);
+ if (dst)
+ printf("\n");
+ }
+
+ if (!pathspecs[0])
+ return 0;
+
+ show_pathspec = dst > 1 || len;
+ pathspec = xmalloc(sizeof(*pathspec)*2);
+ pathspec[1] = NULL;
+ while (*pathspecs) {
+ pathspec[0] = pathspecs[0];
+ pathspecs++;
+
+ show_files(&dir);
+ if (output.nr && show_pathspec)
+ printf("%s:\n", pathspec[0]);
+
+ display_columns(&output, column_mode, term_columns(), 2, NULL);
+ string_list_clear(&output, 0);
+ if (show_pathspec && pathspecs[0])
+ printf("\n");
+ }
return 0;
}
--
1.7.2.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 15/16] ls: strip common directory prefix from output
2011-02-09 12:24 [PATCH 00/16] column output (v2) and git-ls Nguyễn Thái Ngọc Duy
` (13 preceding siblings ...)
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 ` 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
15 siblings, 0 replies; 17+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-02-09 12:24 UTC (permalink / raw)
To: git, Jonathan Niedier; +Cc: Nguyễn Thái Ngọc Duy
In GNU ls, files are printed relative to their parent directory.
We don't have such thing, so stay as close as we can.
The result is quite good. If the given pathspec is a directory prefix,
it will be stripped, strictly following GNU ls behavior. If the pathspec
has wildcards, then the command part is stripped. Usually this is the
prefix part in the pathspec.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
builtin/ls-files.c | 37 +++++++++++++++++++++++++++++++++++++
1 files changed, 37 insertions(+), 0 deletions(-)
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 22e0c87..bc438b2 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -710,6 +710,41 @@ static int one_match_pathspec(const char *pathspec)
return 0;
}
+static void remove_common_prefix()
+{
+ int i, len = -1;
+ const char *s1, *s2;
+
+ if (output.nr <= 1)
+ return;
+
+ /*
+ * Eliminate common prefix. This is caused by a prefix
+ * pathspec like "ls builtin" or even "ls 't/t*.sh'"
+ */
+
+ s1 = output.items[output.nr-1].string;
+ len = strlen(s1);
+ for (i = 1; i < output.nr; i++) {
+ int j = 0;
+ s1 = output.items[i-1].string;
+ s2 = output.items[i].string;
+ while (j < len && s1[j] == s2[j])
+ j++;
+ len = j;
+ }
+ while (len && s1[len] != '/')
+ len--;
+ if (len && s1[len] == '/')
+ len++;
+ if (len) {
+ for (i = 0; i < output.nr; i++) {
+ char *s = output.items[i].string;
+ memcpy(s, s+len, strlen(s) - len + 1);
+ }
+ }
+}
+
int cmd_ls(int argc, const char **argv, const char *cmd_prefix)
{
int show_pathspec;
@@ -801,6 +836,7 @@ int cmd_ls(int argc, const char **argv, const char *cmd_prefix)
one_matches[len] = NULL;
pathspec = one_matches;
show_files(&dir);
+ remove_common_prefix();
display_columns(&output, column_mode, term_columns(), 2, NULL);
string_list_clear(&output, 0);
if (dst)
@@ -821,6 +857,7 @@ int cmd_ls(int argc, const char **argv, const char *cmd_prefix)
if (output.nr && show_pathspec)
printf("%s:\n", pathspec[0]);
+ remove_common_prefix();
display_columns(&output, column_mode, term_columns(), 2, NULL);
string_list_clear(&output, 0);
if (show_pathspec && pathspecs[0])
--
1.7.2.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 16/16] ls: color output
2011-02-09 12:24 [PATCH 00/16] column output (v2) and git-ls Nguyễn Thái Ngọc Duy
` (14 preceding siblings ...)
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 ` Nguyễn Thái Ngọc Duy
15 siblings, 0 replies; 17+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2011-02-09 12:24 UTC (permalink / raw)
To: git, Jonathan Niedier; +Cc: Nguyễn Thái Ngọc Duy
The rules are currently hardcoded (the first item has highest priority)
- If it's a modified entry, it's bold red.
- If it's an executable, it's bold green.
- If it's a directory, it's bold blue.
Personally I'm happy with just that. But people might want to separate
other entries from cached ones in "ls -co", anyone?
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
Bad bad bad hard coding.
builtin/ls-files.c | 59 ++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 50 insertions(+), 9 deletions(-)
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index bc438b2..9c8179a 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -14,6 +14,7 @@
#include "resolve-undo.h"
#include "string-list.h"
#include "column.h"
+#include "color.h"
static int abbrev;
static int show_deleted;
@@ -37,6 +38,7 @@ static int error_unmatch;
static char *ps_matched;
static const char *with_tree;
static int exc_given;
+static int use_color;
static const char *tag_cached = "";
static const char *tag_unmerged = "";
@@ -50,12 +52,18 @@ static const char *tag_resolve_undo = "";
static struct string_list output;
static int column_mode;
-static void write_name(const char* name, size_t len)
+static void write_name(const char* name, size_t len, const char *color)
{
/* No quoting in column layout. It will be done by the end. */
if (column_mode & COL_MODE) {
struct strbuf sb = STRBUF_INIT;
- strbuf_add(&sb, name, len);
+ if (color && use_color) {
+ strbuf_addstr(&sb, color);
+ strbuf_add(&sb, name, len);
+ strbuf_addstr(&sb, GIT_COLOR_RESET);
+ }
+ else
+ strbuf_add(&sb, name, len);
string_list_append(&output, strbuf_detach(&sb, NULL));
return;
}
@@ -81,16 +89,29 @@ static const char *path_too_deep(const char *name)
return strchr(name + common, '/');
}
+static int ansi_length(const char *s)
+{
+ const char *p = s;
+ while (p[0] == '\033')
+ p += strspn(p + 2, "0123456789;") + 3;
+ return p - s;
+}
+
static int already_shown(const char *name)
{
const char *last_item;
- int len;
+ int len, ansi_len;
if (!output.nr)
return 0;
last_item = output.items[output.nr-1].string;
len = strlen(last_item);
+ ansi_len = ansi_length(last_item);
+ if (ansi_len) {
+ last_item += ansi_len;
+ len -= ansi_len + strlen(GIT_COLOR_RESET);
+ }
return !strncmp(last_item, name, len) && name[len] == '/';
}
@@ -98,6 +119,7 @@ static void show_dir_entry(const char *tag, struct dir_entry *ent)
{
int len = max_prefix_len;
const char *too_deep;
+ struct stat st;
if (len >= ent->len)
die("git ls-files: internal error - directory entry not superset of prefix");
@@ -111,7 +133,9 @@ static void show_dir_entry(const char *tag, struct dir_entry *ent)
len = too_deep ? too_deep - ent->name : ent->len;
fputs(tag, stdout);
- write_name(ent->name, len);
+ write_name(ent->name, len,
+ len < ent->len ? GIT_COLOR_BOLD_BLUE :
+ (!stat(ent->name, &st) && st.st_mode & S_IXUSR ? GIT_COLOR_BOLD_GREEN : NULL));
}
static void show_other_files(struct dir_struct *dir)
@@ -179,6 +203,7 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce)
{
int len = max_prefix_len;
const char *too_deep;
+ struct stat st;
int namelen;
if (len >= ce_namelen(ce))
@@ -218,7 +243,10 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce)
find_unique_abbrev(ce->sha1,abbrev),
ce_stage(ce));
}
- write_name(ce->name, namelen);
+ write_name(ce->name, namelen,
+ namelen < ce_namelen(ce) ? GIT_COLOR_BOLD_BLUE :
+ (!stat(ce->name, &st) && ce_modified(ce, &st, 0) ? GIT_COLOR_BOLD_RED :
+ (ce_permissions(ce->ce_mode) == 0755 ? GIT_COLOR_BOLD_GREEN : NULL)));
if (debug_mode) {
printf(" ctime: %d:%d\n", ce->ce_ctime.sec, ce->ce_ctime.nsec);
printf(" mtime: %d:%d\n", ce->ce_mtime.sec, ce->ce_mtime.nsec);
@@ -251,7 +279,7 @@ static void show_ru_info(void)
printf("%s%06o %s %d\t", tag_resolve_undo, ui->mode[i],
find_unique_abbrev(ui->sha1[i], abbrev),
i + 1);
- write_name(path, len);
+ write_name(path, len, NULL);
}
}
}
@@ -676,6 +704,16 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
return 0;
}
+static int ls_config(const char *var, const char *value, void *cb)
+{
+ if (!strcmp(var, "color.ls"))
+ use_color = git_config_colorbool(var, value, -1);
+ else
+ return git_color_default_config(var, value, cb);
+
+ return 0;
+}
+
static int one_match_pathspec(const char *pathspec)
{
struct stat st;
@@ -724,11 +762,13 @@ static void remove_common_prefix()
*/
s1 = output.items[output.nr-1].string;
- len = strlen(s1);
+ len = strlen(s1) - ansi_length(s1);
for (i = 1; i < output.nr; i++) {
int j = 0;
s1 = output.items[i-1].string;
+ s1 += ansi_length(s1);
s2 = output.items[i].string;
+ s2 += ansi_length(s2);
while (j < len && s1[j] == s2[j])
j++;
len = j;
@@ -740,6 +780,7 @@ static void remove_common_prefix()
if (len) {
for (i = 0; i < output.nr; i++) {
char *s = output.items[i].string;
+ s += ansi_length(s);
memcpy(s, s+len, strlen(s) - len + 1);
}
}
@@ -778,12 +819,12 @@ int cmd_ls(int argc, const char **argv, const char *cmd_prefix)
prefix = cmd_prefix;
if (prefix)
prefix_len = strlen(prefix);
- git_config(git_default_config, NULL);
+ git_config(ls_config, NULL);
if (read_cache() < 0)
die("index file corrupt");
- column_mode = core_column;
+ column_mode = core_column | COL_ANSI;
argc = parse_options(argc, argv, prefix, builtin_ls_files_options,
ls_files_usage, 0);
@@ -793,7 +834,7 @@ int cmd_ls(int argc, const char **argv, const char *cmd_prefix)
pathspecs = get_pathspec(prefix, argv);
- if (show_modified)
+ if (show_modified || use_color)
refresh_index(&the_index, REFRESH_QUIET, pathspecs, NULL, NULL);
if (!pathspecs) {
^ permalink raw reply related [flat|nested] 17+ messages in thread
end of thread, other threads:[~2011-02-09 12:52 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [PATCH 04/16] display_columns: add COL_DENSE to do unequal column layout 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
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).