Merge branch 'sb/range-diff-colors'
The color output support for recently introduced "range-diff" command got tweaked a bit. * sb/range-diff-colors: range-diff: indent special lines as context range-diff: make use of different output indicators diff.c: add --output-indicator-{new, old, context} diff.c: rewrite emit_line_0 more understandably diff.c: omit check for line prefix in emit_line_0 diff: use emit_line_0 once per line diff.c: add set_sign to emit_line_0 diff.c: reorder arguments for emit_line_ws_markup diff.c: simplify caller of emit_line_0 t3206: add color test for range-diff --dual-color test_decode_color: understand FAINT and ITALICmaint
commit
30035d1d60
106
diff.c
106
diff.c
|
@ -624,42 +624,54 @@ static void check_blank_at_eof(mmfile_t *mf1, mmfile_t *mf2,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emit_line_0(struct diff_options *o,
|
static void emit_line_0(struct diff_options *o,
|
||||||
const char *set, unsigned reverse, const char *reset,
|
const char *set_sign, const char *set, unsigned reverse, const char *reset,
|
||||||
int first, const char *line, int len)
|
int first, const char *line, int len)
|
||||||
{
|
{
|
||||||
int has_trailing_newline, has_trailing_carriage_return;
|
int has_trailing_newline, has_trailing_carriage_return;
|
||||||
int nofirst;
|
int needs_reset = 0; /* at the end of the line */
|
||||||
FILE *file = o->file;
|
FILE *file = o->file;
|
||||||
|
|
||||||
|
fputs(diff_line_prefix(o), file);
|
||||||
|
|
||||||
|
has_trailing_newline = (len > 0 && line[len-1] == '\n');
|
||||||
|
if (has_trailing_newline)
|
||||||
|
len--;
|
||||||
|
|
||||||
|
has_trailing_carriage_return = (len > 0 && line[len-1] == '\r');
|
||||||
|
if (has_trailing_carriage_return)
|
||||||
|
len--;
|
||||||
|
|
||||||
|
if (!len && !first)
|
||||||
|
goto end_of_line;
|
||||||
|
|
||||||
|
if (reverse && want_color(o->use_color)) {
|
||||||
|
fputs(GIT_COLOR_REVERSE, file);
|
||||||
|
needs_reset = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set_sign) {
|
||||||
|
fputs(set_sign, file);
|
||||||
|
needs_reset = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (first)
|
if (first)
|
||||||
fputs(diff_line_prefix(o), file);
|
fputc(first, file);
|
||||||
else if (!len)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (len == 0) {
|
if (!len)
|
||||||
has_trailing_newline = (first == '\n');
|
goto end_of_line;
|
||||||
has_trailing_carriage_return = (!has_trailing_newline &&
|
|
||||||
(first == '\r'));
|
|
||||||
nofirst = has_trailing_newline || has_trailing_carriage_return;
|
|
||||||
} else {
|
|
||||||
has_trailing_newline = (len > 0 && line[len-1] == '\n');
|
|
||||||
if (has_trailing_newline)
|
|
||||||
len--;
|
|
||||||
has_trailing_carriage_return = (len > 0 && line[len-1] == '\r');
|
|
||||||
if (has_trailing_carriage_return)
|
|
||||||
len--;
|
|
||||||
nofirst = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len || !nofirst) {
|
if (set) {
|
||||||
if (reverse && want_color(o->use_color))
|
if (set_sign && set != set_sign)
|
||||||
fputs(GIT_COLOR_REVERSE, file);
|
fputs(reset, file);
|
||||||
fputs(set, file);
|
fputs(set, file);
|
||||||
if (first && !nofirst)
|
needs_reset = 1;
|
||||||
fputc(first, file);
|
|
||||||
fwrite(line, len, 1, file);
|
|
||||||
fputs(reset, file);
|
|
||||||
}
|
}
|
||||||
|
fwrite(line, len, 1, file);
|
||||||
|
needs_reset = 1; /* 'line' may contain color codes. */
|
||||||
|
|
||||||
|
end_of_line:
|
||||||
|
if (needs_reset)
|
||||||
|
fputs(reset, file);
|
||||||
if (has_trailing_carriage_return)
|
if (has_trailing_carriage_return)
|
||||||
fputc('\r', file);
|
fputc('\r', file);
|
||||||
if (has_trailing_newline)
|
if (has_trailing_newline)
|
||||||
|
@ -669,7 +681,7 @@ static void emit_line_0(struct diff_options *o,
|
||||||
static void emit_line(struct diff_options *o, const char *set, const char *reset,
|
static void emit_line(struct diff_options *o, const char *set, const char *reset,
|
||||||
const char *line, int len)
|
const char *line, int len)
|
||||||
{
|
{
|
||||||
emit_line_0(o, set, 0, reset, line[0], line+1, len-1);
|
emit_line_0(o, set, NULL, 0, reset, 0, line, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum diff_symbol {
|
enum diff_symbol {
|
||||||
|
@ -1187,9 +1199,9 @@ static void dim_moved_lines(struct diff_options *o)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emit_line_ws_markup(struct diff_options *o,
|
static void emit_line_ws_markup(struct diff_options *o,
|
||||||
const char *set, const char *reset,
|
const char *set_sign, const char *set,
|
||||||
const char *line, int len,
|
const char *reset,
|
||||||
const char *set_sign, char sign,
|
char sign, const char *line, int len,
|
||||||
unsigned ws_rule, int blank_at_eof)
|
unsigned ws_rule, int blank_at_eof)
|
||||||
{
|
{
|
||||||
const char *ws = NULL;
|
const char *ws = NULL;
|
||||||
|
@ -1201,18 +1213,15 @@ static void emit_line_ws_markup(struct diff_options *o,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ws && !set_sign)
|
if (!ws && !set_sign)
|
||||||
emit_line_0(o, set, 0, reset, sign, line, len);
|
emit_line_0(o, set, NULL, 0, reset, sign, line, len);
|
||||||
else if (!ws) {
|
else if (!ws) {
|
||||||
/* Emit just the prefix, then the rest. */
|
emit_line_0(o, set_sign, set, !!set_sign, reset, sign, line, len);
|
||||||
emit_line_0(o, set_sign ? set_sign : set, !!set_sign, reset,
|
|
||||||
sign, "", 0);
|
|
||||||
emit_line_0(o, set, 0, reset, 0, line, len);
|
|
||||||
} else if (blank_at_eof)
|
} else if (blank_at_eof)
|
||||||
/* Blank line at EOF - paint '+' as well */
|
/* Blank line at EOF - paint '+' as well */
|
||||||
emit_line_0(o, ws, 0, reset, sign, line, len);
|
emit_line_0(o, ws, NULL, 0, reset, sign, line, len);
|
||||||
else {
|
else {
|
||||||
/* Emit just the prefix, then the rest. */
|
/* Emit just the prefix, then the rest. */
|
||||||
emit_line_0(o, set_sign ? set_sign : set, !!set_sign, reset,
|
emit_line_0(o, set_sign ? set_sign : set, NULL, !!set_sign, reset,
|
||||||
sign, "", 0);
|
sign, "", 0);
|
||||||
ws_check_emit(line, len, ws_rule,
|
ws_check_emit(line, len, ws_rule,
|
||||||
o->file, set, reset, ws);
|
o->file, set, reset, ws);
|
||||||
|
@ -1236,7 +1245,7 @@ static void emit_diff_symbol_from_struct(struct diff_options *o,
|
||||||
context = diff_get_color_opt(o, DIFF_CONTEXT);
|
context = diff_get_color_opt(o, DIFF_CONTEXT);
|
||||||
reset = diff_get_color_opt(o, DIFF_RESET);
|
reset = diff_get_color_opt(o, DIFF_RESET);
|
||||||
putc('\n', o->file);
|
putc('\n', o->file);
|
||||||
emit_line_0(o, context, 0, reset, '\\',
|
emit_line_0(o, context, NULL, 0, reset, '\\',
|
||||||
nneof, strlen(nneof));
|
nneof, strlen(nneof));
|
||||||
break;
|
break;
|
||||||
case DIFF_SYMBOL_SUBMODULE_HEADER:
|
case DIFF_SYMBOL_SUBMODULE_HEADER:
|
||||||
|
@ -1274,7 +1283,9 @@ static void emit_diff_symbol_from_struct(struct diff_options *o,
|
||||||
else if (c == '-')
|
else if (c == '-')
|
||||||
set = diff_get_color_opt(o, DIFF_FILE_OLD);
|
set = diff_get_color_opt(o, DIFF_FILE_OLD);
|
||||||
}
|
}
|
||||||
emit_line_ws_markup(o, set, reset, line, len, set_sign, ' ',
|
emit_line_ws_markup(o, set_sign, set, reset,
|
||||||
|
o->output_indicators[OUTPUT_INDICATOR_CONTEXT],
|
||||||
|
line, len,
|
||||||
flags & (DIFF_SYMBOL_CONTENT_WS_MASK), 0);
|
flags & (DIFF_SYMBOL_CONTENT_WS_MASK), 0);
|
||||||
break;
|
break;
|
||||||
case DIFF_SYMBOL_PLUS:
|
case DIFF_SYMBOL_PLUS:
|
||||||
|
@ -1317,7 +1328,9 @@ static void emit_diff_symbol_from_struct(struct diff_options *o,
|
||||||
set = diff_get_color_opt(o, DIFF_CONTEXT_BOLD);
|
set = diff_get_color_opt(o, DIFF_CONTEXT_BOLD);
|
||||||
flags &= ~DIFF_SYMBOL_CONTENT_WS_MASK;
|
flags &= ~DIFF_SYMBOL_CONTENT_WS_MASK;
|
||||||
}
|
}
|
||||||
emit_line_ws_markup(o, set, reset, line, len, set_sign, '+',
|
emit_line_ws_markup(o, set_sign, set, reset,
|
||||||
|
o->output_indicators[OUTPUT_INDICATOR_NEW],
|
||||||
|
line, len,
|
||||||
flags & DIFF_SYMBOL_CONTENT_WS_MASK,
|
flags & DIFF_SYMBOL_CONTENT_WS_MASK,
|
||||||
flags & DIFF_SYMBOL_CONTENT_BLANK_LINE_EOF);
|
flags & DIFF_SYMBOL_CONTENT_BLANK_LINE_EOF);
|
||||||
break;
|
break;
|
||||||
|
@ -1360,7 +1373,9 @@ static void emit_diff_symbol_from_struct(struct diff_options *o,
|
||||||
else
|
else
|
||||||
set = diff_get_color_opt(o, DIFF_CONTEXT_DIM);
|
set = diff_get_color_opt(o, DIFF_CONTEXT_DIM);
|
||||||
}
|
}
|
||||||
emit_line_ws_markup(o, set, reset, line, len, set_sign, '-',
|
emit_line_ws_markup(o, set_sign, set, reset,
|
||||||
|
o->output_indicators[OUTPUT_INDICATOR_OLD],
|
||||||
|
line, len,
|
||||||
flags & DIFF_SYMBOL_CONTENT_WS_MASK, 0);
|
flags & DIFF_SYMBOL_CONTENT_WS_MASK, 0);
|
||||||
break;
|
break;
|
||||||
case DIFF_SYMBOL_WORDS_PORCELAIN:
|
case DIFF_SYMBOL_WORDS_PORCELAIN:
|
||||||
|
@ -4375,6 +4390,9 @@ void diff_setup(struct diff_options *options)
|
||||||
|
|
||||||
options->file = stdout;
|
options->file = stdout;
|
||||||
|
|
||||||
|
options->output_indicators[OUTPUT_INDICATOR_NEW] = '+';
|
||||||
|
options->output_indicators[OUTPUT_INDICATOR_OLD] = '-';
|
||||||
|
options->output_indicators[OUTPUT_INDICATOR_CONTEXT] = ' ';
|
||||||
options->abbrev = DEFAULT_ABBREV;
|
options->abbrev = DEFAULT_ABBREV;
|
||||||
options->line_termination = '\n';
|
options->line_termination = '\n';
|
||||||
options->break_opt = -1;
|
options->break_opt = -1;
|
||||||
|
@ -4852,6 +4870,12 @@ int diff_opt_parse(struct diff_options *options,
|
||||||
options->output_format |= DIFF_FORMAT_DIFFSTAT;
|
options->output_format |= DIFF_FORMAT_DIFFSTAT;
|
||||||
} else if (!strcmp(arg, "--no-compact-summary"))
|
} else if (!strcmp(arg, "--no-compact-summary"))
|
||||||
options->flags.stat_with_summary = 0;
|
options->flags.stat_with_summary = 0;
|
||||||
|
else if (skip_prefix(arg, "--output-indicator-new=", &arg))
|
||||||
|
options->output_indicators[OUTPUT_INDICATOR_NEW] = arg[0];
|
||||||
|
else if (skip_prefix(arg, "--output-indicator-old=", &arg))
|
||||||
|
options->output_indicators[OUTPUT_INDICATOR_OLD] = arg[0];
|
||||||
|
else if (skip_prefix(arg, "--output-indicator-context=", &arg))
|
||||||
|
options->output_indicators[OUTPUT_INDICATOR_CONTEXT] = arg[0];
|
||||||
|
|
||||||
/* renames options */
|
/* renames options */
|
||||||
else if (starts_with(arg, "-B") ||
|
else if (starts_with(arg, "-B") ||
|
||||||
|
|
5
diff.h
5
diff.h
|
@ -194,6 +194,11 @@ struct diff_options {
|
||||||
FILE *file;
|
FILE *file;
|
||||||
int close_file;
|
int close_file;
|
||||||
|
|
||||||
|
#define OUTPUT_INDICATOR_NEW 0
|
||||||
|
#define OUTPUT_INDICATOR_OLD 1
|
||||||
|
#define OUTPUT_INDICATOR_CONTEXT 2
|
||||||
|
char output_indicators[3];
|
||||||
|
|
||||||
struct pathspec pathspec;
|
struct pathspec pathspec;
|
||||||
pathchange_fn_t pathchange;
|
pathchange_fn_t pathchange;
|
||||||
change_fn_t change;
|
change_fn_t change;
|
||||||
|
|
22
range-diff.c
22
range-diff.c
|
@ -38,6 +38,14 @@ static int read_patches(const char *range, struct string_list *list)
|
||||||
|
|
||||||
argv_array_pushl(&cp.args, "log", "--no-color", "-p", "--no-merges",
|
argv_array_pushl(&cp.args, "log", "--no-color", "-p", "--no-merges",
|
||||||
"--reverse", "--date-order", "--decorate=no",
|
"--reverse", "--date-order", "--decorate=no",
|
||||||
|
/*
|
||||||
|
* Choose indicators that are not used anywhere
|
||||||
|
* else in diffs, but still look reasonable
|
||||||
|
* (e.g. will not be confusing when debugging)
|
||||||
|
*/
|
||||||
|
"--output-indicator-new=>",
|
||||||
|
"--output-indicator-old=<",
|
||||||
|
"--output-indicator-context=#",
|
||||||
"--no-abbrev-commit", range,
|
"--no-abbrev-commit", range,
|
||||||
NULL);
|
NULL);
|
||||||
cp.out = -1;
|
cp.out = -1;
|
||||||
|
@ -82,6 +90,7 @@ static int read_patches(const char *range, struct string_list *list)
|
||||||
strbuf_addch(&buf, '\n');
|
strbuf_addch(&buf, '\n');
|
||||||
if (!util->diff_offset)
|
if (!util->diff_offset)
|
||||||
util->diff_offset = buf.len;
|
util->diff_offset = buf.len;
|
||||||
|
strbuf_addch(&buf, ' ');
|
||||||
strbuf_addbuf(&buf, &line);
|
strbuf_addbuf(&buf, &line);
|
||||||
} else if (in_header) {
|
} else if (in_header) {
|
||||||
if (starts_with(line.buf, "Author: ")) {
|
if (starts_with(line.buf, "Author: ")) {
|
||||||
|
@ -108,8 +117,19 @@ static int read_patches(const char *range, struct string_list *list)
|
||||||
* we are not interested.
|
* we are not interested.
|
||||||
*/
|
*/
|
||||||
continue;
|
continue;
|
||||||
else
|
else if (line.buf[0] == '>') {
|
||||||
|
strbuf_addch(&buf, '+');
|
||||||
|
strbuf_add(&buf, line.buf + 1, line.len - 1);
|
||||||
|
} else if (line.buf[0] == '<') {
|
||||||
|
strbuf_addch(&buf, '-');
|
||||||
|
strbuf_add(&buf, line.buf + 1, line.len - 1);
|
||||||
|
} else if (line.buf[0] == '#') {
|
||||||
|
strbuf_addch(&buf, ' ');
|
||||||
|
strbuf_add(&buf, line.buf + 1, line.len - 1);
|
||||||
|
} else {
|
||||||
|
strbuf_addch(&buf, ' ');
|
||||||
strbuf_addbuf(&buf, &line);
|
strbuf_addbuf(&buf, &line);
|
||||||
|
}
|
||||||
|
|
||||||
strbuf_addch(&buf, '\n');
|
strbuf_addch(&buf, '\n');
|
||||||
util->diffsize++;
|
util->diffsize++;
|
||||||
|
|
|
@ -133,13 +133,52 @@ test_expect_success 'changed message' '
|
||||||
Z
|
Z
|
||||||
+ Also a silly comment here!
|
+ Also a silly comment here!
|
||||||
+
|
+
|
||||||
Zdiff --git a/file b/file
|
Z diff --git a/file b/file
|
||||||
Z--- a/file
|
Z --- a/file
|
||||||
Z+++ b/file
|
Z +++ b/file
|
||||||
3: 147e64e = 3: b9cb956 s/11/B/
|
3: 147e64e = 3: b9cb956 s/11/B/
|
||||||
4: a63e992 = 4: 8add5f1 s/12/B/
|
4: a63e992 = 4: 8add5f1 s/12/B/
|
||||||
EOF
|
EOF
|
||||||
test_cmp expected actual
|
test_cmp expected actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'dual-coloring' '
|
||||||
|
sed -e "s|^:||" >expect <<-\EOF &&
|
||||||
|
:<YELLOW>1: a4b3333 = 1: f686024 s/5/A/<RESET>
|
||||||
|
:<RED>2: f51d370 <RESET><YELLOW>!<RESET><GREEN> 2: 4ab067d<RESET><YELLOW> s/4/A/<RESET>
|
||||||
|
: <REVERSE><CYAN>@@ -2,6 +2,8 @@<RESET>
|
||||||
|
: <RESET>
|
||||||
|
: s/4/A/<RESET>
|
||||||
|
: <RESET>
|
||||||
|
: <REVERSE><GREEN>+<RESET><BOLD> Also a silly comment here!<RESET>
|
||||||
|
: <REVERSE><GREEN>+<RESET>
|
||||||
|
: diff --git a/file b/file<RESET>
|
||||||
|
: --- a/file<RESET>
|
||||||
|
: +++ b/file<RESET>
|
||||||
|
:<RED>3: 0559556 <RESET><YELLOW>!<RESET><GREEN> 3: b9cb956<RESET><YELLOW> s/11/B/<RESET>
|
||||||
|
: <REVERSE><CYAN>@@ -10,7 +10,7 @@<RESET>
|
||||||
|
: 9<RESET>
|
||||||
|
: 10<RESET>
|
||||||
|
: <RED> -11<RESET>
|
||||||
|
: <REVERSE><RED>-<RESET><FAINT;GREEN>+BB<RESET>
|
||||||
|
: <REVERSE><GREEN>+<RESET><BOLD;GREEN>+B<RESET>
|
||||||
|
: 12<RESET>
|
||||||
|
: 13<RESET>
|
||||||
|
: 14<RESET>
|
||||||
|
:<RED>4: d966c5c <RESET><YELLOW>!<RESET><GREEN> 4: 8add5f1<RESET><YELLOW> s/12/B/<RESET>
|
||||||
|
: <REVERSE><CYAN>@@ -8,7 +8,7 @@<RESET>
|
||||||
|
: <CYAN> @@<RESET>
|
||||||
|
: 9<RESET>
|
||||||
|
: 10<RESET>
|
||||||
|
: <REVERSE><RED>-<RESET><FAINT> BB<RESET>
|
||||||
|
: <REVERSE><GREEN>+<RESET><BOLD> B<RESET>
|
||||||
|
: <RED> -12<RESET>
|
||||||
|
: <GREEN> +B<RESET>
|
||||||
|
: 13<RESET>
|
||||||
|
EOF
|
||||||
|
git range-diff changed...changed-message --color --dual-color >actual.raw &&
|
||||||
|
test_decode_color >actual <actual.raw &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
|
|
@ -42,6 +42,8 @@ test_decode_color () {
|
||||||
function name(n) {
|
function name(n) {
|
||||||
if (n == 0) return "RESET";
|
if (n == 0) return "RESET";
|
||||||
if (n == 1) return "BOLD";
|
if (n == 1) return "BOLD";
|
||||||
|
if (n == 2) return "FAINT";
|
||||||
|
if (n == 3) return "ITALIC";
|
||||||
if (n == 7) return "REVERSE";
|
if (n == 7) return "REVERSE";
|
||||||
if (n == 30) return "BLACK";
|
if (n == 30) return "BLACK";
|
||||||
if (n == 31) return "RED";
|
if (n == 31) return "RED";
|
||||||
|
|
Loading…
Reference in New Issue