git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH 0/6] Advanced --oneline layout
@ 2012-09-22  4:22 Nguyễn Thái Ngọc Duy
  2012-09-22  4:22 ` [PATCH 1/6] pretty: share code between format_decoration and show_decorations Nguyễn Thái Ngọc Duy
                   ` (7 more replies)
  0 siblings, 8 replies; 21+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-22  4:22 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

Still a toy series (previous discussion [1]) but it's getting close to
something useful.

This introduces three placeholders %<, %> and %<> for
left/right/center align the next placeholder. Any of them can be
followed by '|' to make the next placeholder use up to the Nth column.

It's pretty useful already. You should be able to do multi column
layout on your wiiide terminal. It might even be useful in multi-line
printouts (e.g. we can relayout the commit header)

There are a few things we can improve:

 - utf8-only support does not sound nice (even though I'm
   perfectly happy with it). At some point I think it'll be easier for
   us to declare all internal strings be in utf8 (or ascii in certain
   places), input/output routines are supposed to do the conversion.
   GNOME has gone this way since 2.0.
 - ellipsis to prevent too long text breaking layout
 - specifing "30% of my screen width" would be nice, but it could get
   complicated if users start to demand "30% width, but no less than 30
   columns and no more than 100 columns, and if blah blah"

[1] http://thread.gmane.org/gmane.comp.version-control.git/205922/focus=206049

Nguyễn Thái Ngọc Duy (6):
  pretty: share code between format_decoration and show_decorations
  pretty: split parsing %C into a separate function
  pretty: support %C(auto[,N]) to turn on coloring on next
    placeholder(s)
  utf8.c: move display_mode_esc_sequence_len() for use by other
    functions
  utf8.c: add utf8_strnwidth() with the ability to skip ansi sequences
  pretty: support padding placeholders, %< %> and %<>

 Documentation/pretty-formats.txt |   5 +
 log-tree.c                       |  59 ++++++-----
 log-tree.h                       |   3 +
 pretty.c                         | 211 +++++++++++++++++++++++++++++++--------
 t/t4207-log-decoration-colors.sh |   8 +-
 utf8.c                           |  48 +++++----
 utf8.h                           |   1 +
 7 files changed, 244 insertions(+), 91 deletions(-)

-- 
1.7.12.1.384.g7b808e7

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 1/6] pretty: share code between format_decoration and show_decorations
  2012-09-22  4:22 [PATCH 0/6] Advanced --oneline layout Nguyễn Thái Ngọc Duy
@ 2012-09-22  4:22 ` Nguyễn Thái Ngọc Duy
  2012-09-22  4:22 ` [PATCH 2/6] pretty: split parsing %C into a separate function Nguyễn Thái Ngọc Duy
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 21+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-22  4:22 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

This also adds color support to format_decoration()

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 log-tree.c                       | 59 ++++++++++++++++++++++++----------------
 log-tree.h                       |  3 ++
 pretty.c                         | 19 +------------
 t/t4207-log-decoration-colors.sh |  8 +++---
 4 files changed, 44 insertions(+), 45 deletions(-)

diff --git a/log-tree.c b/log-tree.c
index c894930..19c54dc 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -174,36 +174,50 @@ static void show_children(struct rev_info *opt, struct commit *commit, int abbre
 	}
 }
 
