Skip to content

Commit bca45fb

Browse files
peffgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ff40d18 commit bca45fb

File tree

2 files changed

+90
-13
lines changed

2 files changed

+90
-13
lines changed

contrib/diff-highlight/README

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,47 @@ following in your git configuration:
5858
diff = diff-highlight | less
5959
---------------------------------------------
6060

61+
62+
Color Config
63+
------------
64+
65+
You can configure the highlight colors and attributes using git's
66+
config. The colors for "old" and "new" lines can be specified
67+
independently. There are two "modes" of configuration:
68+
69+
1. You can specify a "highlight" color and a matching "reset" color.
70+
This will retain any existing colors in the diff, and apply the
71+
"highlight" and "reset" colors before and after the highlighted
72+
portion.
73+
74+
2. You can specify a "normal" color and a "highlight" color. In this
75+
case, existing colors are dropped from that line. The non-highlighted
76+
bits of the line get the "normal" color, and the highlights get the
77+
"highlight" color.
78+
79+
If no "new" colors are specified, they default to the "old" colors. If
80+
no "old" colors are specified, the default is to reverse the foreground
81+
and background for highlighted portions.
82+
83+
Examples:
84+
85+
---------------------------------------------
86+
# Underline highlighted portions
87+
[color "diff-highlight"]
88+
oldHighlight = ul
89+
oldReset = noul
90+
---------------------------------------------
91+
92+
---------------------------------------------
93+
# Varying background intensities
94+
[color "diff-highlight"]
95+
oldNormal = "black #f8cbcb"
96+
oldHighlight = "black #ffaaaa"
97+
newNormal = "black #cbeecb"
98+
newHighlight = "black #aaffaa"
99+
---------------------------------------------
100+
101+
61102
Bugs
62103
----
63104

contrib/diff-highlight/diff-highlight

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,18 @@ use strict;
55

66
# Highlight by reversing foreground and background. You could do
77
# other things like bold or underline if you prefer.
8-
my $HIGHLIGHT = "\x1b[7m";
9-
my $UNHIGHLIGHT = "\x1b[27m";
8+
my @OLD_HIGHLIGHT = (
9+
color_config('color.diff-highlight.oldnormal'),
10+
color_config('color.diff-highlight.oldhighlight', "\x1b[7m"),
11+
color_config('color.diff-highlight.oldreset', "\x1b[27m")
12+
);
13+
my @NEW_HIGHLIGHT = (
14+
color_config('color.diff-highlight.newnormal', $OLD_HIGHLIGHT[0]),
15+
color_config('color.diff-highlight.newhighlight', $OLD_HIGHLIGHT[1]),
16+
color_config('color.diff-highlight.newreset', $OLD_HIGHLIGHT[2])
17+
);
18+
19+
my $RESET = "\x1b[m";
1020
my $COLOR = qr/\x1b\[[0-9;]*m/;
1121
my $BORING = qr/$COLOR|\s/;
1222

@@ -53,6 +63,17 @@ show_hunk(\@removed, \@added);
5363

5464
exit 0;
5565

66+
# Ideally we would feed the default as a human-readable color to
67+
# git-config as the fallback value. But diff-highlight does
68+
# not otherwise depend on git at all, and there are reports
69+
# of it being used in other settings. Let's handle our own
70+
# fallback, which means we will work even if git can't be run.
71+
sub color_config {
72+
my ($key, $default) = @_;
73+
my $s = `git config --get-color $key 2>/dev/null`;
74+
return length($s) ? $s : $default;
75+
}
76+
5677
sub show_hunk {
5778
my ($a, $b) = @_;
5879

@@ -128,8 +149,8 @@ sub highlight_pair {
128149
}
129150

130151
if (is_pair_interesting(\@a, $pa, $sa, \@b, $pb, $sb)) {
131-
return highlight_line(\@a, $pa, $sa),
132-
highlight_line(\@b, $pb, $sb);
152+
return highlight_line(\@a, $pa, $sa, \@OLD_HIGHLIGHT),
153+
highlight_line(\@b, $pb, $sb, \@NEW_HIGHLIGHT);
133154
}
134155
else {
135156
return join('', @a),
@@ -144,15 +165,30 @@ sub split_line {
144165
}
145166

146167
sub highlight_line {
147-
my ($line, $prefix, $suffix) = @_;
148-
149-
return join('',
150-
@{$line}[0..($prefix-1)],
151-
$HIGHLIGHT,
152-
@{$line}[$prefix..$suffix],
153-
$UNHIGHLIGHT,
154-
@{$line}[($suffix+1)..$#$line]
155-
);
168+
my ($line, $prefix, $suffix, $theme) = @_;
169+
170+
my $start = join('', @{$line}[0..($prefix-1)]);
171+
my $mid = join('', @{$line}[$prefix..$suffix]);
172+
my $end = join('', @{$line}[($suffix+1)..$#$line]);
173+
174+
# If we have a "normal" color specified, then take over the whole line.
175+
# Otherwise, we try to just manipulate the highlighted bits.
176+
if (defined $theme->[0]) {
177+
s/$COLOR//g for ($start, $mid, $end);
178+
chomp $end;
179+
return join('',
180+
$theme->[0], $start, $RESET,
181+
$theme->[1], $mid, $RESET,
182+
$theme->[0], $end, $RESET,
183+
"\n"
184+
);
185+
} else {
186+
return join('',
187+
$start,
188+
$theme->[1], $mid, $theme->[2],
189+
$end
190+
);
191+
}
156192
}
157193

158194
# Pairs are interesting to highlight only if we are going to end up

0 commit comments

Comments
 (0)