git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Cc: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH 1/8] Import $LS_COLORS parsing code from coreutils
Date: Thu, 20 Mar 2014 17:15:44 +0700	[thread overview]
Message-ID: <1395310551-23201-2-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <1395310551-23201-1-git-send-email-pclouds@gmail.com>

This could could help highlight files in ls-files or status output, or
even diff --name-only (but that's questionable).

This code is from coreutils.git commit
7326d1f1a67edf21947ae98194f98c38b6e9e527 file src/ls.c. This is the
last GPL-2 commit before coreutils turns to GPL-3.

The code is reformatted to fit Git coding style, which is more than
just adding and removing spaces. For example, "bool" is replaced with
"int", or true/false replaced with 1/0, or the use of git's error()
instead of error(3). There are also two "#if 0" to make it build with
git-compat-util.h.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Makefile          |   1 +
 ls_colors.c (new) | 477 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ls_colors.h (new) |  20 +++
 3 files changed, 498 insertions(+)
 create mode 100644 ls_colors.c
 create mode 100644 ls_colors.h

diff --git a/Makefile b/Makefile
index f818eec..f6a6e14 100644
--- a/Makefile
+++ b/Makefile
@@ -819,6 +819,7 @@ LIB_OBJS += list-objects.o
 LIB_OBJS += ll-merge.o
 LIB_OBJS += lockfile.o
 LIB_OBJS += log-tree.o
+LIB_OBJS += ls_colors.o
 LIB_OBJS += mailmap.o
 LIB_OBJS += match-trees.o
 LIB_OBJS += merge.o
diff --git a/ls_colors.c b/ls_colors.c
new file mode 100644
index 0000000..6385446
--- /dev/null
+++ b/ls_colors.c
@@ -0,0 +1,477 @@
+#include "git-compat-util.h"
+#include "gettext.h"
+#include "ls_colors.h"
+
+#define STREQ(a, b) (strcmp(a, b) == 0)
+
+enum indicator_no {
+	C_LEFT, C_RIGHT, C_END, C_NORM, C_FILE, C_DIR, C_LINK, C_FIFO, C_SOCK,
+	C_BLK, C_CHR, C_MISSING, C_ORPHAN, C_EXEC, C_DOOR, C_SETUID, C_SETGID,
+	C_STICKY, C_OTHER_WRITABLE, C_STICKY_OTHER_WRITABLE
+};
+
+#define FILETYPE_INDICATORS				\
+  {							\
+    C_ORPHAN, C_FIFO, C_CHR, C_DIR, C_BLK, C_FILE,	\
+    C_LINK, C_SOCK, C_FILE, C_DIR			\
+  }
+
+struct bin_str {
+	size_t len;			/* Number of bytes */
+	const char *string;		/* Pointer to the same */
+};
+
+struct color_ext_type {
+	struct bin_str ext;		/* The extension we're looking for */
+	struct bin_str seq;		/* The sequence to output when we do */
+	struct color_ext_type *next;	/* Next in list */
+};
+
+static const char *const indicator_name[]= {
+	"lc", "rc", "ec", "no", "fi", "di", "ln", "pi", "so",
+	"bd", "cd", "mi", "or", "ex", "do", "su", "sg", "st",
+	"ow", "tw", NULL
+};
+
+#define LEN_STR_PAIR(s) sizeof(s) - 1, s
+static struct bin_str color_indicator[] = {
+	{ LEN_STR_PAIR("\033[") },	/* lc: Left of color sequence */
+	{ LEN_STR_PAIR("m") },		/* rc: Right of color sequence */
+	{ 0, NULL },			/* ec: End color (replaces lc+no+rc) */
+	{ LEN_STR_PAIR("0") },		/* no: Normal */
+	{ LEN_STR_PAIR("0") },		/* fi: File: default */
+	{ LEN_STR_PAIR("01;34") },	/* di: Directory: bright blue */
+	{ LEN_STR_PAIR("01;36") },	/* ln: Symlink: bright cyan */
+	{ LEN_STR_PAIR("33") },		/* pi: Pipe: yellow/brown */
+	{ LEN_STR_PAIR("01;35") },	/* so: Socket: bright magenta */
+	{ LEN_STR_PAIR("01;33") },	/* bd: Block device: bright yellow */
+	{ LEN_STR_PAIR("01;33") },	/* cd: Char device: bright yellow */
+	{ 0, NULL },			/* mi: Missing file: undefined */
+	{ 0, NULL },			/* or: Orphaned symlink: undefined */
+	{ LEN_STR_PAIR("01;32") },	/* ex: Executable: bright green */
+	{ LEN_STR_PAIR("01;35") },	/* do: Door: bright magenta */
+	{ LEN_STR_PAIR("37;41") },	/* su: setuid: white on red */
+	{ LEN_STR_PAIR("30;43") },	/* sg: setgid: black on yellow */
+	{ LEN_STR_PAIR("37;44") },	/* st: sticky: black on blue */
+	{ LEN_STR_PAIR("34;42") },	/* ow: other-writable: blue on green */
+	{ LEN_STR_PAIR("30;42") },	/* tw: ow w/ sticky: black on green */
+};
+
+static struct color_ext_type *color_ext_list = NULL;
+/* Buffer for color sequences */
+static char *color_buf;
+
+/*
+ * True means use colors to mark types.  Also define the different
+ * colors as well as the stuff for the LS_COLORS environment variable.
+ * The LS_COLORS variable is now in a termcap-like format.
+ */
+static int print_with_color;
+
+/*
+ * When true, in a color listing, color each symlink name according to the
+ * type of file it points to.  Otherwise, color them according to the `ln'
+ * directive in LS_COLORS.  Dangling (orphan) symlinks are treated specially,
+ * regardless.  This is set when `ln=target' appears in LS_COLORS.
+ */
+static int color_symlink_as_referent;
+
+/*
+ * Parse a string as part of the LS_COLORS variable; this may involve
+ * decoding all kinds of escape characters.  If equals_end is set an
+ * unescaped equal sign ends the string, otherwise only a : or \0
+ * does.  Set *OUTPUT_COUNT to the number of bytes output.  Return
+ * true if successful.
+ *
+ * The resulting string is *not* null-terminated, but may contain
+ * embedded nulls.
+ *
+ * Note that both dest and src are char **; on return they point to
+ * the first free byte after the array and the character that ended
+ * the input string, respectively.
+ */
+static int get_funky_string(char **dest, const char **src, int equals_end,
+			    size_t *output_count)
+{
+	char num;			/* For numerical codes */
+	size_t count;			/* Something to count with */
+	enum {
+		ST_GND, ST_BACKSLASH, ST_OCTAL, ST_HEX,
+		ST_CARET, ST_END, ST_ERROR
+	} state;
+	const char *p;
+	char *q;
+
+	p = *src;			/* We don't want to double-indirect */
+	q = *dest;			/* the whole darn time.  */
+
+	count = 0;			/* No characters counted in yet.  */
+	num = 0;
+
+	state = ST_GND;		/* Start in ground state.  */
+	while (state < ST_END) {
+		switch (state) {
+		case ST_GND:		/* Ground state (no escapes) */
+			switch (*p) {
+			case ':':
+			case '\0':
+				state = ST_END;	/* End of string */
+				break;
+			case '\\':
+				state = ST_BACKSLASH; /* Backslash scape sequence */
+				++p;
+				break;
+			case '^':
+				state = ST_CARET; /* Caret escape */
+				++p;
+				break;
+			case '=':
+				if (equals_end) {
+					state = ST_END; /* End */
+					break;
+				}
+				/* else fall through */
+			default:
+				*(q++) = *(p++);
+				++count;
+				break;
+			}
+			break;
+
+		case ST_BACKSLASH:	/* Backslash escaped character */
+			switch (*p) {
+			case '0':
+			case '1':
+			case '2':
+			case '3':
+			case '4':
+			case '5':
+			case '6':
+			case '7':
+				state = ST_OCTAL;	/* Octal sequence */
+				num = *p - '0';
+				break;
+			case 'x':
+			case 'X':
+				state = ST_HEX;	/* Hex sequence */
+				num = 0;
+				break;
+			case 'a':		/* Bell */
+				num = '\a';
+				break;
+			case 'b':		/* Backspace */
+				num = '\b';
+				break;
+			case 'e':		/* Escape */
+				num = 27;
+				break;
+			case 'f':		/* Form feed */
+				num = '\f';
+				break;
+			case 'n':		/* Newline */
+				num = '\n';
+				break;
+			case 'r':		/* Carriage return */
+				num = '\r';
+				break;
+			case 't':		/* Tab */
+				num = '\t';
+				break;
+			case 'v':		/* Vtab */
+				num = '\v';
+				break;
+			case '?':		/* Delete */
+				num = 127;
+				break;
+			case '_':		/* Space */
+				num = ' ';
+				break;
+			case '\0':		/* End of string */
+				state = ST_ERROR;	/* Error! */
+				break;
+			default:		/* Escaped character like \ ^ : = */
+				num = *p;
+				break;
+			}
+			if (state == ST_BACKSLASH) {
+				*(q++) = num;
+				++count;
+				state = ST_GND;
+			}
+			++p;
+			break;
+
+		case ST_OCTAL:		/* Octal sequence */
+			if (*p < '0' || *p > '7') {
+				*(q++) = num;
+				++count;
+				state = ST_GND;
+			} else
+				num = (num << 3) + (*(p++) - '0');
+			break;
+
+		case ST_HEX:		/* Hex sequence */
+			switch (*p) {
+			case '0':
+			case '1':
+			case '2':
+			case '3':
+			case '4':
+			case '5':
+			case '6':
+			case '7':
+			case '8':
+			case '9':
+				num = (num << 4) + (*(p++) - '0');
+				break;
+			case 'a':
+			case 'b':
+			case 'c':
+			case 'd':
+			case 'e':
+			case 'f':
+				num = (num << 4) + (*(p++) - 'a') + 10;
+				break;
+			case 'A':
+			case 'B':
+			case 'C':
+			case 'D':
+			case 'E':
+			case 'F':
+				num = (num << 4) + (*(p++) - 'A') + 10;
+				break;
+			default:
+				*(q++) = num;
+				++count;
+				state = ST_GND;
+				break;
+			}
+			break;
+
+		case ST_CARET:		/* Caret escape */
+			state = ST_GND;	/* Should be the next state... */
+			if (*p >= '@' && *p <= '~') {
+				*(q++) = *(p++) & 037;
+				++count;
+			} else if (*p == '?') {
+				*(q++) = 127;
+				++count;
+			} else
+				state = ST_ERROR;
+			break;
+
+		default:
+			abort();
+		}
+	}
+
+	*dest = q;
+	*src = p;
+	*output_count = count;
+
+	return state != ST_ERROR;
+}
+
+void parse_ls_color(void)
+{
+	const char *p;			/* Pointer to character being parsed */
+	char *buf;			/* color_buf buffer pointer */
+	int state;			/* State of parser */
+	int ind_no;			/* Indicator number */
+	char label[3];			/* Indicator label */
+	struct color_ext_type *ext;	/* Extension we are working on */
+
+	if ((p = getenv("LS_COLORS")) == NULL || *p == '\0')
+		return;
+
+	ext = NULL;
+	strcpy (label, "??");
+
+	/*
+	 * This is an overly conservative estimate, but any possible
+	 * LS_COLORS string will *not* generate a color_buf longer
+	 * than itself, so it is a safe way of allocating a buffer in
+	 * advance.
+	 */
+	buf = color_buf = xstrdup(p);
+
+	state = 1;
+	while (state > 0) {
+		switch (state) {
+		case 1:		/* First label character */
+			switch (*p) {
+			case ':':
+				++p;
+				break;
+
+			case '*':
+				/*
+				 * Allocate new extension block and add to head of
+				 * linked list (this way a later definition will
+				 * override an earlier one, which can be useful for
+				 * having terminal-specific defs override global).
+				 */
+
+				ext = xmalloc(sizeof *ext);
+				ext->next = color_ext_list;
+				color_ext_list = ext;
+
+				++p;
+				ext->ext.string = buf;
+
+				state = (get_funky_string(&buf, &p, 1, &ext->ext.len)
+					 ? 4 : -1);
+				break;
+
+			case '\0':
+				state = 0;	/* Done! */
+				break;
+
+			default:	/* Assume it is file type label */
+				label[0] = *(p++);
+				state = 2;
+				break;
+			}
+			break;
+
+		case 2:		/* Second label character */
+			if (*p) {
+				label[1] = *(p++);
+				state = 3;
+			} else
+				state = -1;	/* Error */
+			break;
+
+		case 3:		/* Equal sign after indicator label */
+			state = -1;	/* Assume failure...  */
+			if (*(p++) == '=') { /* It *should* be...  */
+				for (ind_no = 0; indicator_name[ind_no] != NULL; ++ind_no) {
+					if (STREQ (label, indicator_name[ind_no])) {
+						color_indicator[ind_no].string = buf;
+						state = (get_funky_string(&buf, &p, 0,
+									  &color_indicator[ind_no].len)
+							 ? 1 : -1);
+						break;
+					}
+				}
+				if (state == -1)
+					error(_("unrecognized prefix: %s"), label);
+			}
+			break;
+
+		case 4:		/* Equal sign after *.ext */
+			if (*(p++) == '=') {
+				ext->seq.string = buf;
+				state = (get_funky_string(&buf, &p, 0, &ext->seq.len)
+					 ? 1 : -1);
+			} else
+				state = -1;
+			break;
+		}
+	}
+
+	if (state < 0) {
+		struct color_ext_type *e;
+		struct color_ext_type *e2;
+
+		error(_("unparsable value for LS_COLORS environment variable"));
+		free(color_buf);
+		for (e = color_ext_list; e != NULL; /* empty */) {
+			e2 = e;
+			e = e->next;
+			free(e2);
+		}
+		print_with_color = 0;
+	}
+
+	if (color_indicator[C_LINK].len == 6 &&
+	    !strncmp(color_indicator[C_LINK].string, "target", 6))
+		color_symlink_as_referent = 1;
+}
+
+/* Output a color indicator (which may contain nulls).  */
+static void put_indicator(const struct bin_str *ind)
+{
+	size_t i;
+	const char *p;
+
+	p = ind->string;
+
+	for (i = ind->len; i != 0; --i)
+		putchar(*(p++));
+}
+
+void print_color_indicator(const char *name, mode_t mode, int linkok,
+			   int stat_ok, enum filetype filetype)
+{
+	int type;
+	struct color_ext_type *ext;	/* Color extension */
+	size_t len;			/* Length of name */
+
+	/* Is this a nonexistent file?  If so, linkok == -1.  */
+
+	if (linkok == -1 && color_indicator[C_MISSING].string != NULL)
+		type = C_MISSING;
+	else if (!stat_ok) {
+		static enum indicator_no filetype_indicator[] = FILETYPE_INDICATORS;
+		type = filetype_indicator[filetype];
+	} else {
+		if (S_ISREG(mode)) {
+			type = C_FILE;
+			if ((mode & S_ISUID) != 0)
+				type = C_SETUID;
+			else if ((mode & S_ISGID) != 0)
+				type = C_SETGID;
+#if 0
+			else if ((mode & S_IXUGO) != 0)
+				type = C_EXEC;
+#endif
+		} else if (S_ISDIR(mode)) {
+			if ((mode & S_ISVTX) && (mode & S_IWOTH))
+				type = C_STICKY_OTHER_WRITABLE;
+			else if ((mode & S_IWOTH) != 0)
+				type = C_OTHER_WRITABLE;
+			else if ((mode & S_ISVTX) != 0)
+				type = C_STICKY;
+			else
+				type = C_DIR;
+		} else if (S_ISLNK(mode))
+			type = ((!linkok && color_indicator[C_ORPHAN].string)
+				? C_ORPHAN : C_LINK);
+		else if (S_ISFIFO(mode))
+			type = C_FIFO;
+		else if (S_ISSOCK(mode))
+			type = C_SOCK;
+		else if (S_ISBLK(mode))
+			type = C_BLK;
+		else if (S_ISCHR(mode))
+			type = C_CHR;
+#if 0
+		else if (S_ISDOOR(mode))
+			type = C_DOOR;
+#endif
+		else {
+			/* Classify a file of some other type as C_ORPHAN.  */
+			type = C_ORPHAN;
+		}
+	}
+
+	/* Check the file's suffix only if still classified as C_FILE.  */
+	ext = NULL;
+	if (type == C_FILE) {
+		/* Test if NAME has a recognized suffix.  */
+
+		len = strlen(name);
+		name += len;		/* Pointer to final \0.  */
+		for (ext = color_ext_list; ext != NULL; ext = ext->next) {
+			if (ext->ext.len <= len
+			    && strncmp(name - ext->ext.len, ext->ext.string,
+				       ext->ext.len) == 0)
+				break;
+		}
+	}
+
+	put_indicator(&color_indicator[C_LEFT]);
+	put_indicator(ext ? &(ext->seq) : &color_indicator[type]);
+	put_indicator(&color_indicator[C_RIGHT]);
+}
diff --git a/ls_colors.h b/ls_colors.h
new file mode 100644
index 0000000..3201be6
--- /dev/null
+++ b/ls_colors.h
@@ -0,0 +1,20 @@
+#ifndef LS_COLORS_H
+#define LS_COLORS_H
+
+enum filetype {
+	unknown,
+	fifo,
+	chardev,
+	directory,
+	blockdev,
+	normal,
+	symbolic_link,
+	sock,
+	whiteout,
+	arg_directory
+};
+
+void parse_ls_color(void);
+void print_color_indicator(const char *name, mode_t mode, int linkok,
+			   int stat_ok, enum filetype filetype);
+#endif
-- 
1.9.0.40.gaa8c3ea

  reply	other threads:[~2014-03-20 10:15 UTC|newest]

Thread overview: 79+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-03-20 10:15 [PATCH/RFC 0/8] git-ls Nguyễn Thái Ngọc Duy
2014-03-20 10:15 ` Nguyễn Thái Ngọc Duy [this message]
2014-03-20 19:09   ` [PATCH 1/8] Import $LS_COLORS parsing code from coreutils David Tran
2014-03-21 11:54     ` Duy Nguyen
2014-03-21 20:01       ` David Tran
2014-03-20 10:15 ` [PATCH 2/8] ls_colors.c: a bit of document on print_color_indicator input Nguyễn Thái Ngọc Duy
2014-03-20 10:15 ` [PATCH 3/8] ls_colors.c: enable coloring on u+x files Nguyễn Thái Ngọc Duy
2014-03-20 11:46   ` Matthieu Moy
2014-03-20 12:14     ` Duy Nguyen
2014-03-20 17:41       ` Junio C Hamano
2014-03-21 11:52         ` Duy Nguyen
2014-03-20 10:15 ` [PATCH 4/8] ls_colors.c: new color descriptors Nguyễn Thái Ngọc Duy
2014-03-20 10:15 ` [PATCH 5/8] ls-files: add --color to highlight based on $LS_COLORS Nguyễn Thái Ngọc Duy
2014-03-20 10:15 ` [PATCH 6/8] ls-files: add --column Nguyễn Thái Ngọc Duy
2014-03-25 11:34   ` Matthieu Moy
2014-03-20 10:15 ` [PATCH 7/8] ls-files: support --max-depth Nguyễn Thái Ngọc Duy
2014-03-25  8:55   ` Matthieu Moy
2014-03-25 11:15     ` Duy Nguyen
2014-03-27 14:36       ` Duy Nguyen
2014-03-28 13:52       ` Matthieu Moy
2014-03-28 14:15         ` Duy Nguyen
2014-03-28 14:38           ` Duy Nguyen
2014-03-20 10:15 ` [PATCH 8/8] Add git-ls, a user friendly version of ls-files and more Nguyễn Thái Ngọc Duy
2014-03-20 11:56   ` Matthieu Moy
2014-03-26 13:48 ` [PATCH v2 00/17] git-ls Nguyễn Thái Ngọc Duy
2014-03-26 13:48   ` [PATCH v2 01/17] ls_colors.c: add $LS_COLORS parsing code Nguyễn Thái Ngọc Duy
2014-03-26 13:48   ` [PATCH v2 02/17] ls_colors.c: parse color.ls.* from config file Nguyễn Thái Ngọc Duy
2014-03-26 13:48   ` [PATCH v2 03/17] ls_colors.c: add function to color a file name Nguyễn Thái Ngọc Duy
2014-03-26 19:14     ` Eric Sunshine
2014-03-26 13:48   ` [PATCH v2 04/17] ls_colors.c: highlight submodules like directories Nguyễn Thái Ngọc Duy
2014-03-26 13:48   ` [PATCH v2 05/17] ls-files: buffer full item in strbuf before printing Nguyễn Thái Ngọc Duy
2014-03-26 19:22     ` Eric Sunshine
2014-03-26 23:18       ` Duy Nguyen
2014-03-27  5:22         ` Eric Sunshine
2014-03-26 13:48   ` [PATCH v2 06/17] ls-files: add --color to highlight file names Nguyễn Thái Ngọc Duy
2014-03-26 19:13     ` Eric Sunshine
2014-03-26 23:15       ` Duy Nguyen
2014-03-28  0:49         ` Eric Sunshine
2014-03-26 13:48   ` [PATCH v2 07/17] ls-files: add --column Nguyễn Thái Ngọc Duy
2014-03-26 19:46     ` Eric Sunshine
2014-03-26 13:48   ` [PATCH v2 08/17] ls-files: support --max-depth Nguyễn Thái Ngọc Duy
2014-03-26 19:50     ` Eric Sunshine
2014-03-26 13:48   ` [PATCH v2 09/17] ls-files: split main ls-files logic into ls_files() function Nguyễn Thái Ngọc Duy
2014-03-26 13:48   ` [PATCH v2 10/17] Add git-ls, a user friendly version of ls-files and more Nguyễn Thái Ngọc Duy
2014-03-26 20:16     ` Eric Sunshine
2014-03-26 13:48   ` [PATCH v2 11/17] ls: -u does not imply showing stages Nguyễn Thái Ngọc Duy
2014-03-26 13:48   ` [PATCH v2 12/17] ls: add -R/--recursive short for --max-depth=-1 Nguyễn Thái Ngọc Duy
2014-03-26 13:48   ` [PATCH v2 13/17] ls: add -1 short for --no-column in the spirit of GNU ls Nguyễn Thái Ngọc Duy
2014-03-28  3:52     ` Eric Sunshine
2014-03-26 13:48   ` [PATCH v2 14/17] ls: add -t back Nguyễn Thái Ngọc Duy
2014-03-26 13:48   ` [PATCH v2 15/17] ls: sort output and remove duplicates Nguyễn Thái Ngọc Duy
2014-03-26 13:48   ` [PATCH v2 16/17] ls: do not show duplicate cached entries Nguyễn Thái Ngọc Duy
2014-03-28  4:04     ` Eric Sunshine
2014-03-28 13:18       ` [PATCH] ls-files: do not trust stat info if lstat() fails Nguyễn Thái Ngọc Duy
2014-04-02 18:15         ` Junio C Hamano
2014-04-03 12:40           ` Duy Nguyen
2014-04-03 16:30             ` Junio C Hamano
2014-04-05  8:03               ` Duy Nguyen
2014-04-07 17:13                 ` Junio C Hamano
2014-03-26 13:48   ` [PATCH v2 17/17] ls: show directories as well as files Nguyễn Thái Ngọc Duy
2014-03-30 13:55   ` [PATCH v3 00/18] git-ls Nguyễn Thái Ngọc Duy
2014-03-30 13:55     ` [PATCH v3 01/18] ls_colors.c: add $LS_COLORS parsing code Nguyễn Thái Ngọc Duy
2014-03-30 13:55     ` [PATCH v3 02/18] ls_colors.c: parse color.ls.* from config file Nguyễn Thái Ngọc Duy
2014-03-30 13:55     ` [PATCH v3 03/18] ls_colors.c: add a function to color a file name Nguyễn Thái Ngọc Duy
2014-03-30 13:55     ` [PATCH v3 04/18] ls_colors.c: highlight submodules like directories Nguyễn Thái Ngọc Duy
2014-03-30 13:55     ` [PATCH v3 05/18] ls-files: buffer full item in strbuf before printing Nguyễn Thái Ngọc Duy
2014-03-30 13:55     ` [PATCH v3 06/18] ls-files: add --color to highlight file names Nguyễn Thái Ngọc Duy
2014-03-30 13:55     ` [PATCH v3 07/18] ls-files: add --column Nguyễn Thái Ngọc Duy
2014-03-30 13:55     ` [PATCH v3 08/18] ls-files: support --max-depth Nguyễn Thái Ngọc Duy
2014-03-30 13:56     ` [PATCH v3 09/18] Add git-list-files, a user friendly version of ls-files and more Nguyễn Thái Ngọc Duy
2014-03-30 13:56     ` [PATCH v3 10/18] list-files: -u does not imply showing stages Nguyễn Thái Ngọc Duy
2014-03-30 13:56     ` [PATCH v3 11/18] list-files: add -R/--recursive short for --max-depth=-1 Nguyễn Thái Ngọc Duy
2014-03-30 13:56     ` [PATCH v3 12/18] list-files: add -1 short for --no-column Nguyễn Thái Ngọc Duy
2014-03-30 13:56     ` [PATCH v3 13/18] list-files: add -t back Nguyễn Thái Ngọc Duy
2014-03-30 13:56     ` [PATCH v3 14/18] list-files: sort output and remove duplicates Nguyễn Thái Ngọc Duy
2014-03-30 13:56     ` [PATCH v3 15/18] list-files: do not show duplicate cached entries Nguyễn Thái Ngọc Duy
2014-03-30 13:56     ` [PATCH v3 16/18] list-files: show directories as well as files Nguyễn Thái Ngọc Duy
2014-03-30 13:56     ` [PATCH v3 17/18] list-files: add -F/--classify Nguyễn Thái Ngọc Duy
2014-03-30 13:56     ` [PATCH v3 18/18] list-files -F: show submodules with the new indicator '&' 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=1395310551-23201-2-git-send-email-pclouds@gmail.com \
    --to=pclouds@gmail.com \
    --cc=git@vger.kernel.org \
    /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).