git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Thomas Rast <trast@student.ethz.ch>
To: git@vger.kernel.org
Subject: [PATCH] git-add--interactive: manual hunk editing mode
Date: Fri, 23 May 2008 22:21:43 +0200	[thread overview]
Message-ID: <200805232221.45406.trast@student.ethz.ch> (raw)

Adds a new option 'e' to the 'add -p' command loop that lets you
discard or keep one hunk line at a time.  This is useful if there are
no unchanged lines in the middle of the hunk, so 's' will not work,
but you would still like to split it.

Signed-off-by: Thomas Rast <trast@student.ethz.ch>
---

This is my first patch, and I had to dust off my Perl knowledge a bit,
so I hope it is up to your standards.

I could have used this a few times because I frequently hack around a
bit, then after some time notice that this should really go in two
separate commits.  Usually 'add -p' can separate the changes, but if
their diff lines are immediately adjacent, one has to go back and
undo some editing before the first commit, then redo later.

I'm not quite happy with the scheme I use to handle colored diffs.
'git diff' apparently does not always reset the color before newlines
(is this a bug?), so I insert extra resets.  However, I did not want
to implement "full" diff coloring directly in git-add--interactive.

Also, I would be glad to hear your comments on the "user interface" of
the edit command loop.  I haven't found a good way of saying "an
optional number followed by y or n" that is consistent with the
"[y/n]" format used in the rest of the patch loop.  Similiarly, an
option to undo an edit might be nice, but would complicate the code a
fair bit.

Best regards,
Thomas


 Documentation/git-add.txt |    1 +
 git-add--interactive.perl |  110 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 111 insertions(+), 0 deletions(-)

diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index bb4abe2..8de4d4a 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -229,6 +229,7 @@ patch::
        k - leave this hunk undecided, see previous undecided hunk
        K - leave this hunk undecided, see previous hunk
        s - split the current hunk into smaller hunks
+       e - manually edit the current hunk
        ? - print help
 +
 After deciding the fate for all hunks, if there is any hunk
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 903953e..8af841a 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -18,6 +18,10 @@ my ($fraginfo_color) =
 	$diff_use_color ? (
 		$repo->get_color('color.diff.frag', 'cyan'),
 	) : ();
+my ($diff_plain_color) =
+	$diff_use_color ? (
+		$repo->get_color('color.diff.plain', ''),
+	) : ();
 
 my $normal_color = $repo->get_color("", "reset");
 
@@ -682,6 +686,107 @@ sub split_hunk {
 	return @split;
 }
 
