Git development
 help / color / mirror / Atom feed
From: Wincent Colaiuta <win@wincent.com>
To: git@vger.kernel.org
Cc: gitster@pobox.com, Wincent Colaiuta <win@wincent.com>
Subject: [PATCH] Teach "git add -i" to colorize whitespace errors
Date: Fri,  7 Dec 2007 13:35:10 +0100	[thread overview]
Message-ID: <1197030910-29638-1-git-send-email-win@wincent.com> (raw)

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@wincent.com>
---

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

             reply	other threads:[~2007-12-07 12:36 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-12-07 12:35 Wincent Colaiuta [this message]
2007-12-07 13:00 ` [PATCH] Teach "git add -i" to colorize whitespace errors Wincent Colaiuta

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1197030910-29638-1-git-send-email-win@wincent.com \
    --to=win@wincent.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox