3 # Highlight by reversing foreground and background. You could do
4 # other things like bold or underline if you prefer.
5 my $HIGHLIGHT = "\x1b[7m";
6 my $UNHIGHLIGHT = "\x1b[27m";
7 my $COLOR = qr/\x1b\[[0-9;]*m/;
12 # We highlight only single-line changes, so we need
13 # a 4-line window to make a decision on whether
17 if ($window[0] =~ /^$COLOR*(\@| )/ &&
18 $window[1] =~ /^$COLOR*-/ &&
19 $window[2] =~ /^$COLOR*\+/ &&
20 $window[3] !~ /^$COLOR*\+/) {
22 show_pair(shift @window, shift @window);
28 # Most of the time there is enough output to keep things streaming,
29 # but for something like "git log -Sfoo", you can get one early
30 # commit and then many seconds of nothing. We want to show
31 # that one commit as soon as possible.
33 # Since we can receive arbitrary input, there's no optimal
34 # place to flush. Flushing on a blank line is a heuristic that
35 # happens to match git-log output.
41 # Special case a single-line hunk at the end of file.
43 $window[0] =~ /^$COLOR*(\@| )/ &&
44 $window[1] =~ /^$COLOR*-/ &&
45 $window[2] =~ /^$COLOR*\+/) {
47 show_pair(shift @window, shift @window);
50 # And then flush any remaining lines.
58 my @a = split_line(shift);
59 my @b = split_line(shift);
61 # Find common prefix, taking care to skip any ansi
64 my ($pa, $pb) = (0, 0);
65 while ($pa < @a && $pb < @b) {
66 if ($a[$pa] =~ /$COLOR/) {
69 elsif ($b[$pb] =~ /$COLOR/) {
72 elsif ($a[$pa] eq $b[$pb]) {
76 elsif (!$seen_plusminus && $a[$pa] eq '-' && $b[$pb] eq '+') {
86 # Find common suffix, ignoring colors.
87 my ($sa, $sb) = ($#a, $#b);
88 while ($sa >= $pa && $sb >= $pb) {
89 if ($a[$sa] =~ /$COLOR/) {
92 elsif ($b[$sb] =~ /$COLOR/) {
95 elsif ($a[$sa] eq $b[$sb]) {
104 print highlight(\@a, $pa, $sa);
105 print highlight(\@b, $pb, $sb);
110 return map { /$COLOR/ ? $_ : (split //) }
115 my ($line, $prefix, $suffix) = @_;
118 @{$line}[0..($prefix-1)],
120 @{$line}[$prefix..$suffix],
122 @{$line}[($suffix+1)..$#$line]