+sub edit_hunk_manually {
+	my ($in_text, $in_display) = @_;
+
+	my @text = @$in_text;
+	my @display = @$in_display;
+
+	my ($o_ofs, $o_cnt, $n_ofs, $n_cnt) = parse_hunk_header($text[0]);
+	my $num = scalar @text;
+
+	my $ix = 0;
+
+      OUTER:
+	while (1) {
+		$text[0] = ("@@ -$o_ofs" .
+			    (($o_cnt != 1) ? ",$o_cnt" : '') .
+			    " +$n_ofs" .
+			    (($n_cnt != 1) ? ",$n_cnt" : '') .
+			    " @@\n");
+		if ($diff_use_color) {
+			$display[0] = colored $fraginfo_color, $text[0];
+		}
+		else {
+			$display[0] = $text[0];
+		}
+
+		while ($text[$ix] !~ /^[+-]/) {
+			$ix++;
+			last OUTER if $ix >= $num;
+		}
+		my $lineno = 0;
+		for (my $i = 0; $i < $num; $i++) {
+			if ($i >= $ix && $text[$i] =~ /^[+-]/) {
+				$lineno++;
+				if ($lineno == 1) {
+					print $normal_color . colored($prompt_color, ">1 ");
+				}
+				elsif ($lineno <  100) {
+					print $normal_color . colored($prompt_color, sprintf("%2d ", $lineno));
+				}
+				else {
+					print "   ";
+				}
+			}
+			else {
+				print "   ";
+			}
+			print $display[$i];
+		}
+		print colored $prompt_color, "Use line(s) [<num>y/n]? ";
+		my $line = <STDIN>;
+		if ($line) {
+			if ($line =~ /^(\d*)y/) {
+				my $repeat = $1 || 1;
+				while (1) {
+					last if ($repeat <= 0 || $ix >= $num);
+					$repeat-- if ($text[$ix] =~ /^[+-]/);
+					$ix++;
+				}
+			}
+			elsif ($line =~ /^(\d*)n/) {
+				# This is the interesting case.
+				# - lines become context, + lines are dropped
+				my $repeat = $1 || 1;
+				while (1) {
+					last if ($repeat <= 0 || $ix >= $num);
+					if ($text[$ix] =~ /^\+/) {
+						$repeat--;
+						splice(@text, $ix, 1);
+						splice(@display, $ix, 1);
+						$n_cnt--;
+						$num--;
+						$ix--;
+					}
+					elsif ($text[$ix] =~ /^-/) {
+						$repeat--;
+						$n_cnt++;
+						$text[$ix] =~ s/^-/ /;
+						# need a better way to do this
+						$display[$ix] = $normal_color . colored $diff_plain_color, $text[$ix];
+					}
+					$ix++;
+				}
+			}
+		}
+	}
+
+	while (1) {
+		for (@display) {
+			print;
+		}
+		print colored $prompt_color, "Accept and replace old hunk [y/n]? ";
+		my $line = <STDIN>;
+		if ($line =~ /^y/) {
+			return (\@text, \@display);
+		}
+		elsif ($line =~ /^n/) {
+			return ($in_text, $in_display);
+		}
+	}
+}
+
 sub find_last_o_ctx {
 	my ($it) = @_;
 	my $text = $it->{TEXT};
@@ -781,6 +886,7 @@ J - leave this hunk undecided, see next hunk
 k - leave this hunk undecided, see previous undecided hunk
 K - leave this hunk undecided, see previous hunk
 s - split the current hunk into smaller hunks
+e - manually edit the current hunk
 ? - print help
 EOF
 }
