From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Cc: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH UI experiment] diffstat: annotate/highlight new or removed files
Date: Mon, 15 Oct 2012 21:35:49 +0700 [thread overview]
Message-ID: <1350311749-15447-1-git-send-email-pclouds@gmail.com> (raw)
diffstat does not show whether a file is added or deleted. I know
--summary does. But the problem with --summary is it makes me look for
information of a file in two places: diffstat and summary. And with a
commit that adds/removes a lot, showing both --stat --summary can be
long.
This patch adds "(new)", "(gone)" or "(new mode)" to diffstat, with
highlight, to easily catch file additions/removals. The extra text is
chosen to be short enough so that it won't take up too much space for
path names:
.gitignore | 1 +
Makefile | 3 +
t/t3070-wildmatch.sh (new) | 188 ++++++++++++++++++++++++
t/t3070/wildtest.txt (gone) | 165 ---------------------
test-wildmatch.c (new) | 14 ++
wildmatch.c | 5 +-
6 files changed, 210 insertions(+), 166 deletions(-)
I don't put creation modes in there too because most of the time it
does not matter much to me and I could look down to --summary for mode
verification. But we could put "(new+x)" for 0755 and just "(new)" for
0644. "(new mode)" then could become "(+x)", "(-x)" or something like
that.
Coloring is to me an improvement over --summary. Probably the main
point. Without it, perhaps it's not worth putting extra text to
diffstat.
Single patch for easy testing. Test suite probably breaks.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
diff.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++-----------------
diff.h | 3 ++-
utf8.c | 33 +++++++++++++++++++++++++++
utf8.h | 2 ++
4 files changed, 97 insertions(+), 22 deletions(-)
diff --git a/diff.c b/diff.c
index 35d3f07..f9217e6 100644
--- a/diff.c
+++ b/diff.c
@@ -45,6 +45,7 @@ static char diff_colors[][COLOR_MAXLEN] = {
GIT_COLOR_YELLOW, /* COMMIT */
GIT_COLOR_BG_RED, /* WHITESPACE */
GIT_COLOR_NORMAL, /* FUNCINFO */
+ GIT_COLOR_YELLOW, /* STATUSINFO */
};
static int parse_diff_color_slot(const char *var, int ofs)
@@ -65,6 +66,8 @@ static int parse_diff_color_slot(const char *var, int ofs)
return DIFF_WHITESPACE;
if (!strcasecmp(var+ofs, "func"))
return DIFF_FUNCINFO;
+ if (!strcasecmp(var+ofs, "status"))
+ return DIFF_STATUSINFO;
return -1;
}
@@ -1223,7 +1226,8 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
}
}
-static char *pprint_rename(const char *a, const char *b)
+static char *pprint_rename(struct diff_options *options,
+ const char *a, const char *b)
{
const char *old = a;
const char *new = b;
@@ -1237,7 +1241,9 @@ static char *pprint_rename(const char *a, const char *b)
if (qlen_a || qlen_b) {
quote_c_style(a, &name, NULL, 0);
- strbuf_addstr(&name, " => ");
+ strbuf_addf(&name, " %s=>%s ",
+ diff_get_color_opt(options, DIFF_STATUSINFO),
+ diff_get_color_opt(options, DIFF_RESET));
quote_c_style(b, &name, NULL, 0);
return strbuf_detach(&name, NULL);
}
@@ -1278,13 +1284,19 @@ static char *pprint_rename(const char *a, const char *b)
strbuf_grow(&name, pfx_length + a_midlen + b_midlen + sfx_length + 7);
if (pfx_length + sfx_length) {
strbuf_add(&name, a, pfx_length);
- strbuf_addch(&name, '{');
+ strbuf_addf(&name, "%s{%s",
+ diff_get_color_opt(options, DIFF_STATUSINFO),
+ diff_get_color_opt(options, DIFF_RESET));
}
strbuf_add(&name, a + pfx_length, a_midlen);
- strbuf_addstr(&name, " => ");
+ strbuf_addf(&name, " %s=>%s ",
+ diff_get_color_opt(options, DIFF_STATUSINFO),
+ diff_get_color_opt(options, DIFF_RESET));
strbuf_add(&name, b + pfx_length, b_midlen);
if (pfx_length + sfx_length) {
- strbuf_addch(&name, '}');
+ strbuf_addf(&name, "%s}%s",
+ diff_get_color_opt(options, DIFF_STATUSINFO),
+ diff_get_color_opt(options, DIFF_RESET));
strbuf_add(&name, a + len_a - sfx_length, sfx_length);
}
return strbuf_detach(&name, NULL);
@@ -1300,6 +1312,7 @@ struct diffstat_t {
unsigned is_unmerged:1;
unsigned is_binary:1;
unsigned is_renamed:1;
+ char status;
uintmax_t added, deleted;
} **files;
};
@@ -1357,7 +1370,8 @@ static int scale_linear(int it, int width, int max_change)
static void show_name(FILE *file,
const char *prefix, const char *name, int len)
{
- fprintf(file, " %s%-*s |", prefix, len, name);
+ fprintf(file, " %s%-*s |", prefix,
+ len + strlen_ansi(name), name);
}
static void show_graph(FILE *file, char ch, int cnt, const char *set, const char *reset)
@@ -1370,7 +1384,8 @@ static void show_graph(FILE *file, char ch, int cnt, const char *set, const char
fprintf(file, "%s", reset);
}
-static void fill_print_name(struct diffstat_file *file)
+static void fill_print_name(struct diff_options *options,
+ struct diffstat_file *file)
{
char *pname;
@@ -1379,14 +1394,32 @@ static void fill_print_name(struct diffstat_file *file)
if (!file->is_renamed) {
struct strbuf buf = STRBUF_INIT;
- if (quote_c_style(file->name, &buf, NULL, 0)) {
+ if (quote_c_style(file->name, &buf, NULL, 0) ||
+ file->status) {
+ const char *str = NULL;
+ switch (file->status) {
+ case DIFF_STATUS_ADDED:
+ str = "new";
+ break;
+ case DIFF_STATUS_DELETED:
+ str = "gone";
+ break;
+ case DIFF_STATUS_TYPE_CHANGED:
+ str = "new mode";
+ break;
+ }
+ if (str)
+ strbuf_addf(&buf, " (%s%s%s)",
+ diff_get_color_opt(options, DIFF_STATUSINFO),
+ str,
+ diff_get_color_opt(options, DIFF_RESET));
pname = strbuf_detach(&buf, NULL);
} else {
pname = file->name;
strbuf_release(&buf);
}
} else {
- pname = pprint_rename(file->from_name, file->name);
+ pname = pprint_rename(options, file->from_name, file->name);
}
file->print_name = pname;
}
@@ -1474,8 +1507,8 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
count++; /* not shown == room for one more */
continue;
}
- fill_print_name(file);
- len = strlen(file->print_name);
+ fill_print_name(options, file);
+ len = strlen_no_ansi(file->print_name);
if (max_len < len)
max_len = len;
@@ -1599,7 +1632,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
* "scale" the filename
*/
len = name_width;
- name_len = strlen(name);
+ name_len = strlen_no_ansi(name);
if (name_width < name_len) {
char *slash;
prefix = "...";
@@ -1737,7 +1770,7 @@ static void show_numstat(struct diffstat_t *data, struct diff_options *options)
"%"PRIuMAX"\t%"PRIuMAX"\t",
file->added, file->deleted);
if (options->line_termination) {
- fill_print_name(file);
+ fill_print_name(options, file);
if (!file->is_renamed)
write_name_quoted(file->name, options->file,
options->line_termination);
@@ -2397,13 +2430,15 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
struct diff_filespec *two,
struct diffstat_t *diffstat,
struct diff_options *o,
- int complete_rewrite)
+ int complete_rewrite,
+ char status)
{
mmfile_t mf1, mf2;
struct diffstat_file *data;
int same_contents;
data = diffstat_add(diffstat, name_a, name_b);
+ data->status = status;
if (!one || !two) {
data->is_unmerged = 1;
@@ -3118,7 +3153,8 @@ static void run_diffstat(struct diff_filepair *p, struct diff_options *o,
if (DIFF_PAIR_UNMERGED(p)) {
/* unmerged */
- builtin_diffstat(p->one->path, NULL, NULL, NULL, diffstat, o, 0);
+ builtin_diffstat(p->one->path, NULL, NULL, NULL,
+ diffstat, o, 0, 0);
return;
}
@@ -3133,7 +3169,8 @@ static void run_diffstat(struct diff_filepair *p, struct diff_options *o,
if (p->status == DIFF_STATUS_MODIFIED && p->score)
complete_rewrite = 1;
- builtin_diffstat(name, other, p->one, p->two, diffstat, o, complete_rewrite);
+ builtin_diffstat(name, other, p->one, p->two, diffstat,
+ o, complete_rewrite, p->status);
}
static void run_checkdiff(struct diff_filepair *p, struct diff_options *o)
@@ -4118,10 +4155,12 @@ static void show_mode_change(FILE *file, struct diff_filepair *p, int show_name,
}
}
-static void show_rename_copy(FILE *file, const char *renamecopy, struct diff_filepair *p,
- const char *line_prefix)
+static void show_rename_copy(FILE *file, const char *renamecopy,
+ struct diff_filepair *p,
+ const char *line_prefix,
+ struct diff_options *options)
{
- char *names = pprint_rename(p->one->path, p->two->path);
+ char *names = pprint_rename(options, p->one->path, p->two->path);
fprintf(file, " %s %s (%d%%)\n", renamecopy, names, similarity_index(p));
free(names);
@@ -4149,11 +4188,11 @@ static void diff_summary(struct diff_options *opt, struct diff_filepair *p)
break;
case DIFF_STATUS_COPIED:
fputs(line_prefix, file);
- show_rename_copy(file, "copy", p, line_prefix);
+ show_rename_copy(file, "copy", p, line_prefix, opt);
break;
case DIFF_STATUS_RENAMED:
fputs(line_prefix, file);
- show_rename_copy(file, "rename", p, line_prefix);
+ show_rename_copy(file, "rename", p, line_prefix, opt);
break;
default:
if (p->score) {
diff --git a/diff.h b/diff.h
index a658f85..c609512 100644
--- a/diff.h
+++ b/diff.h
@@ -167,7 +167,8 @@ enum color_diff {
DIFF_FILE_NEW = 5,
DIFF_COMMIT = 6,
DIFF_WHITESPACE = 7,
- DIFF_FUNCINFO = 8
+ DIFF_FUNCINFO = 8,
+ DIFF_STATUSINFO = 9
};
const char *diff_get_color(int diff_use_color, enum color_diff ix);
#define diff_get_color_opt(o, ix) \
diff --git a/utf8.c b/utf8.c
index a544f15..10823fd 100644
--- a/utf8.c
+++ b/utf8.c
@@ -317,6 +317,39 @@ static size_t display_mode_esc_sequence_len(const char *s)
return p - s;
}
+size_t strlen_no_ansi(const char *s)
+{
+ size_t len = 0;
+ for (;;) {
+ size_t skip;
+
+ while ((skip = display_mode_esc_sequence_len(s)))
+ s += skip;
+ if (!*s)
+ break;
+ len++;
+ s++;
+ }
+ return len;
+}
+
+size_t strlen_ansi(const char *s)
+{
+ size_t len = 0;
+ for (;;) {
+ size_t skip;
+
+ while ((skip = display_mode_esc_sequence_len(s))) {
+ s += skip;
+ len += skip;
+ }
+ if (!*s)
+ break;
+ s++;
+ }
+ return len;
+}
+
/*
* Wrap the text, if necessary. The variable indent is the indent for the
* first line, indent2 is the indent for all other lines.
diff --git a/utf8.h b/utf8.h
index 3c0ae76..fd4cfca 100644
--- a/utf8.h
+++ b/utf8.h
@@ -3,6 +3,8 @@
typedef unsigned int ucs_char_t; /* assuming 32bit int */
+size_t strlen_no_ansi(const char *s);
+size_t strlen_ansi(const char *s);
int utf8_width(const char **start, size_t *remainder_p);
int utf8_strwidth(const char *string);
int is_utf8(const char *text);
--
1.8.0.rc2.11.g2b79d01
next reply other threads:[~2012-10-15 14:36 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-10-15 14:35 Nguyễn Thái Ngọc Duy [this message]
2012-10-15 21:03 ` [PATCH UI experiment] diffstat: annotate/highlight new or removed files Junio C Hamano
2012-10-16 11:15 ` Nguyen Thai Ngoc Duy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1350311749-15447-1-git-send-email-pclouds@gmail.com \
--to=pclouds@gmail.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.