* [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
* 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
* [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
* 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
* [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