Rather than replicating the colorization logic of "git diff-files" we rely on "git diff-files" itself. This guarantees consistent colorization in and outside "git add -i". Seeing as speed is not a concern here (the bottleneck is how fast the user can read, not how fast "git diff-files" runs) we do this by actually running it twice, once without color and once with. In this way as the whitespace colorization provided by "git diff-files" evolves (per-path attributes, new classes of whitespace error), "git add -i" will automatically benefit from it and stay in synch. Also, by working with two sets of diff output (an uncolorized one for internal processing and a colorized one for display only) we minimize the risk of regressions because the changes required to implement this are minimally invasive. Signed-off-by: Wincent Colaiuta <win@xxxxxxxxxxx> --- This applies on top of these patches that Junio sent out yesterday: git config --get-colorbool Color support for "git-add -i" I've tested it here and it works for me but it would be nice if someone else could play with it and see if this is good. git-add--interactive.perl | 67 +++++++++++++++++++------------------------- 1 files changed, 29 insertions(+), 38 deletions(-) diff --git a/git-add--interactive.perl b/git-add--interactive.perl index 1019a72..e492fac 100755 --- a/git-add--interactive.perl +++ b/git-add--interactive.perl @@ -525,42 +525,21 @@ sub add_untracked_cmd { sub parse_diff { my ($path) = @_; my @diff = run_cmd_pipe(qw(git diff-files -p --), $path); - my (@hunk) = { TEXT => [] }; + my @colored = run_cmd_pipe(qw(git diff-files -p --color --), $path) + if $diff_use_color; + my (@hunk) = { TEXT => [], DISPLAY => [] }; - for (@diff) { - if (/^@@ /) { - push @hunk, { TEXT => [] }; + for (my $i = 0; $i < @diff; $i++) { + if ($diff[$i] =~ /^@@ /) { + push @hunk, { TEXT => [], DISPLAY => [] }; } - push @{$hunk[-1]{TEXT}}, $_; + push @{$hunk[-1]{TEXT}}, $diff[$i]; + push @{$hunk[-1]{DISPLAY}}, + $diff_use_color ? $colored[$i] : $diff[$i]; } return @hunk; } -sub colored_diff_hunk { - my ($text) = @_; - # return the text, so that it can be passed to print() - my @ret; - for (@$text) { - if (!$diff_use_color) { - push @ret, $_; - next; - } - - if (/^\+/) { - push @ret, colored($new_color, $_); - } elsif (/^\-/) { - push @ret, colored($old_color, $_); - } elsif (/^\@/) { - push @ret, colored($fraginfo_color, $_); - } elsif (/^ /) { - push @ret, colored($normal_color, $_); - } else { - push @ret, colored($metainfo_color, $_); - } - } - return @ret; -} - sub hunk_splittable { my ($text) = @_; @@ -578,7 +557,9 @@ sub parse_hunk_header { } sub split_hunk { - my ($text) = @_; + my $text = shift; + my $display = shift; + $display = $text unless $display; my @split = (); # If there are context lines in the middle of a hunk, @@ -594,16 +575,19 @@ sub split_hunk { my $i = $hunk_start - 1; my $this = +{ TEXT => [], + DISPLAY => [], OLD => $o_ofs, NEW => $n_ofs, OCNT => 0, NCNT => 0, ADDDEL => 0, POSTCTX => 0, + USE => undef, }; while (++$i < @$text) { my $line = $text->[$i]; + my $display = $display->[$i]; if ($line =~ /^ /) { if ($this->{ADDDEL} && !defined $next_hunk_start) { @@ -615,6 +599,7 @@ sub split_hunk { $next_hunk_start = $i; } push @{$this->{TEXT}}, $line; + push @{$this->{DISPLAY}}, $display; $this->{OCNT}++; $this->{NCNT}++; if (defined $next_hunk_start) { @@ -637,6 +622,7 @@ sub split_hunk { redo OUTER; } push @{$this->{TEXT}}, $line; + push @{$this->{DISPLAY}}, $display; $this->{ADDDEL}++; if ($line =~ /^-/) { $this->{OCNT}++; @@ -662,8 +648,10 @@ sub split_hunk { (($n_cnt != 1) ? ",$n_cnt" : '') . " @@\n"); unshift @{$hunk->{TEXT}}, $head; + unshift @{$hunk->{DISPLAY}}, + $use_color ? (colored $fraginfo_color, $head) : $head; } - return map { $_->{TEXT} } @split; + return @split; } sub find_last_o_ctx { @@ -794,7 +782,9 @@ sub patch_update_file { my ($ix, $num); my $path = shift; my ($head, @hunk) = parse_diff($path); - print colored_diff_hunk($head->{TEXT}); + for (@{$head->{DISPLAY}}) { + print; + } $num = scalar @hunk; $ix = 0; @@ -836,7 +826,9 @@ sub patch_update_file { if (hunk_splittable($hunk[$ix]{TEXT})) { $other .= '/s'; } - print colored_diff_hunk($hunk[$ix]{TEXT}); + for (@{$hunk[$ix]{DISPLAY}}) { + print; + } print colored $prompt_color, "Stage this hunk [y/n/a/d$other/?]? "; my $line = <STDIN>; if ($line) { @@ -889,14 +881,13 @@ sub patch_update_file { next; } elsif ($other =~ /s/ && $line =~ /^s/) { - my @split = split_hunk($hunk[$ix]{TEXT}); + my @split = split_hunk($hunk[$ix]{TEXT}, + $hunk[$ix]{DISPLAY}); if (1 < @split) { print colored $header_color, "Split into ", scalar(@split), " hunks.\n"; } - splice(@hunk, $ix, 1, - map { +{ TEXT => $_, USE => undef } } - @split); + splice (@hunk, $ix, 1, @split); $num = scalar @hunk; next; } -- 1.5.3.7.1079.gb270a-dirty - 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