@@ -885,6 +991,7 @@ sub patch_update_file {
 		if (hunk_splittable($hunk[$ix]{TEXT})) {
 			$other .= '/s';
 		}
+		$other .= '/e';
 		for (@{$hunk[$ix]{DISPLAY}}) {
 			print;
 		}
@@ -949,6 +1056,9 @@ sub patch_update_file {
 				$num = scalar @hunk;
 				next;
 			}
+			elsif ($line =~ /^e/) {
+				($hunk[$ix]{TEXT}, $hunk[$ix]{DISPLAY}) = edit_hunk_manually($hunk[$ix]{TEXT}, $hunk[$ix]{DISPLAY});
+			}
 			else {
 				help_patch_cmd($other);
 				next;
-- 
1.5.4.5

             reply	other threads:[~2008-05-23 20:22 UTC|newest]

Thread overview: 74+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-05-23 20:21 Thomas Rast [this message]
2008-05-24  1:24 ` [PATCH] git-add--interactive: manual hunk editing mode Ping Yin
2008-05-29 15:37 ` Thomas Rast
2008-05-29 16:12   ` Johannes Schindelin
2008-05-29 19:10     ` Thomas Rast
2008-05-29 19:16       ` Thomas Rast
2008-05-29 18:58   ` Jeff King
2008-05-30  9:49     ` Johannes Schindelin
2008-05-30 10:46       ` Jakub Narebski
2008-05-30 12:21     ` Thomas Rast
2008-05-30 21:35       ` Junio C Hamano
2008-06-01  0:41     ` [RFC PATCH] git-add--interactive: manual hunk editing mode v2 Thomas Rast
2008-06-01 14:50       ` [RFC PATCH] git-add--interactive: manual hunk editing mode v2.1 Thomas Rast
2008-06-01 15:14         ` Jeff King
2008-06-05  1:46       ` [RFC PATCH] git-add--interactive: manual hunk editing mode v2 Jeff King
2008-06-05  7:53         ` Thomas Rast
2008-06-05  8:11           ` Jeff King
2008-06-05  9:04             ` Thomas Rast
2008-06-05  9:20               ` Jeff King
2008-06-05  9:38                 ` Thomas Rast
2008-06-05  9:46                   ` Jeff King
2008-06-05  8:16         ` Junio C Hamano
2008-06-05  8:56           ` Jeff King
2008-06-05 10:28             ` Johannes Schindelin
2008-06-06  5:10               ` Jeff King
2008-06-06  6:03                 ` Jeff King
2008-06-08 22:33                   ` Thomas Rast
2008-06-08 23:06                     ` Johannes Schindelin
2008-06-06 14:31                 ` Johannes Schindelin
2008-06-08 22:18                   ` Thomas Rast
2008-06-08 23:02                     ` Johannes Schindelin
2008-06-05 12:38         ` [WIP PATCH v2] git-add--interactive: manual hunk editing mode Thomas Rast
2008-06-08 22:32           ` [PATCH v3] " Thomas Rast
2008-06-08 23:19             ` Johannes Schindelin
2008-06-09  5:46               ` Johan Herland
2008-06-09 12:29                 ` Jeff King
2008-06-09 16:13                   ` Johannes Schindelin
2008-06-09 19:59                     ` Junio C Hamano
2008-06-09 17:31                   ` Johan Herland
2008-06-09 20:17                     ` Jeff King
2008-06-09 21:19                       ` Johan Herland
2008-06-10 11:05                         ` Jeff King
2008-06-11  9:02                           ` Thomas Rast
2008-06-12  4:49                             ` Jeff King
2008-06-12  6:55                               ` Thomas Rast
2008-06-12  7:13                                 ` Jeff King
2008-06-13 15:48                                   ` [PATCH v4] " Thomas Rast
2008-06-23 18:38                                     ` Jeff King
2008-06-23 18:54                                       ` Johannes Schindelin
2008-06-23 19:57                                         ` Jeff King
2008-06-23 21:16                                           ` apply --recount, was " Johannes Schindelin
2008-06-24  5:09                                             ` Jeff King
2008-06-24 19:07                                               ` [PATCH 0/3] Manual editing for 'add' and 'add -p' Thomas Rast
2008-06-24 19:53                                                 ` Miklos Vajna
2008-06-24 19:08                                               ` [PATCH 1/3] Allow git-apply to ignore the hunk headers (AKA recountdiff) Thomas Rast
2008-06-24 23:35                                                 ` Junio C Hamano
2008-06-25  5:45                                                   ` Jeff King
2008-06-27 17:43                                                   ` Johannes Schindelin
2008-06-24 19:08                                               ` [PATCH 2/3] git-add: introduce --edit (to edit the diff vs. the index) Thomas Rast
2008-06-24 19:08                                               ` [PATCH 3/3] git-add--interactive: manual hunk editing mode Thomas Rast
2008-06-10 11:19                       ` [PATCH v3] " Andreas Ericsson
2008-06-05  9:02     ` [PATCH] " Thomas Rast
  -- strict thread matches above, loose matches on Subject: below --
2008-07-01 10:11 What's cooking in git.git (topics) Jeff King
2008-07-01 11:44 ` [PATCH] git-add--interactive: manual hunk editing mode Thomas Rast
2008-07-01 16:48   ` Johannes Schindelin
2008-07-01 23:54   ` Junio C Hamano
2008-07-02  5:39   ` Junio C Hamano
2008-07-02  7:00     ` Thomas Rast
2008-07-02  8:38       ` Junio C Hamano
2008-07-02  8:02     ` Jeff King
2008-07-02  8:08       ` Junio C Hamano
2008-07-02  8:32         ` Jeff King
2008-07-02 13:13           ` Johannes Schindelin
2008-07-02 18:27             ` Junio C Hamano
2008-07-02  9:03 Thomas Rast

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

  List information: http://vger.kernel.org/majordomo-info.html

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

  git send-email \
    --in-reply-to=200805232221.45406.trast@student.ethz.ch \
    --to=trast@student.ethz.ch \
    --cc=git@vger.kernel.org \
    /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.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).