-void show_decorations(struct rev_info *opt, struct commit *commit)
+void format_decoration(struct strbuf *sb,
+		       const struct commit *commit,
+		       int use_color)
 {
-	const char *prefix;
-	struct name_decoration *decoration;
+	const char *prefix = " (";
+	struct name_decoration *d;
 	const char *color_commit =
-		diff_get_color_opt(&opt->diffopt, DIFF_COMMIT);
+		diff_get_color(use_color, DIFF_COMMIT);
 	const char *color_reset =
-		decorate_get_color_opt(&opt->diffopt, DECORATION_NONE);
+		decorate_get_color(use_color, DECORATION_NONE);
+
+	load_ref_decorations(DECORATE_SHORT_REFS);
+	d = lookup_decoration(&name_decoration, &commit->object);
+	if (!d)
+		return;
+	strbuf_addstr(sb, color_commit);
+	while (d) {
+		strbuf_addstr(sb, prefix);
+		strbuf_addstr(sb, decorate_get_color(use_color, d->type));
+		if (d->type == DECORATION_REF_TAG)
+			strbuf_addstr(sb, "tag: ");
+		strbuf_addstr(sb, d->name);
+		strbuf_addstr(sb, color_reset);
+		strbuf_addstr(sb, color_commit);
+		prefix = ", ";
+		d = d->next;
+	}
+	if (prefix[0] == ',') {
+		strbuf_addch(sb, ')');
+		strbuf_addstr(sb, color_reset);
+	}
+}
+
+void show_decorations(struct rev_info *opt, struct commit *commit)
+{
+	struct strbuf sb = STRBUF_INIT;
 
 	if (opt->show_source && commit->util)
 		printf("\t%s", (char *) commit->util);
 	if (!opt->show_decorations)
 		return;
-	decoration = lookup_decoration(&name_decoration, &commit->object);
-	if (!decoration)
-		return;
-	prefix = " (";
-	while (decoration) {
-		printf("%s", prefix);
-		fputs(decorate_get_color_opt(&opt->diffopt, decoration->type),
-		      stdout);
-		if (decoration->type == DECORATION_REF_TAG)
-			fputs("tag: ", stdout);
-		printf("%s", decoration->name);
-		fputs(color_reset, stdout);
-		fputs(color_commit, stdout);
-		prefix = ", ";
-		decoration = decoration->next;
-	}
-	putchar(')');
+	format_decoration(&sb, commit, opt->diffopt.use_color);
+	fputs(sb.buf, stdout);
+	strbuf_release(&sb);
 }
 
 /*
@@ -617,7 +631,6 @@ void show_log(struct rev_info *opt)
 			       find_unique_abbrev(parent->object.sha1,
 						  abbrev_commit));
 		show_decorations(opt, commit);
-		printf("%s", diff_get_color_opt(&opt->diffopt, DIFF_RESET));
 		if (opt->commit_format == CMIT_FMT_ONELINE) {
 			putchar(' ');
 		} else {
diff --git a/log-tree.h b/log-tree.h
index f5ac238..10c2682 100644
--- a/log-tree.h
+++ b/log-tree.h
@@ -13,6 +13,9 @@ int log_tree_diff_flush(struct rev_info *);
 int log_tree_commit(struct rev_info *, struct commit *);
 int log_tree_opt_parse(struct rev_info *, const char **, int);
 void show_log(struct rev_info *opt);
+void format_decoration(struct strbuf *sb,
+		       const struct commit *commit,
+		       int use_color);
 void show_decorations(struct rev_info *opt, struct commit *commit);
 void log_write_email_headers(struct rev_info *opt, struct commit *commit,
 			     const char **subject_p,
diff --git a/pretty.c b/pretty.c
index 8b1ea9f..e910679 100644
--- a/pretty.c
+++ b/pretty.c
@@ -764,23 +764,6 @@ static void parse_commit_message(struct format_commit_context *c)
 	c->commit_message_parsed = 1;
 }
 
-static void format_decoration(struct strbuf *sb, const struct commit *commit)
-{
-	struct name_decoration *d;
-	const char *prefix = " (";
-
-	load_ref_decorations(DECORATE_SHORT_REFS);
-	d = lookup_decoration(&name_decoration, &commit->object);
-	while (d) {
-		strbuf_addstr(sb, prefix);
-		prefix = ", ";
-		strbuf_addstr(sb, d->name);
-		d = d->next;
-	}
-	if (prefix[0] == ',')
-		strbuf_addch(sb, ')');
-}
-
 static void strbuf_wrap(struct strbuf *sb, size_t pos,
 			size_t width, size_t indent1, size_t indent2)
 {
@@ -1005,7 +988,7 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
 		strbuf_addstr(sb, get_revision_mark(NULL, commit));
 		return 1;
 	case 'd':
-		format_decoration(sb, commit);
+		format_decoration(sb, commit, 0);
 		return 1;
 	case 'g':		/* reflog info */
 		switch(placeholder[1]) {
diff --git a/t/t4207-log-decoration-colors.sh b/t/t4207-log-decoration-colors.sh
index bbde31b..067f5aa 100755
--- a/t/t4207-log-decoration-colors.sh
+++ b/t/t4207-log-decoration-colors.sh
@@ -44,15 +44,15 @@ test_expect_success setup '
 '
 
 cat >expected <<EOF
-${c_commit}COMMIT_ID (${c_HEAD}HEAD${c_reset}${c_commit},\
+${c_commit}COMMIT_ID${c_commit} (${c_HEAD}HEAD${c_reset}${c_commit},\
  ${c_tag}tag: v1.0${c_reset}${c_commit},\
  ${c_tag}tag: B${c_reset}${c_commit},\
  ${c_branch}master${c_reset}${c_commit})${c_reset} B
-${c_commit}COMMIT_ID (${c_tag}tag: A1${c_reset}${c_commit},\
+${c_commit}COMMIT_ID${c_commit} (${c_tag}tag: A1${c_reset}${c_commit},\
  ${c_remoteBranch}other/master${c_reset}${c_commit})${c_reset} A1
-${c_commit}COMMIT_ID (${c_stash}refs/stash${c_reset}${c_commit})${c_reset}\
+${c_commit}COMMIT_ID${c_commit} (${c_stash}refs/stash${c_reset}${c_commit})${c_reset}\
  On master: Changes to A.t
-${c_commit}COMMIT_ID (${c_tag}tag: A${c_reset}${c_commit})${c_reset} A
+${c_commit}COMMIT_ID${c_commit} (${c_tag}tag: A${c_reset}${c_commit})${c_reset} A
 EOF
 
 # We want log to show all, but the second parent to refs/stash is irrelevant
-- 
1.7.12.1.384.g7b808e7

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 2/6] pretty: split parsing %C into a separate function
  2012-09-22  4:22 [PATCH 0/6] Advanced --oneline layout Nguyễn Thái Ngọc Duy
  2012-09-22  4:22 ` [PATCH 1/6] pretty: share code between format_decoration and show_decorations Nguyễn Thái Ngọc Duy
@ 2012-09-22  4:22 ` Nguyễn Thái Ngọc Duy
  2012-09-22  4:22 ` [PATCH 3/6] pretty: support %C(auto[,N]) to turn on coloring on next placeholder(s) Nguyễn Thái Ngọc Duy
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 21+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-22  4:22 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 pretty.c | 60 +++++++++++++++++++++++++++++++++++-------------------------
 1 file changed, 35 insertions(+), 25 deletions(-)

diff --git a/pretty.c b/pretty.c
index e910679..93c96c2 100644
--- a/pretty.c
+++ b/pretty.c
@@ -863,6 +863,40 @@ static int format_reflog_person(struct strbuf *sb,
 	return format_person_part(sb, part, ident, strlen(ident), dmode);
 }
 
+static size_t parse_color_placeholder(struct strbuf *sb,
+				      const char *placeholder,
+				      struct format_commit_context *c)
+{
+	if (placeholder[1] == '(') {
+		const char *end = strchr(placeholder + 2, ')');
+		char color[COLOR_MAXLEN];
+		if (!end)
+			return 0;
+		color_parse_mem(placeholder + 2,
+				end - (placeholder + 2),
+				"--pretty format", color);
+		strbuf_addstr(sb, color);
+		return end - placeholder + 1;
+	}
+	if (!prefixcmp(placeholder + 1, "red")) {
+		strbuf_addstr(sb, GIT_COLOR_RED);
+		return 4;
+	}
+	if (!prefixcmp(placeholder + 1, "green")) {
+		strbuf_addstr(sb, GIT_COLOR_GREEN);
+		return 6;
+	}
+	if (!prefixcmp(placeholder + 1, "blue")) {
+		strbuf_addstr(sb, GIT_COLOR_BLUE);
+		return 5;
+	}
+	if (!prefixcmp(placeholder + 1, "reset")) {
+		strbuf_addstr(sb, GIT_COLOR_RESET);
+		return 6;
+	}
+	return 0;
+}
+
 static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
 				void *context)
 {
@@ -875,31 +909,7 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
 	/* these are independent of the commit */
 	switch (placeholder[0]) {
 	case 'C':
-		if (placeholder[1] == '(') {
-			const char *end = strchr(placeholder + 2, ')');
-			char color[COLOR_MAXLEN];
-			if (!end)
-				return 0;
-			color_parse_mem(placeholder + 2,
-					end - (placeholder + 2),
-					"--pretty format", color);
-			strbuf_addstr(sb, color);
-			return end - placeholder + 1;
-		}
-		if (!prefixcmp(placeholder + 1, "red")) {
-			strbuf_addstr(sb, GIT_COLOR_RED);
-			return 4;
-		} else if (!prefixcmp(placeholder + 1, "green")) {
-			strbuf_addstr(sb, GIT_COLOR_GREEN);
-			return 6;
-		} else if (!prefixcmp(placeholder + 1, "blue")) {
-			strbuf_addstr(sb, GIT_COLOR_BLUE);
-			return 5;
-		} else if (!prefixcmp(placeholder + 1, "reset")) {
-			strbuf_addstr(sb, GIT_COLOR_RESET);
-			return 6;
-		} else
-			return 0;
+		return parse_color_placeholder(sb, placeholder, c);
 	case 'n':		/* newline */
 		strbuf_addch(sb, '\n');
 		return 1;
-- 
1.7.12.1.384.g7b808e7

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 3/6] pretty: support %C(auto[,N]) to turn on coloring on next placeholder(s)
  2012-09-22  4:22 [PATCH 0/6] Advanced --oneline layout Nguyễn Thái Ngọc Duy
  2012-09-22  4:22 ` [PATCH 1/6] pretty: share code between format_decoration and show_decorations Nguyễn Thái Ngọc Duy
  2012-09-22  4:22 ` [PATCH 2/6] pretty: split parsing %C into a separate function Nguyễn Thái Ngọc Duy
@ 2012-09-22  4:22 ` Nguyễn Thái Ngọc Duy
  2012-09-22  4:22 ` [PATCH 4/6] utf8.c: move display_mode_esc_sequence_len() for use by other functions Nguyễn Thái Ngọc Duy
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 21+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-22  4:22 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/pretty-formats.txt |  1 +
 pretty.c                         | 28 +++++++++++++++++++++++++++-
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index e3d8a83..8304325 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -142,6 +142,7 @@ The placeholders are:
 - '%Cblue': switch color to blue
 - '%Creset': reset color
 - '%C(...)': color specification, as described in color.branch.* config option
+- '%C(auto[,<N>])': turn on coloring on the next placeholder (or the next N placeholders) if supported
 - '%m': left, right or boundary mark
 - '%n': newline
 - '%%': a raw '%'
diff --git a/pretty.c b/pretty.c
index 93c96c2..45fe878 100644
--- a/pretty.c
+++ b/pretty.c
@@ -630,6 +630,7 @@ struct format_commit_context {
 	} signature;
 	char *message;
 	size_t width, indent1, indent2;
+	unsigned use_color;
 
 	/* These offsets are relative to the start of the commit message. */
 	struct chunk author;
@@ -872,6 +873,24 @@ static size_t parse_color_placeholder(struct strbuf *sb,
 		char color[COLOR_MAXLEN];
 		if (!end)
 			return 0;
+		if (!prefixcmp(placeholder + 1, "(auto")) {
+			/*
+			 * use_color decreased after every
+			 * format_commit_one() so we lose one right
+			 * after parsing "%C". Which is why we add an
+			 * extra one to use_color here.
+			 */
+			if (placeholder[6] == ',') {
+				char *next;
+				int v = strtoul(placeholder + 7, &next, 10);
+				if (next == end)
+					c->use_color = v + 1;
+				else
+					return 0;
+			} else
+				c->use_color = 2;
+			return end - placeholder + 1;
+		}
 		color_parse_mem(placeholder + 2,
 				end - (placeholder + 2),
 				"--pretty format", color);
@@ -955,13 +974,17 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
 
 	switch (placeholder[0]) {
 	case 'H':		/* commit hash */
+		strbuf_addstr(sb, diff_get_color(c->use_color, DIFF_COMMIT));
 		strbuf_addstr(sb, sha1_to_hex(commit->object.sha1));
+		strbuf_addstr(sb, diff_get_color(c->use_color, DIFF_RESET));
 		return 1;
 	case 'h':		/* abbreviated commit hash */
+		strbuf_addstr(sb, diff_get_color(c->use_color, DIFF_COMMIT));
 		if (add_again(sb, &c->abbrev_commit_hash))
 			return 1;
 		strbuf_addstr(sb, find_unique_abbrev(commit->object.sha1,
 						     c->pretty_ctx->abbrev));
+		strbuf_addstr(sb, diff_get_color(c->use_color, DIFF_RESET));
 		c->abbrev_commit_hash.len = sb->len - c->abbrev_commit_hash.off;
 		return 1;
 	case 'T':		/* tree hash */
@@ -998,7 +1021,7 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
 		strbuf_addstr(sb, get_revision_mark(NULL, commit));
 		return 1;
 	case 'd':
-		format_decoration(sb, commit, 0);
+		format_decoration(sb, commit, c->use_color);
 		return 1;
 	case 'g':		/* reflog info */
 		switch(placeholder[1]) {
@@ -1101,6 +1124,7 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
 static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
 				 void *context)
 {
+	struct format_commit_context *c = context;
 	int consumed;
 	size_t orig_len;
 	enum {
@@ -1128,6 +1152,8 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
 
 	orig_len = sb->len;
 	consumed = format_commit_one(sb, placeholder, context);
+	if (c->use_color)
+		c->use_color--;
 	if (magic == NO_MAGIC)
 		return consumed;
 
-- 
1.7.12.1.384.g7b808e7

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 4/6] utf8.c: move display_mode_esc_sequence_len() for use by other functions
  2012-09-22  4:22 [PATCH 0/6] Advanced --oneline layout Nguyễn Thái Ngọc Duy
                   ` (2 preceding siblings ...)
  2012-09-22  4:22 ` [PATCH 3/6] pretty: support %C(auto[,N]) to turn on coloring on next placeholder(s) Nguyễn Thái Ngọc Duy
@ 2012-09-22  4:22 ` Nguyễn Thái Ngọc Duy
  2012-09-22  4:22 ` [PATCH 5/6] utf8.c: add utf8_strnwidth() with the ability to skip ansi sequences Nguyễn Thái Ngọc Duy
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 21+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-22  4:22 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 utf8.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/utf8.c b/utf8.c
index a544f15..18a4d9c 100644
--- a/utf8.c
+++ b/utf8.c
@@ -9,6 +9,20 @@ struct interval {
   int last;
 };
 
+static size_t display_mode_esc_sequence_len(const char *s)
+{
+	const char *p = s;
+	if (*p++ != '\033')
+		return 0;
+	if (*p++ != '[')
+		return 0;
+	while (isdigit(*p) || *p == ';')
+		p++;
+	if (*p++ != 'm')
+		return 0;
+	return p - s;
+}
+
 /* auxiliary function for binary search in interval table */
 static int bisearch(ucs_char_t ucs, const struct interval *table, int max)
 {
@@ -303,20 +317,6 @@ static void strbuf_add_indented_text(struct strbuf *buf, const char *text,
 	}
 }
 
-static size_t display_mode_esc_sequence_len(const char *s)
-{
-	const char *p = s;
-	if (*p++ != '\033')
-		return 0;
-	if (*p++ != '[')
-		return 0;
-	while (isdigit(*p) || *p == ';')
-		p++;
-	if (*p++ != 'm')
-		return 0;
-	return p - s;
-}
-
 /*
  * Wrap the text, if necessary. The variable indent is the indent for the
  * first line, indent2 is the indent for all other lines.
-- 
1.7.12.1.384.g7b808e7

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 5/6] utf8.c: add utf8_strnwidth() with the ability to skip ansi sequences
  2012-09-22  4:22 [PATCH 0/6] Advanced --oneline layout Nguyễn Thái Ngọc Duy
                   ` (3 preceding siblings ...)
  2012-09-22  4:22 ` [PATCH 4/6] utf8.c: move display_mode_esc_sequence_len() for use by other functions Nguyễn Thái Ngọc Duy
@ 2012-09-22  4:22 ` Nguyễn Thái Ngọc Duy
  2012-09-22  4:22 ` [PATCH 6/6] pretty: support padding placeholders, %< %> and %<> Nguyễn Thái Ngọc Duy
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 21+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-22  4:22 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy


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

diff --git a/utf8.c b/utf8.c
index 18a4d9c..791499e 100644
--- a/utf8.c
+++ b/utf8.c
@@ -266,18 +266,26 @@ int utf8_width(const char **start, size_t *remainder_p)
  * string, assuming that the string is utf8.  Returns strlen() instead
  * if the string does not look like a valid utf8 string.
  */
-int utf8_strwidth(const char *string)
+int utf8_strnwidth(const char *string, int len, int skip_ansi)
 {
 	int width = 0;
 	const char *orig = string;
 
-	while (1) {
-		if (!string)
-			return strlen(orig);
-		if (!*string)
-			return width;
+	if (len == -1)
+		len = strlen(string);
+	while (string && string < orig + len) {
+		int skip;
+		while (skip_ansi &&
+		       (skip = display_mode_esc_sequence_len(string)))
+			string += skip;
 		width += utf8_width(&string, NULL);
 	}
+	return string ? width : len;
+}
+
+int utf8_strwidth(const char *string)
+{
+	return utf8_strnwidth(string, -1, 0);
 }
 
 int is_utf8(const char *text)
diff --git a/utf8.h b/utf8.h
index 3c0ae76..58d5b6b 100644
--- a/utf8.h
+++ b/utf8.h
@@ -4,6 +4,7 @@
 typedef unsigned int ucs_char_t;  /* assuming 32bit int */
 
 int utf8_width(const char **start, size_t *remainder_p);
+int utf8_strnwidth(const char *string, int len, int skip_ansi);
 int utf8_strwidth(const char *string);
 int is_utf8(const char *text);
 int is_encoding_utf8(const char *name);
-- 
1.7.12.1.384.g7b808e7

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 6/6] pretty: support padding placeholders, %< %> and %<>
  2012-09-22  4:22 [PATCH 0/6] Advanced --oneline layout Nguyễn Thái Ngọc Duy
                   ` (4 preceding siblings ...)
  2012-09-22  4:22 ` [PATCH 5/6] utf8.c: add utf8_strnwidth() with the ability to skip ansi sequences Nguyễn Thái Ngọc Duy
@ 2012-09-22  4:22 ` Nguyễn Thái Ngọc Duy
  2012-09-22  4:26 ` [PATCH 7/6] pretty: trim trailing spaces due to padding Nguyễn Thái Ngọc Duy
  2012-09-23  9:10 ` [PATCH v2 0/9] Advanced --oneline layout Nguyễn Thái Ngọc Duy
  7 siblings, 0 replies; 21+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-22  4:22 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

Either %<, %> or %<> standing before a placeholder specifies how many
columns (at least as the placeholder can exceed it) it takes. Each
differs on how spaces are padded:

  %< pads on the right (aka left alignment)
  %> pads on the left (aka right alignment)
  %<> pads both ways equally (aka centered)

The (<N>) follows them, e.g. `%<(100)', to specify the number of
columns the next placeholder takes.

However, if '|' stands before (<N>), e.g. `%>|(100)', then the number
of columns is calculated so that it reaches the Nth column on screen.

TODO: %>> allows the next placeholder to eat the trailing spaces in
resulting string if it exceeds its allocated space. Maybe useful in
combination with %<(100)%s%>(40)%d, where spaces are wasted sometimes.

TODO: maybe support modifier '!' in addition to '|' above to cut
exceeding part in the next placeholder.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/pretty-formats.txt |   4 ++
 pretty.c                         | 106 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 109 insertions(+), 1 deletion(-)

diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index 8304325..7710ea8 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -149,6 +149,10 @@ The placeholders are:
 - '%x00': print a byte from a hex code
 - '%w([<w>[,<i1>[,<i2>]]])': switch line wrapping, like the -w option of
   linkgit:git-shortlog[1].
+- '%<(<N>)': make the next placeholder take at least N columns, padding spaces on the right if necessary
+- '%<|(<N>)': make the next placeholder take at least until Nth columns, padding spaces on the right if necessary
+- '%>(<N>)', '%>|(<N>)': similar to '%<(<N<)', '%<|(<N<)' respectively, but padding spaces on the left
+- '%<>(<N>)', '%<>|(<N>)': similar to '%<(<N<)', '%<|(<N<)' respectively, but padding both sides (i.e. the text is centered)
 
 NOTE: Some placeholders may depend on other options given to the
 revision traversal engine. For example, the `%g*` reflog options will
diff --git a/pretty.c b/pretty.c
index 45fe878..6662f52 100644
--- a/pretty.c
+++ b/pretty.c
@@ -617,12 +617,20 @@ struct chunk {
 	size_t len;
 };
 
+enum flush_type {
+	no_flush,
+	flush_right,
+	flush_left,
+	flush_both
+};
+
 struct format_commit_context {
 	const struct commit *commit;
 	const struct pretty_print_context *pretty_ctx;
 	unsigned commit_header_parsed:1;
 	unsigned commit_message_parsed:1;
 	unsigned commit_signature_parsed:1;
+	enum flush_type flush_type;
 	struct {
 		char *gpg_output;
 		char good_bad;
@@ -631,6 +639,7 @@ struct format_commit_context {
 	char *message;
 	size_t width, indent1, indent2;
 	unsigned use_color;
+	int padding;
 
 	/* These offsets are relative to the start of the commit message. */
 	struct chunk author;
@@ -916,6 +925,52 @@ static size_t parse_color_placeholder(struct strbuf *sb,
 	return 0;
 }
 
+static size_t parse_padding_placeholder(struct strbuf *sb,
+					const char *placeholder,
+					struct format_commit_context *c)
+{
+	const char *ch = placeholder;
+	enum flush_type flush_type;
+	int to_column = 0;
+
+	switch (*ch++) {
+	case '<':
+		if (*ch == '>') {
+			flush_type = flush_both;
+			ch++;
+		} else
+			flush_type = flush_right;
+		break;
+	case '>':
+		flush_type = flush_left;
+		break;
+	default:
+		return 0;
+	}
+
+	/* the next value means "wide enough to that column" */
+	if (*ch == '|') {
+		to_column = 1;
+		ch++;
+	}
+
+	if (*ch == '(') {
+		const char *start = ch + 1;
+		const char *end = strchr(start, ')');
+		char *next;
+		int width;
+		if (!end || end == start)
+			return 0;
+		width = strtoul(start, &next, 10);
+		if (next == start || width == 0)
+			return 0;
+		c->padding = to_column ? -width : width;
+		c->flush_type = flush_type;
+		return end - placeholder + 1;
+	}
+	return 0;
+}
+
 static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
 				void *context)
 {
@@ -966,6 +1021,10 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
 			return end - placeholder + 1;
 		} else
 			return 0;
+
+	case '<':
+	case '>':
+		return parse_padding_placeholder(sb, placeholder, c);
 	}
 
 	/* these depend on the commit */
@@ -1125,6 +1184,7 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
 				 void *context)
 {
 	struct format_commit_context *c = context;
+	struct strbuf local_sb = STRBUF_INIT;
 	int consumed;
 	size_t orig_len;
 	enum {
@@ -1151,7 +1211,51 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
 		placeholder++;
 
 	orig_len = sb->len;
-	consumed = format_commit_one(sb, placeholder, context);
+	if (c->flush_type != no_flush) {
+		int len, padding = c->padding;
+		if (padding < 0) {
+			const char *start = strrchr(sb->buf, '\n');
+			int occupied;
+			if (!start)
+				start = sb->buf;
+			occupied = utf8_strnwidth(start, -1, 1);
+			padding = (-padding) - occupied;
+		}
+		consumed = format_commit_one(&local_sb, placeholder, context);
+		len = utf8_strnwidth(local_sb.buf, -1, 1);
+		if (len >= padding)
+			/* Maybe we can trim the exceeded part */
+			strbuf_addstr(sb, local_sb.buf);
+		else {
+			int sb_len = sb->len, offset;
+			switch (c->flush_type) {
+			case flush_left:
+				offset = padding - len;
+				break;
+			case flush_right:
+				offset = 0;
+				break;
+			case flush_both:
+				offset = (padding - len) / 2;
+				break;
+			case no_flush: /* to make gcc happy */
+				break;
+			}
+			/*
+			 * we calculate padding in columns, now
+			 * convert it back to chars
+			 */
+			padding = padding - len + local_sb.len;
+			strbuf_grow(sb, padding);
+			strbuf_setlen(sb, sb_len + padding);
+			memset(sb->buf + sb_len, ' ', sb->len - sb_len);
+			memcpy(sb->buf + sb_len + offset, local_sb.buf,
+			       local_sb.len);
+		}
+		strbuf_release(&local_sb);
+		c->flush_type = no_flush;
+	} else
+		consumed = format_commit_one(sb, placeholder, context);
 	if (c->use_color)
 		c->use_color--;
 	if (magic == NO_MAGIC)
-- 
1.7.12.1.384.g7b808e7

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 7/6] pretty: trim trailing spaces due to padding
  2012-09-22  4:22 [PATCH 0/6] Advanced --oneline layout Nguyễn Thái Ngọc Duy
                   ` (5 preceding siblings ...)
  2012-09-22  4:22 ` [PATCH 6/6] pretty: support padding placeholders, %< %> and %<> Nguyễn Thái Ngọc Duy
@ 2012-09-22  4:26 ` Nguyễn Thái Ngọc Duy
  2012-09-23  9:10 ` [PATCH v2 0/9] Advanced --oneline layout Nguyễn Thái Ngọc Duy
  7 siblings, 0 replies; 21+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-22  4:26 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

TODO: should only be enabled explicitly to avoid unexpected trimming

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 And I did not remember I was in interactive rebase mode when I made
 the series. This patch is for discussion only. My screen seems to
 flash (I think) printing trailing spaces.

 pretty.c          |  1 +
 strbuf.c          | 29 +++++++++++++++++++++++++++++
 strbuf.h          |  1 +
 t/t9010-svn-fe.sh |  2 +-
 4 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/pretty.c b/pretty.c
index 6662f52..70f776b 100644
--- a/pretty.c
+++ b/pretty.c
@@ -1327,6 +1327,7 @@ void format_commit_message(const struct commit *commit,
 
 	strbuf_expand(sb, format, format_commit_item, &context);
 	rewrap_message_tail(sb, &context, 0, 0, 0);
+	delete_trailing_whitespace(sb);
 
 	if (context.message != commit->buffer)
 		free(context.message);
diff --git a/strbuf.c b/strbuf.c
index 0510f76..e001175 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -488,3 +488,32 @@ int fprintf_ln(FILE *fp, const char *fmt, ...)
 		return -1;
 	return ret + 1;
 }
+
+void delete_trailing_whitespace(struct strbuf *sb)
+{
+	char *src = sb->buf, *dst = sb->buf;
+	char *end = src + sb->len, *anchor = NULL;
+	while (src < end) {
+		if (*src == ' ') {
+			if (anchor)
+				src++;
+			else
+				anchor = src++;
+		} else if (*src == '\n') {
+			if (anchor) {
+				*dst++ = *src++;
+				anchor = NULL;
+			} else
+				*dst++ = *src++;
+		} else {
+			if (anchor) {
+				memcpy(dst, anchor, src - anchor);
+				dst += src - anchor;
+				anchor = NULL;
+			}
+			*dst++ = *src++;
+		}
+	}
+	sb->len = dst - sb->buf;
+	sb->buf[sb->len] = '\0';
+}
diff --git a/strbuf.h b/strbuf.h
index be941ee..75a8908 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -42,6 +42,7 @@ static inline void strbuf_setlen(struct strbuf *sb, size_t len) {
 extern void strbuf_trim(struct strbuf *);
 extern void strbuf_rtrim(struct strbuf *);
 extern void strbuf_ltrim(struct strbuf *);
+extern void delete_trailing_whitespace(struct strbuf *);
 extern int strbuf_cmp(const struct strbuf *, const struct strbuf *);
 
 extern struct strbuf **strbuf_split_buf(const char *, size_t,
diff --git a/t/t9010-svn-fe.sh b/t/t9010-svn-fe.sh
index b7eed24..b603e70 100755
--- a/t/t9010-svn-fe.sh
+++ b/t/t9010-svn-fe.sh
@@ -96,7 +96,7 @@ test_expect_failure PIPE 'empty revision' '
 
 test_expect_success PIPE 'empty properties' '
 	reinit_git &&
-	printf "rev <nobody, nobody@local>: %s\n" "" "" >expect &&
+	printf "rev <nobody, nobody@local>: %s\n" "" "" | sed "s/ *$//" >expect &&
 	cat >emptyprop.dump <<-\EOF &&
 	SVN-fs-dump-format-version: 3
 
-- 
1.7.12.1.384.g7b808e7

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 0/9] Advanced --oneline layout
  2012-09-22  4:22 [PATCH 0/6] Advanced --oneline layout Nguyễn Thái Ngọc Duy
                   ` (6 preceding siblings ...)
  2012-09-22  4:26 ` [PATCH 7/6] pretty: trim trailing spaces due to padding Nguyễn Thái Ngọc Duy
@ 2012-09-23  9:10 ` Nguyễn Thái Ngọc Duy
  2012-09-23  9:10   ` [PATCH 1/9] pretty: share code between format_decoration and show_decorations Nguyễn Thái Ngọc Duy
                     ` (8 more replies)
  7 siblings, 9 replies; 21+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-23  9:10 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, Nguyễn Thái Ngọc Duy

The series is now feature complete from my usage pov. The syntax may
change though. No tests yet until we agree on the syntax and semantics.
Summary:

 - %C(auto) turns on coloring for the next placeholder
 - %C(auto,N) the same on the next N placeholders
 - %<(W) makes sure the next placeholder takes W columns, left aligned
 - %>(W) like %< but right aligned
 - %><(W) like %< but centered
 - %>|(W), %<|(W), %><|(W) are similar, except that W is calculated
   to reach the Nth column on screen. (We might want %>|< instead of
   %><|)
 - %>>(W) like %>(W) but it will try to steal trailing spaces if the
   placeholder uses more than "W" columns. Very useful in "%<%>"
   combination where the last placeholder may leave a lot of spaces
   unused
 - All the above may take trunc, ltrunc, mtrunc optios in the bracket
   to truncate the result string if exceeds the given width. It
   truncates on the right, left and middle respectively.
 - No support for $COLUMNS. If you want to fit your screen, bash's
   $(()) syntax is your friend to calculate columns.
 - We might want to support %<direction>(W,N), e.g. %<(40,3), where
   the next N placeholders are grouped and aligned together as a
   single placeholder.

Show off time:

6ab07c4 pretty: support %>> that steal trailing spaces     (HEAD, lanh/prettier) Nguyễn..gọc Duy
ee1c10e pretty: support truncating in %>, %< and %><                             Nguyễn..gọc Duy
77aefae pretty: support padding placeholders, %< %> and %><                      Nguyễn..gọc Duy
8f81f6b pretty: two phase conversion for non utf-8 commits                       Nguyễn..gọc Duy
c3f1243 utf8.c: add utf8_strnwidth() with the ability to skip ansi sequences     Nguyễn..gọc Duy
1a4e9bb utf8.c: move display_mode_esc_sequence_len() for use by other functions  Nguyễn..gọc Duy
99aa0c2 pretty: support %C(auto[,N]) to turn on coloring on next placeholder(s)  Nguyễn..gọc Duy
1feaab6 pretty: split parsing %C into a separate function                        Nguyễn..gọc Duy
b2676ac pretty: share code between format_decoration and show_decorations        Nguyễn..gọc Duy
6bdccbe graph: avoid infinite loop in graph_show_commit()                        Nguyễn..gọc Duy
16eed7c Merge branch 'mh/fetch-filter-refs'                      (origin/master)  Junio C Hamano

Produced with "%C(auto,99)%h %<|(80,trunc)%s%>>|(80)%d%>(15,mtrunc)% an"

Nguyễn Thái Ngọc Duy (9):
  pretty: share code between format_decoration and show_decorations
  pretty: split parsing %C into a separate function
  pretty: support %C(auto[,N]) to turn on coloring on next placeholder(s)
  utf8.c: move display_mode_esc_sequence_len() for use by other functions
  utf8.c: add utf8_strnwidth() with the ability to skip ansi sequences
  pretty: two phase conversion for non utf-8 commits
  pretty: support padding placeholders, %< %> and %><
  pretty: support truncating in %>, %< and %><
  pretty: support %>> that steal trailing spaces

 Documentation/pretty-formats.txt |   7 +
 log-tree.c                       |  60 ++++---
 log-tree.h                       |   3 +
 pretty.c                         | 327 ++++++++++++++++++++++++++++++++-------
 t/t4207-log-decoration-colors.sh |   8 +-
 t/t6006-rev-list-format.sh       |  16 +-
 t/t6006/commit-msg.iso8859-1     |   5 +
 utf8.c                           |  94 ++++++++---
 utf8.h                           |   4 +
 9 files changed, 412 insertions(+), 112 deletions(-)
 create mode 100644 t/t6006/commit-msg.iso8859-1

-- 
1.7.12.1.406.g6ab07c4

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 1/9] pretty: share code between format_decoration and show_decorations
  2012-09-23  9:10 ` [PATCH v2 0/9] Advanced --oneline layout Nguyễn Thái Ngọc Duy
@ 2012-09-23  9:10   ` Nguyễn Thái Ngọc Duy
  2012-09-23  9:10   ` [PATCH 2/9] pretty: split parsing %C into a separate function Nguyễn Thái Ngọc Duy
                     ` (7 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-23  9:10 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, Nguyễn Thái Ngọc Duy

This also adds color support to format_decoration()

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 log-tree.c                       | 60 +++++++++++++++++++++++++---------------
 log-tree.h                       |  3 ++
 pretty.c                         | 19 +------------
 t/t4207-log-decoration-colors.sh |  8 +++---
 4 files changed, 45 insertions(+), 45 deletions(-)

diff --git a/log-tree.c b/log-tree.c
index c894930..528cab0 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -174,36 +174,50 @@ static void show_children(struct rev_info *opt, struct commit *commit, int abbre
 	}
 }
 
-void show_decorations(struct rev_info *opt, struct commit *commit)
+void format_decoration(struct strbuf *sb,
+		       const struct commit *commit,
+		       int use_color)
 {
-	const char *prefix;
-	struct name_decoration *decoration;
+	const char *prefix = " (";
+	struct name_decoration *d;
 	const char *color_commit =
-		diff_get_color_opt(&opt->diffopt, DIFF_COMMIT);
+		diff_get_color(use_color, DIFF_COMMIT);
 	const char *color_reset =
-		decorate_get_color_opt(&opt->diffopt, DECORATION_NONE);
+		decorate_get_color(use_color, DECORATION_NONE);
+
+	load_ref_decorations(DECORATE_SHORT_REFS);
+	d = lookup_decoration(&name_decoration, &commit->object);
+	if (!d)
+		return;
+	while (d) {
+		strbuf_addstr(sb, color_commit);
+		strbuf_addstr(sb, prefix);
+		strbuf_addstr(sb, decorate_get_color(use_color, d->type));
+		if (d->type == DECORATION_REF_TAG)
+			strbuf_addstr(sb, "tag: ");
+		strbuf_addstr(sb, d->name);
+		strbuf_addstr(sb, color_reset);
+		prefix = ", ";
+		d = d->next;
+	}
+	if (prefix[0] == ',') {
+		strbuf_addstr(sb, color_commit);
+		strbuf_addch(sb, ')');
+		strbuf_addstr(sb, color_reset);
+	}
+}
+
+void show_decorations(struct rev_info *opt, struct commit *commit)
+{
+	struct strbuf sb = STRBUF_INIT;
 
 	if (opt->show_source && commit->util)
 		printf("\t%s", (char *) commit->util);
 	if (!opt->show_decorations)
 		return;
-	decoration = lookup_decoration(&name_decoration, &commit->object);
-	if (!decoration)
-		return;
-	prefix = " (";
-	while (decoration) {
-		printf("%s", prefix);
-		fputs(decorate_get_color_opt(&opt->diffopt, decoration->type),
-		      stdout);
-		if (decoration->type == DECORATION_REF_TAG)
-			fputs("tag: ", stdout);
-		printf("%s", decoration->name);
-		fputs(color_reset, stdout);
-		fputs(color_commit, stdout);
-		prefix = ", ";
-		decoration = decoration->next;
-	}
-	putchar(')');
+	format_decoration(&sb, commit, opt->diffopt.use_color);
+	fputs(sb.buf, stdout);
+	strbuf_release(&sb);
 }
 
 /*
@@ -616,8 +630,8 @@ void show_log(struct rev_info *opt)
 			printf(" (from %s)",
 			       find_unique_abbrev(parent->object.sha1,
 						  abbrev_commit));
+		fputs(diff_get_color_opt(&opt->diffopt, DIFF_RESET), stdout);
 		show_decorations(opt, commit);
-		printf("%s", diff_get_color_opt(&opt->diffopt, DIFF_RESET));
 		if (opt->commit_format == CMIT_FMT_ONELINE) {
 			putchar(' ');
 		} else {
diff --git a/log-tree.h b/log-tree.h
index f5ac238..10c2682 100644
--- a/log-tree.h
+++ b/log-tree.h
@@ -13,6 +13,9 @@ int log_tree_diff_flush(struct rev_info *);
 int log_tree_commit(struct rev_info *, struct commit *);
 int log_tree_opt_parse(struct rev_info *, const char **, int);
 void show_log(struct rev_info *opt);
+void format_decoration(struct strbuf *sb,
+		       const struct commit *commit,
+		       int use_color);
 void show_decorations(struct rev_info *opt, struct commit *commit);
 void log_write_email_headers(struct rev_info *opt, struct commit *commit,
 			     const char **subject_p,
diff --git a/pretty.c b/pretty.c
index 8b1ea9f..e910679 100644
--- a/pretty.c
+++ b/pretty.c
@@ -764,23 +764,6 @@ static void parse_commit_message(struct format_commit_context *c)
 	c->commit_message_parsed = 1;
 }
 
-static void format_decoration(struct strbuf *sb, const struct commit *commit)
-{
-	struct name_decoration *d;
-	const char *prefix = " (";
-
-	load_ref_decorations(DECORATE_SHORT_REFS);
-	d = lookup_decoration(&name_decoration, &commit->object);
-	while (d) {
-		strbuf_addstr(sb, prefix);
-		prefix = ", ";
-		strbuf_addstr(sb, d->name);
-		d = d->next;
-	}
-	if (prefix[0] == ',')
-		strbuf_addch(sb, ')');
-}
-
 static void strbuf_wrap(struct strbuf *sb, size_t pos,
 			size_t width, size_t indent1, size_t indent2)
 {
@@ -1005,7 +988,7 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
 		strbuf_addstr(sb, get_revision_mark(NULL, commit));
 		return 1;
 	case 'd':
-		format_decoration(sb, commit);
+		format_decoration(sb, commit, 0);
 		return 1;
 	case 'g':		/* reflog info */
 		switch(placeholder[1]) {
diff --git a/t/t4207-log-decoration-colors.sh b/t/t4207-log-decoration-colors.sh
index bbde31b..925f577 100755
--- a/t/t4207-log-decoration-colors.sh
+++ b/t/t4207-log-decoration-colors.sh
@@ -44,15 +44,15 @@ test_expect_success setup '
 '
 
 cat >expected <<EOF
-${c_commit}COMMIT_ID (${c_HEAD}HEAD${c_reset}${c_commit},\
+${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_HEAD}HEAD${c_reset}${c_commit},\
  ${c_tag}tag: v1.0${c_reset}${c_commit},\
  ${c_tag}tag: B${c_reset}${c_commit},\
  ${c_branch}master${c_reset}${c_commit})${c_reset} B
-${c_commit}COMMIT_ID (${c_tag}tag: A1${c_reset}${c_commit},\
+${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_tag}tag: A1${c_reset}${c_commit},\
  ${c_remoteBranch}other/master${c_reset}${c_commit})${c_reset} A1
-${c_commit}COMMIT_ID (${c_stash}refs/stash${c_reset}${c_commit})${c_reset}\
+${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_stash}refs/stash${c_reset}${c_commit})${c_reset}\
  On master: Changes to A.t
-${c_commit}COMMIT_ID (${c_tag}tag: A${c_reset}${c_commit})${c_reset} A
+${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_tag}tag: A${c_reset}${c_commit})${c_reset} A
 EOF
 
 # We want log to show all, but the second parent to refs/stash is irrelevant
-- 
1.7.12.1.406.g6ab07c4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 2/9] pretty: split parsing %C into a separate function
  2012-09-23  9:10 ` [PATCH v2 0/9] Advanced --oneline layout Nguyễn Thái Ngọc Duy
  2012-09-23  9:10   ` [PATCH 1/9] pretty: share code between format_decoration and show_decorations Nguyễn Thái Ngọc Duy
@ 2012-09-23  9:10   ` Nguyễn Thái Ngọc Duy
  2012-09-23  9:10   ` [PATCH 3/9] pretty: support %C(auto[,N]) to turn on coloring on next placeholder(s) Nguyễn Thái Ngọc Duy
                     ` (6 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-23  9:10 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, Nguyễn Thái Ngọc Duy


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 pretty.c | 60 +++++++++++++++++++++++++++++++++++-------------------------
 1 file changed, 35 insertions(+), 25 deletions(-)

diff --git a/pretty.c b/pretty.c
index e910679..93c96c2 100644
--- a/pretty.c
+++ b/pretty.c
@@ -863,6 +863,40 @@ static int format_reflog_person(struct strbuf *sb,
 	return format_person_part(sb, part, ident, strlen(ident), dmode);
 }
 
+static size_t parse_color_placeholder(struct strbuf *sb,
+				      const char *placeholder,
+				      struct format_commit_context *c)
+{
+	if (placeholder[1] == '(') {
+		const char *end = strchr(placeholder + 2, ')');
+		char color[COLOR_MAXLEN];
+		if (!end)
+			return 0;
+		color_parse_mem(placeholder + 2,
+				end - (placeholder + 2),
+				"--pretty format", color);
+		strbuf_addstr(sb, color);
+		return end - placeholder + 1;
+	}
+	if (!prefixcmp(placeholder + 1, "red")) {
+		strbuf_addstr(sb, GIT_COLOR_RED);
+		return 4;
+	}
+	if (!prefixcmp(placeholder + 1, "green")) {
+		strbuf_addstr(sb, GIT_COLOR_GREEN);
+		return 6;
+	}
+	if (!prefixcmp(placeholder + 1, "blue")) {
+		strbuf_addstr(sb, GIT_COLOR_BLUE);
+		return 5;
+	}
+	if (!prefixcmp(placeholder + 1, "reset")) {
+		strbuf_addstr(sb, GIT_COLOR_RESET);
+		return 6;
+	}
+	return 0;
+}
+
 static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
 				void *context)
 {
@@ -875,31 +909,7 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
 	/* these are independent of the commit */
 	switch (placeholder[0]) {
 	case 'C':
-		if (placeholder[1] == '(') {
-			const char *end = strchr(placeholder + 2, ')');
-			char color[COLOR_MAXLEN];
-			if (!end)
-				return 0;
-			color_parse_mem(placeholder + 2,
-					end - (placeholder + 2),
-					"--pretty format", color);
-			strbuf_addstr(sb, color);
-			return end - placeholder + 1;
-		}
-		if (!prefixcmp(placeholder + 1, "red")) {
-			strbuf_addstr(sb, GIT_COLOR_RED);
-			return 4;
-		} else if (!prefixcmp(placeholder + 1, "green")) {
-			strbuf_addstr(sb, GIT_COLOR_GREEN);
-			return 6;
-		} else if (!prefixcmp(placeholder + 1, "blue")) {
-			strbuf_addstr(sb, GIT_COLOR_BLUE);
-			return 5;
-		} else if (!prefixcmp(placeholder + 1, "reset")) {
-			strbuf_addstr(sb, GIT_COLOR_RESET);
-			return 6;
-		} else
-			return 0;
+		return parse_color_placeholder(sb, placeholder, c);
 	case 'n':		/* newline */
 		strbuf_addch(sb, '\n');
 		return 1;
-- 
1.7.12.1.406.g6ab07c4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 3/9] pretty: support %C(auto[,N]) to turn on coloring on next placeholder(s)
  2012-09-23  9:10 ` [PATCH v2 0/9] Advanced --oneline layout Nguyễn Thái Ngọc Duy
  2012-09-23  9:10   ` [PATCH 1/9] pretty: share code between format_decoration and show_decorations Nguyễn Thái Ngọc Duy
  2012-09-23  9:10   ` [PATCH 2/9] pretty: split parsing %C into a separate function Nguyễn Thái Ngọc Duy
@ 2012-09-23  9:10   ` Nguyễn Thái Ngọc Duy
  2012-09-23  9:10   ` [PATCH 4/9] utf8.c: move display_mode_esc_sequence_len() for use by other functions Nguyễn Thái Ngọc Duy
                     ` (5 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-23  9:10 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, Nguyễn Thái Ngọc Duy


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/pretty-formats.txt |  1 +
 pretty.c                         | 28 +++++++++++++++++++++++++++-
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index d9edded..c706556 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -145,6 +145,7 @@ The placeholders are:
 - '%Cblue': switch color to blue
 - '%Creset': reset color
 - '%C(...)': color specification, as described in color.branch.* config option
+- '%C(auto[,<N>])': turn on coloring on the next placeholder (or the next N placeholders) if supported
 - '%m': left, right or boundary mark
 - '%n': newline
 - '%%': a raw '%'
diff --git a/pretty.c b/pretty.c
index 93c96c2..45fe878 100644
--- a/pretty.c
+++ b/pretty.c
@@ -630,6 +630,7 @@ struct format_commit_context {
 	} signature;
 	char *message;
 	size_t width, indent1, indent2;
+	unsigned use_color;
 
 	/* These offsets are relative to the start of the commit message. */
 	struct chunk author;
@@ -872,6 +873,24 @@ static size_t parse_color_placeholder(struct strbuf *sb,
 		char color[COLOR_MAXLEN];
 		if (!end)
 			return 0;
+		if (!prefixcmp(placeholder + 1, "(auto")) {
+			/*
+			 * use_color decreased after every
+			 * format_commit_one() so we lose one right
+			 * after parsing "%C". Which is why we add an
+			 * extra one to use_color here.
+			 */
+			if (placeholder[6] == ',') {
+				char *next;
+				int v = strtoul(placeholder + 7, &next, 10);
+				if (next == end)
+					c->use_color = v + 1;
+				else
+					return 0;
+			} else
+				c->use_color = 2;
+			return end - placeholder + 1;
+		}
 		color_parse_mem(placeholder + 2,
 				end - (placeholder + 2),
 				"--pretty format", color);
@@ -955,13 +974,17 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
 
 	switch (placeholder[0]) {
 	case 'H':		/* commit hash */
+		strbuf_addstr(sb, diff_get_color(c->use_color, DIFF_COMMIT));
 		strbuf_addstr(sb, sha1_to_hex(commit->object.sha1));
+		strbuf_addstr(sb, diff_get_color(c->use_color, DIFF_RESET));
 		return 1;
 	case 'h':		/* abbreviated commit hash */
+		strbuf_addstr(sb, diff_get_color(c->use_color, DIFF_COMMIT));
 		if (add_again(sb, &c->abbrev_commit_hash))
 			return 1;
 		strbuf_addstr(sb, find_unique_abbrev(commit->object.sha1,
 						     c->pretty_ctx->abbrev));
+		strbuf_addstr(sb, diff_get_color(c->use_color, DIFF_RESET));
 		c->abbrev_commit_hash.len = sb->len - c->abbrev_commit_hash.off;
 		return 1;
 	case 'T':		/* tree hash */
@@ -998,7 +1021,7 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
 		strbuf_addstr(sb, get_revision_mark(NULL, commit));
 		return 1;
 	case 'd':
-		format_decoration(sb, commit, 0);
+		format_decoration(sb, commit, c->use_color);
 		return 1;
 	case 'g':		/* reflog info */
 		switch(placeholder[1]) {
@@ -1101,6 +1124,7 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
 static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
 				 void *context)
 {
+	struct format_commit_context *c = context;
 	int consumed;
 	size_t orig_len;
 	enum {
@@ -1128,6 +1152,8 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
 
 	orig_len = sb->len;
 	consumed = format_commit_one(sb, placeholder, context);
+	if (c->use_color)
+		c->use_color--;
 	if (magic == NO_MAGIC)
 		return consumed;
 
-- 
1.7.12.1.406.g6ab07c4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 4/9] utf8.c: move display_mode_esc_sequence_len() for use by other functions
  2012-09-23  9:10 ` [PATCH v2 0/9] Advanced --oneline layout Nguyễn Thái Ngọc Duy
                     ` (2 preceding siblings ...)
  2012-09-23  9:10   ` [PATCH 3/9] pretty: support %C(auto[,N]) to turn on coloring on next placeholder(s) Nguyễn Thái Ngọc Duy
@ 2012-09-23  9:10   ` Nguyễn Thái Ngọc Duy
  2012-09-23  9:10   ` [PATCH 5/9] utf8.c: add utf8_strnwidth() with the ability to skip ansi sequences Nguyễn Thái Ngọc Duy
                     ` (4 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-23  9:10 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, Nguyễn Thái Ngọc Duy


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 utf8.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/utf8.c b/utf8.c
index a544f15..18a4d9c 100644
--- a/utf8.c
+++ b/utf8.c
@@ -9,6 +9,20 @@ struct interval {
   int last;
 };
 
+static size_t display_mode_esc_sequence_len(const char *s)
+{
+	const char *p = s;
+	if (*p++ != '\033')
+		return 0;
+	if (*p++ != '[')
+		return 0;
+	while (isdigit(*p) || *p == ';')
+		p++;
+	if (*p++ != 'm')
+		return 0;
+	return p - s;
+}
+
 /* auxiliary function for binary search in interval table */
 static int bisearch(ucs_char_t ucs, const struct interval *table, int max)
 {
@@ -303,20 +317,6 @@ static void strbuf_add_indented_text(struct strbuf *buf, const char *text,
 	}
 }
 
-static size_t display_mode_esc_sequence_len(const char *s)
-{
-	const char *p = s;
-	if (*p++ != '\033')
-		return 0;
-	if (*p++ != '[')
-		return 0;
-	while (isdigit(*p) || *p == ';')
-		p++;
-	if (*p++ != 'm')
-		return 0;
-	return p - s;
-}
-
 /*
  * Wrap the text, if necessary. The variable indent is the indent for the
  * first line, indent2 is the indent for all other lines.
-- 
1.7.12.1.406.g6ab07c4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 5/9] utf8.c: add utf8_strnwidth() with the ability to skip ansi sequences
  2012-09-23  9:10 ` [PATCH v2 0/9] Advanced --oneline layout Nguyễn Thái Ngọc Duy
                     ` (3 preceding siblings ...)
  2012-09-23  9:10   ` [PATCH 4/9] utf8.c: move display_mode_esc_sequence_len() for use by other functions Nguyễn Thái Ngọc Duy
@ 2012-09-23  9:10   ` Nguyễn Thái Ngọc Duy
  2012-09-23  9:10   ` [PATCH 6/9] pretty: two phase conversion for non utf-8 commits Nguyễn Thái Ngọc Duy
                     ` (3 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-23  9:10 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, Nguyễn Thái Ngọc Duy


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

diff --git a/utf8.c b/utf8.c
index 18a4d9c..791499e 100644
--- a/utf8.c
+++ b/utf8.c
@@ -266,18 +266,26 @@ int utf8_width(const char **start, size_t *remainder_p)
  * string, assuming that the string is utf8.  Returns strlen() instead
  * if the string does not look like a valid utf8 string.
  */
-int utf8_strwidth(const char *string)
+int utf8_strnwidth(const char *string, int len, int skip_ansi)
 {
 	int width = 0;
 	const char *orig = string;
 
-	while (1) {
-		if (!string)
-			return strlen(orig);
-		if (!*string)
-			return width;
+	if (len == -1)
+		len = strlen(string);
+	while (string && string < orig + len) {
+		int skip;
+		while (skip_ansi &&
+		       (skip = display_mode_esc_sequence_len(string)))
+			string += skip;
 		width += utf8_width(&string, NULL);
 	}
+	return string ? width : len;
+}
+
+int utf8_strwidth(const char *string)
+{
+	return utf8_strnwidth(string, -1, 0);
 }
 
 int is_utf8(const char *text)
diff --git a/utf8.h b/utf8.h
index 3c0ae76..58d5b6b 100644
--- a/utf8.h
+++ b/utf8.h
@@ -4,6 +4,7 @@
 typedef unsigned int ucs_char_t;  /* assuming 32bit int */
 
 int utf8_width(const char **start, size_t *remainder_p);
+int utf8_strnwidth(const char *string, int len, int skip_ansi);
 int utf8_strwidth(const char *string);
 int is_utf8(const char *text);
 int is_encoding_utf8(const char *name);
-- 
1.7.12.1.406.g6ab07c4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 6/9] pretty: two phase conversion for non utf-8 commits
  2012-09-23  9:10 ` [PATCH v2 0/9] Advanced --oneline layout Nguyễn Thái Ngọc Duy
                     ` (4 preceding siblings ...)
  2012-09-23  9:10   ` [PATCH 5/9] utf8.c: add utf8_strnwidth() with the ability to skip ansi sequences Nguyễn Thái Ngọc Duy
@ 2012-09-23  9:10   ` Nguyễn Thái Ngọc Duy
  2012-09-23 13:54     ` Robin Rosenberg
  2012-09-23  9:10   ` [PATCH 7/9] pretty: support padding placeholders, %< %> and %>< Nguyễn Thái Ngọc Duy
                     ` (2 subsequent siblings)
  8 siblings, 1 reply; 21+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-23  9:10 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, Nguyễn Thái Ngọc Duy

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 5420 bytes --]

Always assume format_commit_item() takes an utf-8 string for
simplicity. If commit message is in non-utf8, or output encoding is
not, then the commit is first converted to utf-8, processed, then
output converted to output encoding.

This of course only works with encodings that are compatible with
Unicode.

This also fixes the iso8859-1 test. It's supposed to create an
iso8859-1 commit, but the commit content in t6006-rev-list-format.sh
is in UTF-8. Split the content out in a separate file (so its encoding
won't accidentally be converted) and convert it back to iso8859-1.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 pretty.c                     | 29 +++++++++++++++++++----------
 t/t6006-rev-list-format.sh   | 16 +++++-----------
 t/t6006/commit-msg.iso8859-1 |  5 +++++
 3 files changed, 29 insertions(+), 21 deletions(-)
 create mode 100644 t/t6006/commit-msg.iso8859-1

diff --git a/pretty.c b/pretty.c
index 45fe878..f3275a7 100644
--- a/pretty.c
+++ b/pretty.c
@@ -916,7 +916,8 @@ static size_t parse_color_placeholder(struct strbuf *sb,
 	return 0;
 }
 
-static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
+static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
+				const char *placeholder,
 				void *context)
 {
 	struct format_commit_context *c = context;
@@ -1121,7 +1122,8 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
 	return 0;	/* unknown placeholder */
 }
 
-static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
+static size_t format_commit_item(struct strbuf *sb, /* in UTF-8 */
+				 const char *placeholder,
 				 void *context)
 {
 	struct format_commit_context *c = context;
@@ -1205,25 +1207,32 @@ void format_commit_message(const struct commit *commit,
 	struct format_commit_context context;
 	static const char utf8[] = "UTF-8";
 	const char *output_enc = pretty_ctx->output_encoding;
+	char *enc;
 
 	memset(&context, 0, sizeof(context));
 	context.commit = commit;
 	context.pretty_ctx = pretty_ctx;
 	context.wrap_start = sb->len;
 	context.message = commit->buffer;
-	if (output_enc) {
-		char *enc = get_header(commit, "encoding");
-		if (strcmp(enc ? enc : utf8, output_enc)) {
-			context.message = logmsg_reencode(commit, output_enc);
-			if (!context.message)
-				context.message = commit->buffer;
-		}
-		free(enc);
+	enc = get_header(commit, "encoding");
+	if (enc && strcmp(utf8, enc)) {
+		context.message = reencode_string(context.message, utf8, enc);
+		if (!context.message)
+			context.message = commit->buffer;
 	}
+	free(enc);
 
 	strbuf_expand(sb, format, format_commit_item, &context);
 	rewrap_message_tail(sb, &context, 0, 0, 0);
 
+	if (output_enc && strcmp(utf8, output_enc)) {
+		char *out = reencode_string(sb->buf, output_enc, utf8);
+		if (out) {
+			int len = strlen(out);
+			strbuf_attach(sb, out, len, len + 1);
+		}
+	}
+
 	if (context.message != commit->buffer)
 		free(context.message);
 	free(context.signature.gpg_output);
diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh
index f94f0c4..cd24839 100755
--- a/t/t6006-rev-list-format.sh
+++ b/t/t6006-rev-list-format.sh
@@ -124,27 +124,21 @@ commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
 ^[[1;31;43mfoo^[[m
 EOF
 
-cat >commit-msg <<'EOF'
-Test printing of complex bodies
-
-This commit message is much longer than the others,
-and it will be encoded in iso8859-1. We should therefore
-include an iso8859 character: ¡bueno!
-EOF
+cat "$TEST_DIRECTORY/t6006/commit-msg.iso8859-1" >commit-msg
 test_expect_success 'setup complex body' '
 git config i18n.commitencoding iso8859-1 &&
   echo change2 >foo && git commit -a -F commit-msg
 '
 
 test_format complex-encoding %e <<'EOF'
-commit f58db70b055c5718631e5c61528b28b12090cdea
+commit 1ed88da4a5b5ed8c449114ac131efc62178734c3
 iso8859-1
 commit 131a310eb913d107dd3c09a65d1651175898735d
 commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
 EOF
 
 test_format complex-subject %s <<'EOF'
-commit f58db70b055c5718631e5c61528b28b12090cdea
+commit 1ed88da4a5b5ed8c449114ac131efc62178734c3
 Test printing of complex bodies
 commit 131a310eb913d107dd3c09a65d1651175898735d
 changed foo
@@ -153,7 +147,7 @@ added foo
 EOF
 
 test_format complex-body %b <<'EOF'
-commit f58db70b055c5718631e5c61528b28b12090cdea
+commit 1ed88da4a5b5ed8c449114ac131efc62178734c3
 This commit message is much longer than the others,
 and it will be encoded in iso8859-1. We should therefore
 include an iso8859 character: ¡bueno!
@@ -163,7 +157,7 @@ commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
 EOF
 
 test_expect_success '%x00 shows NUL' '
-	echo  >expect commit f58db70b055c5718631e5c61528b28b12090cdea &&
+	echo  >expect commit 1ed88da4a5b5ed8c449114ac131efc62178734c3 &&
 	echo >>expect fooQbar &&
 	git rev-list -1 --format=foo%x00bar HEAD >actual.nul &&
 	nul_to_q <actual.nul >actual &&
diff --git a/t/t6006/commit-msg.iso8859-1 b/t/t6006/commit-msg.iso8859-1
new file mode 100644
index 0000000..f8fe808
--- /dev/null
+++ b/t/t6006/commit-msg.iso8859-1
@@ -0,0 +1,5 @@
+Test printing of complex bodies
+
+This commit message is much longer than the others,
+and it will be encoded in iso8859-1. We should therefore
+include an iso8859 character: ¡bueno!
-- 
1.7.12.1.406.g6ab07c4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 7/9] pretty: support padding placeholders, %< %> and %><
  2012-09-23  9:10 ` [PATCH v2 0/9] Advanced --oneline layout Nguyễn Thái Ngọc Duy
                     ` (5 preceding siblings ...)
  2012-09-23  9:10   ` [PATCH 6/9] pretty: two phase conversion for non utf-8 commits Nguyễn Thái Ngọc Duy
@ 2012-09-23  9:10   ` Nguyễn Thái Ngọc Duy
  2012-10-24  8:25     ` Jeff King
  2012-09-23  9:10   ` [PATCH 8/9] pretty: support truncating in %>, %< " Nguyễn Thái Ngọc Duy
  2012-09-23  9:10   ` [PATCH 9/9] pretty: support %>> that steal trailing spaces Nguyễn Thái Ngọc Duy
  8 siblings, 1 reply; 21+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-23  9:10 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, Nguyễn Thái Ngọc Duy

Either %<, %> or %<> standing before a placeholder specifies how many
columns (at least as the placeholder can exceed it) it takes. Each
differs on how spaces are padded:

  %< pads on the right (aka left alignment)
  %> pads on the left (aka right alignment)
  %>< pads both ways equally (aka centered)

The (<N>) follows them, e.g. `%<(100)', to specify the number of
columns the next placeholder takes.

However, if '|' stands before (<N>), e.g. `%>|(100)', then the number
of columns is calculated so that it reaches the Nth column on screen.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/pretty-formats.txt |   4 ++
 pretty.c                         | 113 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 116 insertions(+), 1 deletion(-)

diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index c706556..49d29ab 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -152,6 +152,10 @@ The placeholders are:
 - '%x00': print a byte from a hex code
 - '%w([<w>[,<i1>[,<i2>]]])': switch line wrapping, like the -w option of
   linkgit:git-shortlog[1].
+- '%<(<N>)': make the next placeholder take at least N columns, padding spaces on the right if necessary
+- '%<|(<N>)': make the next placeholder take at least until Nth columns, padding spaces on the right if necessary
+- '%>(<N>)', '%>|(<N>)': similar to '%<(<N<)', '%<|(<N<)' respectively, but padding spaces on the left
+- '%><(<N>)', '%><|(<N>)': similar to '%<(<N<)', '%<|(<N<)' respectively, but padding both sides (i.e. the text is centered)
 
 NOTE: Some placeholders may depend on other options given to the
 revision traversal engine. For example, the `%g*` reflog options will
diff --git a/pretty.c b/pretty.c
index f3275a7..d169673 100644
--- a/pretty.c
+++ b/pretty.c
@@ -617,12 +617,20 @@ struct chunk {
 	size_t len;
 };
 
+enum flush_type {
+	no_flush,
+	flush_right,
+	flush_left,
+	flush_both
+};
+
 struct format_commit_context {
 	const struct commit *commit;
 	const struct pretty_print_context *pretty_ctx;
 	unsigned commit_header_parsed:1;
 	unsigned commit_message_parsed:1;
 	unsigned commit_signature_parsed:1;
+	enum flush_type flush_type;
 	struct {
 		char *gpg_output;
 		char good_bad;
@@ -631,6 +639,7 @@ struct format_commit_context {
 	char *message;
 	size_t width, indent1, indent2;
 	unsigned use_color;
+	int padding;
 
 	/* These offsets are relative to the start of the commit message. */
 	struct chunk author;
@@ -916,6 +925,52 @@ static size_t parse_color_placeholder(struct strbuf *sb,
 	return 0;
 }
 
+static size_t parse_padding_placeholder(struct strbuf *sb,
+					const char *placeholder,
+					struct format_commit_context *c)
+{
+	const char *ch = placeholder;
+	enum flush_type flush_type;
+	int to_column = 0;
+
+	switch (*ch++) {
+	case '<':
+		flush_type = flush_right;
+		break;
+	case '>':
+		if (*ch == '<') {
+			flush_type = flush_both;
+			ch++;
+		} else
+			flush_type = flush_left;
+		break;
+	default:
+		return 0;
+	}
+
+	/* the next value means "wide enough to that column" */
+	if (*ch == '|') {
+		to_column = 1;
+		ch++;
+	}
+
+	if (*ch == '(') {
+		const char *start = ch + 1;
+		const char *end = strchr(start, ')');
+		char *next;
+		int width;
+		if (!end || end == start)
+			return 0;
+		width = strtoul(start, &next, 10);
+		if (next == start || width == 0)
+			return 0;
+		c->padding = to_column ? -width : width;
+		c->flush_type = flush_type;
+		return end - placeholder + 1;
+	}
+	return 0;
+}
+
 static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
 				const char *placeholder,
 				void *context)
@@ -967,6 +1022,10 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
 			return end - placeholder + 1;
 		} else
 			return 0;
+
+	case '<':
+	case '>':
+		return parse_padding_placeholder(sb, placeholder, c);
 	}
 
 	/* these depend on the commit */
@@ -1122,6 +1181,55 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
 	return 0;	/* unknown placeholder */
 }
 
+static size_t format_and_pad_commit(struct strbuf *sb, /* in UTF-8 */
+				    const char *placeholder,
+				    struct format_commit_context *c)
+{
+	struct strbuf local_sb = STRBUF_INIT;
+	int consumed, len, padding = c->padding;
+	if (padding < 0) {
+		const char *start = strrchr(sb->buf, '\n');
+		int occupied;
+		if (!start)
+			start = sb->buf;
+		occupied = utf8_strnwidth(start, -1, 1);
+		padding = (-padding) - occupied;
+	}
+	consumed = format_commit_one(&local_sb, placeholder, c);
+	len = utf8_strnwidth(local_sb.buf, -1, 1);
+	if (len > padding)
+		strbuf_addstr(sb, local_sb.buf);
+	else {
+		int sb_len = sb->len, offset;
+		switch (c->flush_type) {
+		case flush_left:
+			offset = padding - len;
+			break;
+		case flush_right:
+			offset = 0;
+			break;
+		case flush_both:
+			offset = (padding - len) / 2;
+			break;
+		case no_flush: /* to make gcc happy */
+			break;
+		}
+		/*
+		 * we calculate padding in columns, now
+		 * convert it back to chars
+		 */
+		padding = padding - len + local_sb.len;
+		strbuf_grow(sb, padding);
+		strbuf_setlen(sb, sb_len + padding);
+		memset(sb->buf + sb_len, ' ', sb->len - sb_len);
+		memcpy(sb->buf + sb_len + offset, local_sb.buf,
+		       local_sb.len);
+	}
+	strbuf_release(&local_sb);
+	c->flush_type = no_flush;
+	return consumed;
+}
+
 static size_t format_commit_item(struct strbuf *sb, /* in UTF-8 */
 				 const char *placeholder,
 				 void *context)
@@ -1153,7 +1261,10 @@ static size_t format_commit_item(struct strbuf *sb, /* in UTF-8 */
 		placeholder++;
 
 	orig_len = sb->len;
-	consumed = format_commit_one(sb, placeholder, context);
+	if (c->flush_type != no_flush)
+		consumed = format_and_pad_commit(sb, placeholder, context);
+	else
+		consumed = format_commit_one(sb, placeholder, context);
 	if (c->use_color)
 		c->use_color--;
 	if (magic == NO_MAGIC)
-- 
1.7.12.1.406.g6ab07c4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 8/9] pretty: support truncating in %>, %< and %><
  2012-09-23  9:10 ` [PATCH v2 0/9] Advanced --oneline layout Nguyễn Thái Ngọc Duy
                     ` (6 preceding siblings ...)
  2012-09-23  9:10   ` [PATCH 7/9] pretty: support padding placeholders, %< %> and %>< Nguyễn Thái Ngọc Duy
@ 2012-09-23  9:10   ` Nguyễn Thái Ngọc Duy
  2012-09-23  9:10   ` [PATCH 9/9] pretty: support %>> that steal trailing spaces Nguyễn Thái Ngọc Duy
  8 siblings, 0 replies; 21+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-23  9:10 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, Nguyễn Thái Ngọc Duy

%>(N,trunc) truncates the righ part after N columns and replace the
last two letters with "..". ltrunc does the same on the left. mtrunc
cuts the middle out.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/pretty-formats.txt |  2 +-
 pretty.c                         | 51 +++++++++++++++++++++++++++++++++++++---
 utf8.c                           | 46 ++++++++++++++++++++++++++++++++++++
 utf8.h                           |  2 ++
 4 files changed, 97 insertions(+), 4 deletions(-)

diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index 49d29ab..3f056dc 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -152,7 +152,7 @@ The placeholders are:
 - '%x00': print a byte from a hex code
 - '%w([<w>[,<i1>[,<i2>]]])': switch line wrapping, like the -w option of
   linkgit:git-shortlog[1].
-- '%<(<N>)': make the next placeholder take at least N columns, padding spaces on the right if necessary
+- '%<(<N>[,trunc|ltrunc|mtrunc])': make the next placeholder take at least N columns, padding spaces on the right if necessary
 - '%<|(<N>)': make the next placeholder take at least until Nth columns, padding spaces on the right if necessary
 - '%>(<N>)', '%>|(<N>)': similar to '%<(<N<)', '%<|(<N<)' respectively, but padding spaces on the left
 - '%><(<N>)', '%><|(<N>)': similar to '%<(<N<)', '%<|(<N<)' respectively, but padding both sides (i.e. the text is centered)
diff --git a/pretty.c b/pretty.c
index d169673..673193e 100644
--- a/pretty.c
+++ b/pretty.c
@@ -624,6 +624,13 @@ enum flush_type {
 	flush_both
 };
 
+enum trunc_type {
+	trunc_none,
+	trunc_left,
+	trunc_middle,
+	trunc_right
+};
+
 struct format_commit_context {
 	const struct commit *commit;
 	const struct pretty_print_context *pretty_ctx;
@@ -631,6 +638,7 @@ struct format_commit_context {
 	unsigned commit_message_parsed:1;
 	unsigned commit_signature_parsed:1;
 	enum flush_type flush_type;
+	enum trunc_type truncate;
 	struct {
 		char *gpg_output;
 		char good_bad;
@@ -956,7 +964,7 @@ static size_t parse_padding_placeholder(struct strbuf *sb,
 
 	if (*ch == '(') {
 		const char *start = ch + 1;
-		const char *end = strchr(start, ')');
+		const char *end = start + strcspn(start, ",)");
 		char *next;
 		int width;
 		if (!end || end == start)
@@ -966,6 +974,23 @@ static size_t parse_padding_placeholder(struct strbuf *sb,
 			return 0;
 		c->padding = to_column ? -width : width;
 		c->flush_type = flush_type;
+
+		if (*end == ',') {
+			start = end + 1;
+			end = strchr(start, ')');
+			if (!end || end == start)
+				return 0;
+			if (!prefixcmp(start, "trunc)"))
+				c->truncate = trunc_right;
+			else if (!prefixcmp(start, "ltrunc)"))
+				c->truncate = trunc_left;
+			else if (!prefixcmp(start, "mtrunc)"))
+				c->truncate = trunc_middle;
+			else
+				return 0;
+		} else
+			c->truncate = trunc_none;
+
 		return end - placeholder + 1;
 	}
 	return 0;
@@ -1197,9 +1222,29 @@ static size_t format_and_pad_commit(struct strbuf *sb, /* in UTF-8 */
 	}
 	consumed = format_commit_one(&local_sb, placeholder, c);
 	len = utf8_strnwidth(local_sb.buf, -1, 1);
-	if (len > padding)
+	if (len > padding) {
+		switch (c->truncate) {
+		case trunc_left:
+			strbuf_utf8_replace(&local_sb,
+					    0, len - (padding - 2),
+					    "..");
+			break;
+		case trunc_middle:
+			strbuf_utf8_replace(&local_sb,
+					    padding / 2 - 1,
+					    len - (padding - 2),
+					    "..");
+			break;
+		case trunc_right:
+			strbuf_utf8_replace(&local_sb,
+					    padding - 2, len - (padding - 2),
+					    "..");
+			break;
+		case trunc_none:
+			break;
+		}
 		strbuf_addstr(sb, local_sb.buf);
-	else {
+	} else {
 		int sb_len = sb->len, offset;
 		switch (c->flush_type) {
 		case flush_left:
diff --git a/utf8.c b/utf8.c
index 791499e..095c5ff 100644
--- a/utf8.c
+++ b/utf8.c
@@ -422,6 +422,52 @@ int strbuf_add_wrapped_bytes(struct strbuf *buf, const char *data, int len,
 	return r;
 }
 
+void strbuf_utf8_replace(struct strbuf *sb_src, int pos, int width,
+			 const char *subst)
+{
+	struct strbuf sb_dst = STRBUF_INIT;
+	char *src = sb_src->buf;
+	char *end = src + sb_src->len;
+	char *dst;
+	int w = 0, subst_len = 0;
+
+	if (subst)
+		subst_len = strlen(subst);
+	strbuf_grow(&sb_dst, sb_src->len + subst_len);
+	dst = sb_dst.buf;
+
+	while (src < end) {
+		char *old;
+		size_t n;
+
+		while ((n = display_mode_esc_sequence_len(src))) {
+			memcpy(dst, src, n);
+			src += n;
+			dst += n;
+		}
+
+		old = src;
+		n = utf8_width((const char**)&src, NULL);
+		if (!src) 	/* broken utf-8, do nothing */
+			return;
+		if (n && w >= pos && w < pos + width) {
+			if (subst) {
+				memcpy(dst, subst, subst_len);
+				dst += subst_len;
+				subst = NULL;
+			}
+			w += n;
+			continue;
+		}
+		memcpy(dst, old, src - old);
+		dst += src - old;
+		w += n;
+	}
+	strbuf_setlen(&sb_dst, dst - sb_dst.buf);
+	strbuf_attach(sb_src, strbuf_detach(&sb_dst, NULL),
+		      sb_dst.len, sb_dst.alloc);
+}
+
 int is_encoding_utf8(const char *name)
 {
 	if (!name)
diff --git a/utf8.h b/utf8.h
index 58d5b6b..0451a70 100644
--- a/utf8.h
+++ b/utf8.h
@@ -13,6 +13,8 @@ int strbuf_add_wrapped_text(struct strbuf *buf,
 		const char *text, int indent, int indent2, int width);
 int strbuf_add_wrapped_bytes(struct strbuf *buf, const char *data, int len,
 			     int indent, int indent2, int width);
+void strbuf_utf8_replace(struct strbuf *sb, int pos, int width,
+			 const char *subst);
 
 #ifndef NO_ICONV
 char *reencode_string_iconv(const char *in, size_t insz, iconv_t conv);
-- 
1.7.12.1.406.g6ab07c4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 9/9] pretty: support %>> that steal trailing spaces
  2012-09-23  9:10 ` [PATCH v2 0/9] Advanced --oneline layout Nguyễn Thái Ngọc Duy
                     ` (7 preceding siblings ...)
  2012-09-23  9:10   ` [PATCH 8/9] pretty: support truncating in %>, %< " Nguyễn Thái Ngọc Duy
@ 2012-09-23  9:10   ` Nguyễn Thái Ngọc Duy
  8 siblings, 0 replies; 21+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-23  9:10 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, Nguyễn Thái Ngọc Duy

This is pretty useful in `%<(100)%s%Cred%>(20)% an' where %s does not
use up all 100 columns and %an needs more than 20 columns. By
replacing %>(20) with %>>(20), %an can steal spaces from %s.

%>> understands escape sequences, so %Cred does not stop it from
stealing spaces in %<(100).

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/pretty-formats.txt |  4 +++-
 pretty.c                         | 35 +++++++++++++++++++++++++++++++++++
 utf8.c                           |  2 +-
 utf8.h                           |  1 +
 4 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index 3f056dc..e752da0 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -155,7 +155,9 @@ The placeholders are:
 - '%<(<N>[,trunc|ltrunc|mtrunc])': make the next placeholder take at least N columns, padding spaces on the right if necessary
 - '%<|(<N>)': make the next placeholder take at least until Nth columns, padding spaces on the right if necessary
 - '%>(<N>)', '%>|(<N>)': similar to '%<(<N<)', '%<|(<N<)' respectively, but padding spaces on the left
-- '%><(<N>)', '%><|(<N>)': similar to '%<(<N<)', '%<|(<N<)' respectively, but padding both sides (i.e. the text is centered)
+- '%>>(<N>)', '%>>|(<N>)': similar to '%>(<N<)', '%>|(<N<)' respectively, except that if the next placeholder takes more spaces than given and there are spaces on its left, use those spaces
+- '%><(<N>)', '%><|(<N>)': similar to '%
+<(<N<)', '%<|(<N<)' respectively, but padding both sides (i.e. the text is centered)
 
 NOTE: Some placeholders may depend on other options given to the
 revision traversal engine. For example, the `%g*` reflog options will
diff --git a/pretty.c b/pretty.c
index 673193e..deeacf2 100644
--- a/pretty.c
+++ b/pretty.c
@@ -621,6 +621,7 @@ enum flush_type {
 	no_flush,
 	flush_right,
 	flush_left,
+	flush_left_and_steal,
 	flush_both
 };
 
@@ -949,6 +950,9 @@ static size_t parse_padding_placeholder(struct strbuf *sb,
 		if (*ch == '<') {
 			flush_type = flush_both;
 			ch++;
+		} else if (*ch == '>') {
+			flush_type = flush_left_and_steal;
+			ch++;
 		} else
 			flush_type = flush_left;
 		break;
@@ -1222,6 +1226,36 @@ static size_t format_and_pad_commit(struct strbuf *sb, /* in UTF-8 */
 	}
 	consumed = format_commit_one(&local_sb, placeholder, c);
 	len = utf8_strnwidth(local_sb.buf, -1, 1);
+
+	if (c->flush_type == flush_left_and_steal) {
+		const char *ch = sb->buf + sb->len - 1;
+		while (len > padding && ch > sb->buf) {
+			const char *p;
+			if (*ch == ' ') {
+				ch--;
+				padding++;
+				continue;
+			}
+			/* check for trailing ansi sequences */
+			if (*ch != 'm')
+				break;
+			p = ch - 1;
+			while (ch - p < 10 && *p != '\033')
+				p--;
+			if (*p != '\033' ||
+			    ch + 1 - p != display_mode_esc_sequence_len(p))
+				break;
+			/*
+			 * got a good ansi sequence, put it back to
+			 * local_sb as we're cutting sb
+			 */
+			strbuf_insert(&local_sb, 0, p, ch + 1 - p);
+			ch = p - 1;
+		}
+		strbuf_setlen(sb, ch + 1 - sb->buf);
+		c->flush_type = flush_left;
+	}
+
 	if (len > padding) {
 		switch (c->truncate) {
 		case trunc_left:
@@ -1256,6 +1290,7 @@ static size_t format_and_pad_commit(struct strbuf *sb, /* in UTF-8 */
 		case flush_both:
 			offset = (padding - len) / 2;
 			break;
+		case flush_left_and_steal:
 		case no_flush: /* to make gcc happy */
 			break;
 		}
diff --git a/utf8.c b/utf8.c
index 095c5ff..6af288d 100644
--- a/utf8.c
+++ b/utf8.c
@@ -9,7 +9,7 @@ struct interval {
   int last;
 };
 
-static size_t display_mode_esc_sequence_len(const char *s)
+size_t display_mode_esc_sequence_len(const char *s)
 {
 	const char *p = s;
 	if (*p++ != '\033')
diff --git a/utf8.h b/utf8.h
index 0451a70..758a1ed 100644
--- a/utf8.h
+++ b/utf8.h
@@ -3,6 +3,7 @@
 
 typedef unsigned int ucs_char_t;  /* assuming 32bit int */
 
+size_t display_mode_esc_sequence_len(const char *s);
 int utf8_width(const char **start, size_t *remainder_p);
 int utf8_strnwidth(const char *string, int len, int skip_ansi);
 int utf8_strwidth(const char *string);
-- 
1.7.12.1.406.g6ab07c4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH 6/9] pretty: two phase conversion for non utf-8 commits
  2012-09-23  9:10   ` [PATCH 6/9] pretty: two phase conversion for non utf-8 commits Nguyễn Thái Ngọc Duy
@ 2012-09-23 13:54     ` Robin Rosenberg
  2012-09-24  1:21       ` Nguyen Thai Ngoc Duy
  0 siblings, 1 reply; 21+ messages in thread
From: Robin Rosenberg @ 2012-09-23 13:54 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: Junio C Hamano, Jeff King, git


A few nitpicks

----- Ursprungligt meddelande -----
> Always assume format_commit_item() takes an utf-8 string for
> simplicity. If commit message is in non-utf8, or output encoding is
> not, then the commit is first converted to utf-8, processed, then
> output converted to output encoding.
> 
> This of course only works with encodings that are compatible with
> Unicode.
Such as? Unicode was defined to encompass all knows encodings.

> -static size_t format_commit_one(struct strbuf *sb, const char
> *placeholder,
> +static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
> +				const char *placeholder,
>  				void *context)
>  {
>  	struct format_commit_context *c = context;

Which parameter does the comment apply to? I believe most conventions
nowadays include parameter documentation in the comment preceding
the function header.

[...]

> b/t/t6006/commit-msg.iso8859-1
> new file mode 100644
> index 0000000..f8fe808
> --- /dev/null
> +++ b/t/t6006/commit-msg.iso8859-1
> @@ -0,0 +1,5 @@
> +Test printing of complex bodies
> +
> +This commit message is much longer than the others,
> +and it will be encoded in iso8859-1. We should therefore
> +include an iso8859 character: �bueno!

"8859-1" to be exact. Only three 8859 encoding has the
character.

-- robin

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 6/9] pretty: two phase conversion for non utf-8 commits
  2012-09-23 13:54     ` Robin Rosenberg
@ 2012-09-24  1:21       ` Nguyen Thai Ngoc Duy
  0 siblings, 0 replies; 21+ messages in thread
From: Nguyen Thai Ngoc Duy @ 2012-09-24  1:21 UTC (permalink / raw)
  To: Robin Rosenberg; +Cc: Junio C Hamano, Jeff King, git

On Sun, Sep 23, 2012 at 8:54 PM, Robin Rosenberg
<robin.rosenberg@dewire.com> wrote:
>> This of course only works with encodings that are compatible with
>> Unicode.
> Such as? Unicode was defined to encompass all knows encodings.

Just a precaution because I have never read Unicode standard (and it
keeps getting updated, hence "incomplete")

>
>> -static size_t format_commit_one(struct strbuf *sb, const char
>> *placeholder,
>> +static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
>> +                             const char *placeholder,
>>                               void *context)
>>  {
>>       struct format_commit_context *c = context;
>
> Which parameter does the comment apply to? I believe most conventions
> nowadays include parameter documentation in the comment preceding
> the function header.

Yeah. I should have followed that.

>> b/t/t6006/commit-msg.iso8859-1
>> new file mode 100644
>> index 0000000..f8fe808
>> --- /dev/null
>> +++ b/t/t6006/commit-msg.iso8859-1
>> @@ -0,0 +1,5 @@
>> +Test printing of complex bodies
>> +
>> +This commit message is much longer than the others,
>> +and it will be encoded in iso8859-1. We should therefore
>> +include an iso8859 character: �bueno!
>
> "8859-1" to be exact. Only three 8859 encoding has the
> character.

Yep. But i'll probably need a closer look at t6006. It seems there's a
few "upside down exclamation" (not sure what it's called) in UTF-8 in
that test. I'll fix the text too.
-- 
Duy

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 7/9] pretty: support padding placeholders, %< %> and %><
  2012-09-23  9:10   ` [PATCH 7/9] pretty: support padding placeholders, %< %> and %>< Nguyễn Thái Ngọc Duy
@ 2012-10-24  8:25     ` Jeff King
  0 siblings, 0 replies; 21+ messages in thread
From: Jeff King @ 2012-10-24  8:25 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: git, Junio C Hamano

On Sun, Sep 23, 2012 at 04:10:31PM +0700, Nguyen Thai Ngoc Duy wrote:

> +	else {
> +		int sb_len = sb->len, offset;
> +		switch (c->flush_type) {
> +		case flush_left:
> +			offset = padding - len;
> +			break;
> +		case flush_right:
> +			offset = 0;
> +			break;
> +		case flush_both:
> +			offset = (padding - len) / 2;
> +			break;
> +		case no_flush: /* to make gcc happy */
> +			break;
> +		}
> +		/*
> +		 * we calculate padding in columns, now
> +		 * convert it back to chars
> +		 */
> +		padding = padding - len + local_sb.len;
> +		strbuf_grow(sb, padding);
> +		strbuf_setlen(sb, sb_len + padding);
> +		memset(sb->buf + sb_len, ' ', sb->len - sb_len);
> +		memcpy(sb->buf + sb_len + offset, local_sb.buf,
> +		       local_sb.len);
> +	}

gcc complains (rightly, I think) that offset can be used uninitialized
in the final line (looks like it is from the no_flush case). If it is a
"can never happen" case that is there to appease gcc in the switch
statement, should we drop a die("BUG: XXX") there? If so, what would the
XXX be?

-Peff

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2012-10-24  8:25 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-09-22  4:22 [PATCH 0/6] Advanced --oneline layout Nguyễn Thái Ngọc Duy
2012-09-22  4:22 ` [PATCH 1/6] pretty: share code between format_decoration and show_decorations Nguyễn Thái Ngọc Duy
2012-09-22  4:22 ` [PATCH 2/6] pretty: split parsing %C into a separate function Nguyễn Thái Ngọc Duy
2012-09-22  4:22 ` [PATCH 3/6] pretty: support %C(auto[,N]) to turn on coloring on next placeholder(s) Nguyễn Thái Ngọc Duy
2012-09-22  4:22 ` [PATCH 4/6] utf8.c: move display_mode_esc_sequence_len() for use by other functions Nguyễn Thái Ngọc Duy
2012-09-22  4:22 ` [PATCH 5/6] utf8.c: add utf8_strnwidth() with the ability to skip ansi sequences Nguyễn Thái Ngọc Duy
2012-09-22  4:22 ` [PATCH 6/6] pretty: support padding placeholders, %< %> and %<> Nguyễn Thái Ngọc Duy
2012-09-22  4:26 ` [PATCH 7/6] pretty: trim trailing spaces due to padding Nguyễn Thái Ngọc Duy
2012-09-23  9:10 ` [PATCH v2 0/9] Advanced --oneline layout Nguyễn Thái Ngọc Duy
2012-09-23  9:10   ` [PATCH 1/9] pretty: share code between format_decoration and show_decorations Nguyễn Thái Ngọc Duy
2012-09-23  9:10   ` [PATCH 2/9] pretty: split parsing %C into a separate function Nguyễn Thái Ngọc Duy
2012-09-23  9:10   ` [PATCH 3/9] pretty: support %C(auto[,N]) to turn on coloring on next placeholder(s) Nguyễn Thái Ngọc Duy
2012-09-23  9:10   ` [PATCH 4/9] utf8.c: move display_mode_esc_sequence_len() for use by other functions Nguyễn Thái Ngọc Duy
2012-09-23  9:10   ` [PATCH 5/9] utf8.c: add utf8_strnwidth() with the ability to skip ansi sequences Nguyễn Thái Ngọc Duy
2012-09-23  9:10   ` [PATCH 6/9] pretty: two phase conversion for non utf-8 commits Nguyễn Thái Ngọc Duy
2012-09-23 13:54     ` Robin Rosenberg
2012-09-24  1:21       ` Nguyen Thai Ngoc Duy
2012-09-23  9:10   ` [PATCH 7/9] pretty: support padding placeholders, %< %> and %>< Nguyễn Thái Ngọc Duy
2012-10-24  8:25     ` Jeff King
2012-09-23  9:10   ` [PATCH 8/9] pretty: support truncating in %>, %< " Nguyễn Thái Ngọc Duy
2012-09-23  9:10   ` [PATCH 9/9] pretty: support %>> that steal trailing spaces Nguyễn Thái Ngọc Duy

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

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 read-only IMAP folder(s) and NNTP newsgroup(s).