Re: Understanding and improving --word-diff

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Nov 09, 2010 at 05:01:36PM -0500, Jeff King wrote:

>   2. There is a buglet in git's color emitting code. For added lines, it
>      produces "<g>+</g><g>rest of line</g>" which is annoying to parse.
>      It is fixed by the patch below:
> 
> diff --git a/diff.c b/diff.c
> index b1b0d3d..0efcdb7 100644
> --- a/diff.c
> +++ b/diff.c
> @@ -363,9 +363,9 @@ static void emit_add_line(const char *reset,
>  		emit_line_0(ecbdata->opt, ws, reset, '+', line, len);
>  	else {
>  		/* Emit just the prefix, then the rest. */
> -		emit_line_0(ecbdata->opt, set, reset, '+', "", 0);
> +		emit_line_0(ecbdata->opt, set, "", '+', "", 0);
>  		ws_check_emit(line, len, ecbdata->ws_rule,
> -			      ecbdata->opt->file, set, reset, ws);
> +			      ecbdata->opt->file, "", reset, ws);
>  	}
>  }

FYI, I looked further at this patch, and it should not be used. There
are cases where ws_check_emit will output a reset (e.g., because it has
colored some whitespace), and needs to be able to set the proper color
again. So while I think the intent of this patch is fine (to avoid
duplicate colorizing in the output), the actual implementation would
need to be much more complex.

Instead, here's an updated version of my color highlighting script that
handles this case.

With the patch I posted earlier today:

  [PATCH 2/2] allow command-specific pagers in pager.<cmd>
  http://article.gmane.org/gmane.comp.version-control.git/161624

you can do:

  git config pager.log '/path/to/diff-highlight.pl | less'

and get automagic coloring. Still, this is a bit of a hack, and there
are some funny corner cases, so something that used the internal diff
machinery would be much nicer.

-Peff

-- >8 --
#!/usr/bin/perl

use strict;
my $COLOR = qr/\x1b\[[0-9;]*m/;
my $RESET = "\x1b[0m";
my $RED = "\x1b[31m";
my $GREEN = "\x1b[32m";
my $REVERSE = "\x1b[7m";
my $UNREVERSE = "\x1b[27m";

my @window;

while (<>) {
  chomp;
  my $plain = $_;
  $plain =~ s/$COLOR//g;

  push @window, [$_, $plain];

  if ($window[0] && $window[0]->[1] =~ /^(\@| )/ &&
      $window[1] && $window[1]->[1] =~ /^-/ &&
      $window[2] && $window[2]->[1] =~ /^\+/ &&
      $window[3] && $window[3]->[1] !~ /^\+/) {
    show_line(shift @window);
    show_pair(shift @window, shift @window);
  }

  if (@window >= 4) {
    show_line(shift @window);
  }
}

if (@window == 3 &&
    $window[0] && $window[0]->[1] =~ /^(\@| )/ &&
    $window[1] && $window[1]->[1] =~ /^-/ &&
    $window[2] && $window[2]->[1] =~ /^\+/) {
  show_line(shift @window);
  show_pair(shift @window, shift @window);
}
while (@window) {
  show_line(shift @window);
}

exit 0;

sub show_line {
  my $line = shift;
  print $line->[0], "\n";
}

sub show_pair {
  my ($from, $to) = @_;
  my @from = split //, $from->[1];
  my @to = split //, $to->[1];

  my $prefix = 1;
  while ($from[$prefix] eq $to[$prefix]) {
    $prefix++;
  }
  my $suffix = 0;
  while ($from[$#from-$suffix] eq $to[$#to-$suffix]) {
    $suffix++;
  }

  print $RED, highlight($from->[1], $prefix, $suffix), $RESET, "\n";
  print $GREEN, highlight($to->[1], $prefix, $suffix), $RESET, "\n";
}

sub highlight {
  my ($line, $prefix, $suffix) = @_;
  my $end = length($line) - $suffix;
  return $line unless $end > $prefix;
  return join('',
    substr($line, 0, $prefix),
    $REVERSE,
    substr($line, $prefix, $end - $prefix),
    $UNREVERSE,
    substr($line, $end)
  );
}
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]