diff-highlight: allow configurable colors

Until now, the highlighting colors were hard-coded in the
script (as "reverse" and "noreverse"), and you had to edit
the script to change them. This patch teaches diff-highlight
to read from color.diff-highlight.* to set them.

In addition, it expands the possiblities considerably by
adding two features:

  1. Old/new lines can be colored independently (so you can
     use a color scheme that complements existing line
     coloring).

  2. Normal, unhighlighted parts of the lines can be colored,
     too. Technically this can be done by separately
     configuring color.diff.old/new and matching it to your
     diff-highlight colors. But you may want a different
     look for your highlighted diffs versus your regular
     diffs.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Jeff King 2014-11-20 10:29:18 -05:00 коммит произвёл Junio C Hamano
Родитель ff40d185d2
Коммит bca45fbc1f
2 изменённых файлов: 89 добавлений и 12 удалений

Просмотреть файл

@ -58,6 +58,47 @@ following in your git configuration:
diff = diff-highlight | less
---------------------------------------------
Color Config
------------
You can configure the highlight colors and attributes using git's
config. The colors for "old" and "new" lines can be specified
independently. There are two "modes" of configuration:
1. You can specify a "highlight" color and a matching "reset" color.
This will retain any existing colors in the diff, and apply the
"highlight" and "reset" colors before and after the highlighted
portion.
2. You can specify a "normal" color and a "highlight" color. In this
case, existing colors are dropped from that line. The non-highlighted
bits of the line get the "normal" color, and the highlights get the
"highlight" color.
If no "new" colors are specified, they default to the "old" colors. If
no "old" colors are specified, the default is to reverse the foreground
and background for highlighted portions.
Examples:
---------------------------------------------
# Underline highlighted portions
[color "diff-highlight"]
oldHighlight = ul
oldReset = noul
---------------------------------------------
---------------------------------------------
# Varying background intensities
[color "diff-highlight"]
oldNormal = "black #f8cbcb"
oldHighlight = "black #ffaaaa"
newNormal = "black #cbeecb"
newHighlight = "black #aaffaa"
---------------------------------------------
Bugs
----

Просмотреть файл

@ -5,8 +5,18 @@ use strict;
# Highlight by reversing foreground and background. You could do
# other things like bold or underline if you prefer.
my $HIGHLIGHT = "\x1b[7m";
my $UNHIGHLIGHT = "\x1b[27m";
my @OLD_HIGHLIGHT = (
color_config('color.diff-highlight.oldnormal'),
color_config('color.diff-highlight.oldhighlight', "\x1b[7m"),
color_config('color.diff-highlight.oldreset', "\x1b[27m")
);
my @NEW_HIGHLIGHT = (
color_config('color.diff-highlight.newnormal', $OLD_HIGHLIGHT[0]),
color_config('color.diff-highlight.newhighlight', $OLD_HIGHLIGHT[1]),
color_config('color.diff-highlight.newreset', $OLD_HIGHLIGHT[2])
);
my $RESET = "\x1b[m";
my $COLOR = qr/\x1b\[[0-9;]*m/;
my $BORING = qr/$COLOR|\s/;
@ -53,6 +63,17 @@ show_hunk(\@removed, \@added);
exit 0;
# Ideally we would feed the default as a human-readable color to
# git-config as the fallback value. But diff-highlight does
# not otherwise depend on git at all, and there are reports
# of it being used in other settings. Let's handle our own
# fallback, which means we will work even if git can't be run.
sub color_config {
my ($key, $default) = @_;
my $s = `git config --get-color $key 2>/dev/null`;
return length($s) ? $s : $default;
}
sub show_hunk {
my ($a, $b) = @_;
@ -128,8 +149,8 @@ sub highlight_pair {
}
if (is_pair_interesting(\@a, $pa, $sa, \@b, $pb, $sb)) {
return highlight_line(\@a, $pa, $sa),
highlight_line(\@b, $pb, $sb);
return highlight_line(\@a, $pa, $sa, \@OLD_HIGHLIGHT),
highlight_line(\@b, $pb, $sb, \@NEW_HIGHLIGHT);
}
else {
return join('', @a),
@ -144,15 +165,30 @@ sub split_line {
}
sub highlight_line {
my ($line, $prefix, $suffix) = @_;
my ($line, $prefix, $suffix, $theme) = @_;
return join('',
@{$line}[0..($prefix-1)],
$HIGHLIGHT,
@{$line}[$prefix..$suffix],
$UNHIGHLIGHT,
@{$line}[($suffix+1)..$#$line]
);
my $start = join('', @{$line}[0..($prefix-1)]);
my $mid = join('', @{$line}[$prefix..$suffix]);
my $end = join('', @{$line}[($suffix+1)..$#$line]);
# If we have a "normal" color specified, then take over the whole line.
# Otherwise, we try to just manipulate the highlighted bits.
if (defined $theme->[0]) {
s/$COLOR//g for ($start, $mid, $end);
chomp $end;
return join('',
$theme->[0], $start, $RESET,
$theme->[1], $mid, $RESET,
$theme->[0], $end, $RESET,
"\n"
);
} else {
return join('',
$start,
$theme->[1], $mid, $theme->[2],
$end
);
}
}
# Pairs are interesting to highlight only if we are going to end up