* [RFC PATCH] git-gui: Allow staging multiple lines at once
@ 2009-10-19 19:54 Jeff Epler
2009-10-19 20:08 ` Geert Bosch
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: Jeff Epler @ 2009-10-19 19:54 UTC (permalink / raw)
To: git
When applying less than a full hunk, it's still often desirable to apply
a number of consecutive lines.
This change makes it possible to sweep out a range of lines in the diff view
with the left mouse button, then right click and "Stage Lines For Commit".
The selected lines may span multiple hunks.
Signed-off-by: Jeff Epler <jepler@unpythonic.net>
---
The diff looks bigger than it is because it changed the indentation level
of about 80 lines, and that made it necessary to reflow a lengthy comment
block as well.
This introduces new user interface strings. I felt this was probably a
better decision than using the inaccurate "Stage Line For Commit" when
a block of text was swept out.
I wonder a bit about the message [mc "Apply/Reverse Line"] -- as far as
I can tell, it is never shown to a user, so why is it translated?
git-gui/git-gui.sh | 15 +++-
git-gui/lib/diff.tcl | 222 +++++++++++++++++++++++++++----------------------
2 files changed, 134 insertions(+), 103 deletions(-)
diff --git a/git-gui/git-gui.sh b/git-gui/git-gui.sh
index 14b92ba..a80ed0d 100755
--- a/git-gui/git-gui.sh
+++ b/git-gui/git-gui.sh
@@ -3165,7 +3165,7 @@ set ui_diff_applyhunk [$ctxm index last]
lappend diff_actions [list $ctxm entryconf $ui_diff_applyhunk -state]
$ctxm add command \
-label [mc "Apply/Reverse Line"] \
- -command {apply_line $cursorX $cursorY; do_rescan}
+ -command {apply_range_or_line $cursorX $cursorY; do_rescan}
set ui_diff_applyline [$ctxm index last]
lappend diff_actions [list $ctxm entryconf $ui_diff_applyline -state]
$ctxm add separator
@@ -3205,12 +3205,21 @@ proc popup_diff_menu {ctxm ctxmmg x y X Y} {
if {[string first {U} $state] >= 0} {
tk_popup $ctxmmg $X $Y
} else {
+ set has_range [expr {[$::ui_diff tag nextrange sel 0.0] != {}}]
if {$::ui_index eq $::current_diff_side} {
set l [mc "Unstage Hunk From Commit"]
- set t [mc "Unstage Line From Commit"]
+ if {$has_range} {
+ set t [mc "Unstage Lines From Commit"]
+ } else {
+ set t [mc "Unstage Line From Commit"]
+ }
} else {
set l [mc "Stage Hunk For Commit"]
- set t [mc "Stage Line For Commit"]
+ if {$has_range} {
+ set t [mc "Stage Lines For Commit"]
+ } else {
+ set t [mc "Stage Line For Commit"]
+ }
}
if {$::is_3way_diff
|| $current_diff_path eq {}
diff --git a/git-gui/lib/diff.tcl b/git-gui/lib/diff.tcl
index 925b3f5..30ac659 100644
--- a/git-gui/lib/diff.tcl
+++ b/git-gui/lib/diff.tcl
@@ -505,10 +505,23 @@ proc apply_hunk {x y} {
}
}
-proc apply_line {x y} {
+proc apply_range_or_line {x y} {
global current_diff_path current_diff_header current_diff_side
global ui_diff ui_index file_states
+ set selected [$ui_diff tag nextrange sel 0.0]
+
+ if {$selected == {}} {
+ set first [$ui_diff index "@$x,$y"]
+ set last $first
+ } else {
+ set first [lindex $selected 0]
+ set last [lindex $selected 1]
+ }
+
+ set first_l [$ui_diff index "$first linestart"]
+ set last_l [$ui_diff index "$last lineend"]
+
if {$current_diff_path eq {} || $current_diff_header eq {}} return
if {![lock_index apply_hunk]} return
@@ -531,119 +544,128 @@ proc apply_line {x y} {
}
}
- set the_l [$ui_diff index @$x,$y]
+ set wholepatch {}
- # operate only on change lines
- set c1 [$ui_diff get "$the_l linestart"]
- if {$c1 ne {+} && $c1 ne {-}} {
- unlock_index
- return
- }
- set sign $c1
-
- set i_l [$ui_diff search -backwards -regexp ^@@ $the_l 0.0]
- if {$i_l eq {}} {
- unlock_index
- return
- }
- # $i_l is now at the beginning of a line
+ while {$first_l < $last_l} {
+ set i_l [$ui_diff search -backwards -regexp ^@@ $first_l 0.0]
+ if {$i_l eq {}} {
+ # If there's not a @@ above, then the selected range
+ # must have come before the first_l @@
+ set i_l [$ui_diff search -regexp ^@@ $first_l $last_l]
+ }
+ if {$i_l eq {}} {
+ unlock_index
+ return
+ }
+ # $i_l is now at the beginning of a line
- # pick start line number from hunk header
- set hh [$ui_diff get $i_l "$i_l + 1 lines"]
- set hh [lindex [split $hh ,] 0]
- set hln [lindex [split $hh -] 1]
+ # pick start line number from hunk header
+ set hh [$ui_diff get $i_l "$i_l + 1 lines"]
+ set hh [lindex [split $hh ,] 0]
+ set hln [lindex [split $hh -] 1]
- # There is a special situation to take care of. Consider this hunk:
- #
- # @@ -10,4 +10,4 @@
- # context before
- # -old 1
- # -old 2
- # +new 1
- # +new 2
- # context after
- #
- # We used to keep the context lines in the order they appear in the
- # hunk. But then it is not possible to correctly stage only
- # "-old 1" and "+new 1" - it would result in this staged text:
- #
- # context before
- # old 2
- # new 1
- # context after
- #
- # (By symmetry it is not possible to *un*stage "old 2" and "new 2".)
- #
- # We resolve the problem by introducing an asymmetry, namely, when
- # a "+" line is *staged*, it is moved in front of the context lines
- # that are generated from the "-" lines that are immediately before
- # the "+" block. That is, we construct this patch:
- #
- # @@ -10,4 +10,5 @@
- # context before
- # +new 1
- # old 1
- # old 2
- # context after
- #
- # But we do *not* treat "-" lines that are *un*staged in a special
- # way.
- #
- # With this asymmetry it is possible to stage the change
- # "old 1" -> "new 1" directly, and to stage the change
- # "old 2" -> "new 2" by first staging the entire hunk and
- # then unstaging the change "old 1" -> "new 1".
-
- # This is non-empty if and only if we are _staging_ changes;
- # then it accumulates the consecutive "-" lines (after converting
- # them to context lines) in order to be moved after the "+" change
- # line.
- set pre_context {}
-
- set n 0
- set i_l [$ui_diff index "$i_l + 1 lines"]
- set patch {}
- while {[$ui_diff compare $i_l < "end - 1 chars"] &&
- [$ui_diff get $i_l "$i_l + 2 chars"] ne {@@}} {
- set next_l [$ui_diff index "$i_l + 1 lines"]
- set c1 [$ui_diff get $i_l]
- if {[$ui_diff compare $i_l <= $the_l] &&
- [$ui_diff compare $the_l < $next_l]} {
- # the line to stage/unstage
- set ln [$ui_diff get $i_l $next_l]
- if {$c1 eq {-}} {
- set n [expr $n+1]
+ # There is a special situation to take care of. Consider this
+ # hunk:
+ #
+ # @@ -10,4 +10,4 @@
+ # context before
+ # -old 1
+ # -old 2
+ # +new 1
+ # +new 2
+ # context after
+ #
+ # We used to keep the context lines in the order they appear in
+ # the hunk. But then it is not possible to correctly stage only
+ # "-old 1" and "+new 1" - it would result in this staged text:
+ #
+ # context before
+ # old 2
+ # new 1
+ # context after
+ #
+ # (By symmetry it is not possible to *un*stage "old 2" and "new
+ # 2".)
+ #
+ # We resolve the problem by introducing an asymmetry, namely,
+ # when a "+" line is *staged*, it is moved in front of the
+ # context lines that are generated from the "-" lines that are
+ # immediately before the "+" block. That is, we construct this
+ # patch:
+ #
+ # @@ -10,4 +10,5 @@
+ # context before
+ # +new 1
+ # old 1
+ # old 2
+ # context after
+ #
+ # But we do *not* treat "-" lines that are *un*staged in a
+ # special way.
+ #
+ # With this asymmetry it is possible to stage the change "old
+ # 1" -> "new 1" directly, and to stage the change "old 2" ->
+ # "new 2" by first staging the entire hunk and then unstaging
+ # the change "old 1" -> "new 1".
+
+ # This is non-empty if and only if we are _staging_ changes;
+ # then it accumulates the consecutive "-" lines (after
+ # converting them to context lines) in order to be moved after
+ # the "+" change line.
+ set pre_context {}
+
+ set n 0
+ set m 0
+ set i_l [$ui_diff index "$i_l + 1 lines"]
+ set patch {}
+ while {[$ui_diff compare $i_l < "end - 1 chars"] &&
+ [$ui_diff get $i_l "$i_l + 2 chars"] ne {@@}} {
+ set next_l [$ui_diff index "$i_l + 1 lines"]
+ set c1 [$ui_diff get $i_l]
+ if {[$ui_diff compare $first_l <= $i_l] &&
+ [$ui_diff compare $i_l < $last_l] &&
+ ($c1 eq {-} || $c1 eq {+})} {
+ # the line to stage/unstage
+ set ln [$ui_diff get $i_l $next_l]
+ if {$c1 eq {-}} {
+ set n [expr $n+1]
+ set patch "$patch$pre_context$ln"
+ } else {
+ set m [expr $m+1]
+ set patch "$patch$ln$pre_context"
+ }
+ set pre_context {}
+ } elseif {$c1 ne {-} && $c1 ne {+}} {
+ # context line
+ set ln [$ui_diff get $i_l $next_l]
set patch "$patch$pre_context$ln"
+ set n [expr $n+1]
+ set m [expr $m+1]
+ set pre_context {}
+ } elseif {$c1 eq $to_context} {
+ # turn change line into context line
+ set ln [$ui_diff get "$i_l + 1 chars" $next_l]
+ if {$c1 eq {-}} {
+ set pre_context "$pre_context $ln"
+ } else {
+ set patch "$patch $ln"
+ }
+ set n [expr $n+1]
+ set m [expr $m+1]
} else {
- set patch "$patch$ln$pre_context"
- }
- set pre_context {}
- } elseif {$c1 ne {-} && $c1 ne {+}} {
- # context line
- set ln [$ui_diff get $i_l $next_l]
- set patch "$patch$pre_context$ln"
- set n [expr $n+1]
- set pre_context {}
- } elseif {$c1 eq $to_context} {
- # turn change line into context line
- set ln [$ui_diff get "$i_l + 1 chars" $next_l]
- if {$c1 eq {-}} {
- set pre_context "$pre_context $ln"
- } else {
- set patch "$patch $ln"
}
- set n [expr $n+1]
+ set i_l $next_l
}
- set i_l $next_l
+ set wholepatch "$wholepatch@@ -$hln,$n +$hln,$m @@\n$patch"
+ set first_l [$ui_diff index "$next_l + 1 lines"]
}
- set patch "@@ -$hln,$n +$hln,[eval expr $n $sign 1] @@\n$patch"
if {[catch {
set enc [get_path_encoding $current_diff_path]
set p [eval git_write $apply_cmd]
fconfigure $p -translation binary -encoding $enc
puts -nonewline $p $current_diff_header
- puts -nonewline $p $patch
+ puts -nonewline $p $wholepatch
close $p} err]} {
error_popup [append $failed_msg "\n\n$err"]
}
--
1.6.5.rc1.49.ge970
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [RFC PATCH] git-gui: Allow staging multiple lines at once
2009-10-19 19:54 [RFC PATCH] git-gui: Allow staging multiple lines at once Jeff Epler
@ 2009-10-19 20:08 ` Geert Bosch
2009-10-20 6:11 ` Johannes Sixt
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Geert Bosch @ 2009-10-19 20:08 UTC (permalink / raw)
To: Jeff Epler; +Cc: git
On Oct 19, 2009, at 15:54, Jeff Epler wrote:
> When applying less than a full hunk, it's still often desirable to
> apply
> a number of consecutive lines.
>
> This change makes it possible to sweep out a range of lines in the
> diff view
> with the left mouse button, then right click and "Stage Lines For
> Commit".
>
> The selected lines may span multiple hunks.
Great! I've wished for this feature...
Thanks,
-Geert
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC PATCH] git-gui: Allow staging multiple lines at once
2009-10-19 19:54 [RFC PATCH] git-gui: Allow staging multiple lines at once Jeff Epler
2009-10-19 20:08 ` Geert Bosch
@ 2009-10-20 6:11 ` Johannes Sixt
2009-10-20 17:09 ` Dirk Süsserott
2009-10-22 19:51 ` Heiko Voigt
3 siblings, 0 replies; 6+ messages in thread
From: Johannes Sixt @ 2009-10-20 6:11 UTC (permalink / raw)
To: Jeff Epler; +Cc: git
Jeff Epler schrieb:
> When applying less than a full hunk, it's still often desirable to apply
> a number of consecutive lines.
>
> This change makes it possible to sweep out a range of lines in the diff view
> with the left mouse button, then right click and "Stage Lines For Commit".
>
> The selected lines may span multiple hunks.
Superb! Will test.
-- Hannes
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC PATCH] git-gui: Allow staging multiple lines at once
2009-10-19 19:54 [RFC PATCH] git-gui: Allow staging multiple lines at once Jeff Epler
2009-10-19 20:08 ` Geert Bosch
2009-10-20 6:11 ` Johannes Sixt
@ 2009-10-20 17:09 ` Dirk Süsserott
2009-10-22 19:51 ` Heiko Voigt
3 siblings, 0 replies; 6+ messages in thread
From: Dirk Süsserott @ 2009-10-20 17:09 UTC (permalink / raw)
To: Jeff Epler; +Cc: git
Am 19.10.2009 21:54 schrieb Jeff Epler:
> When applying less than a full hunk, it's still often desirable to apply
> a number of consecutive lines.
>
> This change makes it possible to sweep out a range of lines in the diff view
> with the left mouse button, then right click and "Stage Lines For Commit".
>
> The selected lines may span multiple hunks.
>
Awesome! I've been waiting for that very feature. Thanks in advance.
-- Dirk
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC PATCH] git-gui: Allow staging multiple lines at once
2009-10-19 19:54 [RFC PATCH] git-gui: Allow staging multiple lines at once Jeff Epler
` (2 preceding siblings ...)
2009-10-20 17:09 ` Dirk Süsserott
@ 2009-10-22 19:51 ` Heiko Voigt
2009-10-23 1:53 ` Jeff Epler
3 siblings, 1 reply; 6+ messages in thread
From: Heiko Voigt @ 2009-10-22 19:51 UTC (permalink / raw)
To: Jeff Epler; +Cc: git, Shawn O. Pearce
On Mon, Oct 19, 2009 at 02:54:57PM -0500, Jeff Epler wrote:
> When applying less than a full hunk, it's still often desirable to apply
> a number of consecutive lines.
>
> This change makes it possible to sweep out a range of lines in the diff view
> with the left mouse button, then right click and "Stage Lines For Commit".
>
> The selected lines may span multiple hunks.
Thanks a lot! Very nice. I've been planning to implement this sometime
myself but never got around it.
Tested it and it works like a charm. I will include Shawn in the CC: so
he can comment.
cheers Heiko
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC PATCH] git-gui: Allow staging multiple lines at once
2009-10-22 19:51 ` Heiko Voigt
@ 2009-10-23 1:53 ` Jeff Epler
0 siblings, 0 replies; 6+ messages in thread
From: Jeff Epler @ 2009-10-23 1:53 UTC (permalink / raw)
To: Heiko Voigt; +Cc: git, Shawn O. Pearce
On Thu, Oct 22, 2009 at 09:51:16PM +0200, Heiko Voigt wrote:
> Tested it and it works like a charm. I will include Shawn in the CC: so
> he can comment.
Thanks, but don't miss the v2 patch:
http://thread.gmane.org/gmane.comp.version-control.git/130968
this fixes a bug staging line(s) followed only by deletions.
Jeff
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2009-10-23 1:53 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-10-19 19:54 [RFC PATCH] git-gui: Allow staging multiple lines at once Jeff Epler
2009-10-19 20:08 ` Geert Bosch
2009-10-20 6:11 ` Johannes Sixt
2009-10-20 17:09 ` Dirk Süsserott
2009-10-22 19:51 ` Heiko Voigt
2009-10-23 1:53 ` Jeff Epler
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.