From: Johannes Schindelin <Johannes.Schindelin@gmx.de>
To: "Shawn O. Pearce" <spearce@spearce.org>, git@vger.kernel.org
Subject: [PATCH] Teach git-gui to split hunks
Date: Thu, 26 Jul 2007 06:32:07 +0100 (BST) [thread overview]
Message-ID: <Pine.LNX.4.64.0707260630570.14781@racer.site> (raw)
When you select the context menu item "Split Hunk" in the diff area,
git-gui will now split the current hunk so that a new hunk starts at
the current position.
For this to work, apply has to be called with --unidiff-zero, since
the new hunks can start or stop with a "-" or "+" line.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
No more complaining from me about the lack of that feature.
And I did not even need a C compiler to do that.
git-gui.sh | 4 +++
lib/diff.tcl | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 78 insertions(+), 1 deletions(-)
diff --git a/git-gui.sh b/git-gui.sh
index a38293a..a0f7617 100755
--- a/git-gui.sh
+++ b/git-gui.sh
@@ -2400,6 +2400,10 @@ $ctxm add command \
-command {apply_hunk $cursorX $cursorY}
set ui_diff_applyhunk [$ctxm index last]
lappend diff_actions [list $ctxm entryconf $ui_diff_applyhunk -state]
+$ctxm add command \
+ -label [mc "Split Hunk"] \
+ -command {split_hunk $cursorX $cursorY}
+lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
$ctxm add separator
$ctxm add command \
-label {Decrease Font Size} \
diff --git a/lib/diff.tcl b/lib/diff.tcl
index e09e125..88ec8f3 100644
--- a/lib/diff.tcl
+++ b/lib/diff.tcl
@@ -265,6 +265,79 @@ proc read_diff {fd} {
}
}
+proc split_hunk {x y} {
+ global current_diff_path current_diff_header current_diff_side
+ global ui_diff ui_index file_states
+
+ if {$current_diff_path eq {} || $current_diff_header eq {}} return
+ if {![lock_index apply_hunk]} return
+
+ set c_lno [lindex [split [$ui_diff index @$x,$y] .] 0]
+ set s_idx [$ui_diff search -backwards -regexp ^@@ $c_lno.0 0.0]
+ if {$s_idx eq {} || $s_idx >= [expr $c_lno - 1]} {
+ unlock_index
+ return
+ }
+ set s_lno [lindex [split $s_idx .] 0]
+
+ # the first hunk will look like this: @@ -$m1,$m2 +$p1,$p2 @@
+ # the second hunk will look like this: @@ -$m3,$m4 +$p3,$p4 @@
+
+ # get original hunk numbers
+ set hunk_line [$ui_diff get $s_idx "$s_idx lineend"]
+ set re "@@ +-(\[0-9\]+)(,(\[0-9\]+))? +\\+(\[0-9\]+)(,(\[0-9\]+))? *@@"
+ if {![regexp $re $hunk_line dummy m1 dummy m4 p1 dummy p4] ||
+ $m1 == 0 || $p1 == 0} { # create/delete file
+ unlock_index
+ return
+ }
+ if {$m4 == ""} {
+ set m4 1
+ }
+ if {$p4 == ""} {
+ set p4 1
+ }
+
+ # count changes
+ set m2 0
+ set p2 0
+ for {set l [expr $s_lno + 1]} {$l < $c_lno} {incr l} {
+ switch -exact -- [$ui_diff get $l.0] {
+ " " {
+ incr m2
+ incr p2
+ }
+ "+" {
+ incr p2
+ }
+ "-" {
+ incr m2
+ }
+ }
+ }
+
+ # We could check if {$m2 == $p2 && $m2 == [expr $c_lno - $s_lno]}
+ # and just remove the hunk. But let's not be too clever here.
+
+ set m3 [expr $m1 + $m2]
+ set m4 [expr $m4 - $m2]
+ set p3 [expr $p1 + $p2]
+ set p4 [expr $p4 - $p2]
+
+ if {$m4 == 0 && $p4 == 0} {
+ index_unlock
+ return
+ }
+
+ $ui_diff configure -state normal
+ $ui_diff delete $s_idx "$s_idx lineend"
+ $ui_diff insert $s_idx "@@ -$m1,$m2 +$p1,$p2 @@" d_@
+ $ui_diff insert $c_lno.0 "@@ -$m3,$m4 +$p3,$p4 @@\n" d_@
+ $ui_diff configure -state disabled
+
+ unlock_index
+}
+
proc apply_hunk {x y} {
global current_diff_path current_diff_header current_diff_side
global ui_diff ui_index file_states
@@ -272,7 +345,7 @@ proc apply_hunk {x y} {
if {$current_diff_path eq {} || $current_diff_header eq {}} return
if {![lock_index apply_hunk]} return
- set apply_cmd {apply --cached --whitespace=nowarn}
+ set apply_cmd {apply --cached --whitespace=nowarn --unidiff-zero}
set mi [lindex $file_states($current_diff_path) 0]
if {$current_diff_side eq $ui_index} {
set mode unstage
--
1.5.3.rc2.42.gda8d-dirty
next reply other threads:[~2007-07-26 5:32 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-07-26 5:32 Johannes Schindelin [this message]
2007-07-26 5:48 ` [PATCH] Teach git-gui to split hunks David Kastrup
2007-07-26 7:07 ` Shawn O. Pearce
2007-07-26 14:34 ` Johannes Schindelin
2007-07-26 7:32 ` Johannes Sixt
2007-07-26 14:26 ` Johannes Schindelin
-- strict thread matches above, loose matches on Subject: below --
2007-12-11 13:48 [ANNOUNCE] ugit: a pyqt-based git gui // was: Re: If you would write git from scratch now, what would you change? David
2007-12-11 19:14 ` Jason Sewall
2007-12-11 19:33 ` Marco Costalba
2007-12-11 20:54 ` David
2007-12-11 21:29 ` Jason Sewall
2007-12-12 4:10 ` Shawn O. Pearce
2007-12-12 5:13 ` Jason Sewall
2007-12-12 5:23 ` Shawn O. Pearce
2007-12-12 15:02 ` Jason Sewall
2007-12-12 18:15 ` Johannes Schindelin
2007-12-12 18:50 ` Jason Sewall
2007-12-12 19:37 ` [PATCH] Teach git-gui to split hunks Johannes Schindelin
2007-12-12 20:18 ` Junio C Hamano
2007-12-12 20:39 ` Johannes Schindelin
2007-12-12 20:50 ` Jean-François Veillette
2007-12-12 22:54 ` Junio C Hamano
2007-12-12 23:02 ` Wincent Colaiuta
2007-12-13 7:35 ` Johannes Sixt
2007-12-13 7:48 ` Shawn O. Pearce
2007-12-13 12:25 ` Johannes Schindelin
2007-12-13 8:45 ` Junio C Hamano
2007-12-13 9:41 ` Johannes Sixt
2007-12-13 12:49 ` Johannes Schindelin
2007-12-13 14:03 ` Johannes Sixt
2007-12-13 14:18 ` Johannes Schindelin
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=Pine.LNX.4.64.0707260630570.14781@racer.site \
--to=johannes.schindelin@gmx.de \
--cc=git@vger.kernel.org \
--cc=spearce@spearce.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.
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 NNTP newsgroup(s).