Skip to content

Commit

Permalink
diff-highlight: allow configurable colors
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jeff King authored and Junio C Hamano committed Nov 20, 2014
1 parent ff40d18 commit bca45fb
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 13 deletions.
41 changes: 41 additions & 0 deletions contrib/diff-highlight/README
Original file line number Diff line number Diff line change
Expand Up @@ -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
----

Expand Down
62 changes: 49 additions & 13 deletions contrib/diff-highlight/diff-highlight
Original file line number Diff line number Diff line change
Expand Up @@ -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/;

Expand Down Expand Up @@ -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) = @_;

Expand Down Expand Up @@ -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),
Expand All @@ -144,15 +165,30 @@ sub split_line {
}

sub highlight_line {
my ($line, $prefix, $suffix) = @_;

return join('',
@{$line}[0..($prefix-1)],
$HIGHLIGHT,
@{$line}[$prefix..$suffix],
$UNHIGHLIGHT,
@{$line}[($suffix+1)..$#$line]
);
my ($line, $prefix, $suffix, $theme) = @_;

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
Expand Down

0 comments on commit bca45fb

Please sign in to comment.