Code

git-gui: Always indicate the file in the diff viewer.
[git.git] / git-gui
diff --git a/git-gui b/git-gui
index 640519c204c904eb3982a827f44c997165639dd2..f36594eea0f8a85a5abb75f51fff7123cf6b04b0 100755 (executable)
--- a/git-gui
+++ b/git-gui
@@ -150,7 +150,7 @@ proc repository_state {hdvar ctvar} {
 proc update_status {{final Ready.}} {
        global HEAD PARENT commit_type
        global ui_index ui_other ui_status_value ui_comm
-       global status_active file_states
+       global status_active file_states file_lists
        global cfg_trust_mtime
 
        if {$status_active || ![lock_index read]} return
@@ -166,6 +166,7 @@ proc update_status {{final Ready.}} {
        }
 
        array unset file_states
+       array unset file_lists
        foreach w [list $ui_index $ui_other] {
                $w conf -state normal
                $w delete 0.0 end
@@ -179,6 +180,7 @@ proc update_status {{final Ready.}} {
                } elseif {[load_message SQUASH_MSG]} {
                }
                $ui_comm edit modified false
+               $ui_comm edit reset
        }
 
        if {$cfg_trust_mtime == {true}} {
@@ -195,7 +197,7 @@ proc update_status {{final Ready.}} {
 proc update_status_stage2 {fd final} {
        global gitdir PARENT commit_type
        global ui_index ui_other ui_status_value ui_comm
-       global status_active file_states
+       global status_active
        global buf_rdi buf_rdf buf_rlo
 
        if {$fd != {}} {
@@ -345,22 +347,40 @@ proc status_eof {fd buf final} {
 ## diff
 
 proc clear_diff {} {
-       global ui_diff ui_fname_value ui_fstatus_value
+       global ui_diff ui_fname_value ui_fstatus_value ui_index ui_other
 
        $ui_diff conf -state normal
        $ui_diff delete 0.0 end
        $ui_diff conf -state disabled
+
        set ui_fname_value {}
        set ui_fstatus_value {}
+
+       $ui_index tag remove in_diff 0.0 end
+       $ui_other tag remove in_diff 0.0 end
 }
 
-proc show_diff {path} {
-       global file_states PARENT diff_3way diff_active
+proc show_diff {path {w {}} {lno {}}} {
+       global file_states file_lists
+       global PARENT diff_3way diff_active
        global ui_diff ui_fname_value ui_fstatus_value ui_status_value
 
        if {$diff_active || ![lock_index read]} return
 
        clear_diff
+       if {$w == {} || $lno == {}} {
+               foreach w [array names file_lists] {
+                       set lno [lsearch -sorted $file_lists($w) $path]
+                       if {$lno >= 0} {
+                               incr lno
+                               break
+                       }
+               }
+       }
+       if {$w != {} && $lno >= 1} {
+               $w tag add in_diff $lno.0 [expr $lno + 1].0
+       }
+
        set s $file_states($path)
        set m [lindex $s 0]
        set diff_3way 0
@@ -503,6 +523,7 @@ proc load_last_commit {} {
                $ui_comm delete 0.0 end
                $ui_comm insert end $msg
                $ui_comm edit modified false
+               $ui_comm edit reset
                update_status
        } else {
                error_popup {You can't amend a merge commit.}
@@ -698,6 +719,7 @@ proc commit_stage2 {fd_wt curHEAD msg} {
 
        $ui_comm delete 0.0 end
        $ui_comm edit modified false
+       $ui_comm edit reset
 
        if {$single_commit} do_quit
 
@@ -820,27 +842,6 @@ proc mapdesc {state path} {
        return $r
 }
 
-proc bsearch {w path} {
-       set hi [expr [lindex [split [$w index end] .] 0] - 2]
-       if {$hi == 0} {
-               return -1
-       }
-       set lo 0
-       while {$lo < $hi} {
-               set mi [expr [expr $lo + $hi] / 2]
-               set ti [expr $mi + 1]
-               set cmp [string compare [$w get $ti.1 $ti.end] $path]
-               if {$cmp < 0} {
-                       set lo $ti
-               } elseif {$cmp == 0} {
-                       return $mi
-               } else {
-                       set hi $mi
-               }
-       }
-       return -[expr $lo + 1]
-}
-
 set next_icon_id 0
 
 proc merge_state {path new_state} {
@@ -874,7 +875,8 @@ proc merge_state {path new_state} {
 }
 
 proc display_file {path state} {
-       global ui_index ui_other file_states status_active
+       global ui_index ui_other
+       global file_states file_lists status_active
 
        set old_m [merge_state $path $state]
        if {$status_active} return
@@ -886,7 +888,7 @@ proc display_file {path state} {
        set new_icon [mapicon $new_m $path]
 
        if {$new_w != $old_w} {
-               set lno [bsearch $old_w $path]
+               set lno [lsearch -sorted $file_lists($old_w) $path]
                if {$lno >= 0} {
                        incr lno
                        $old_w conf -state normal
@@ -894,7 +896,10 @@ proc display_file {path state} {
                        $old_w conf -state disabled
                }
 
-               set lno [expr abs([bsearch $new_w $path] + 1) + 1]
+               lappend file_lists($new_w) $path
+               set file_lists($new_w) [lsort $file_lists($new_w)]
+               set lno [lsearch -sorted $file_lists($new_w) $path]
+               incr lno
                $new_w conf -state normal
                $new_w image create $lno.0 \
                        -align center -padx 5 -pady 1 \
@@ -910,7 +915,7 @@ proc display_file {path state} {
 }
 
 proc display_all_files {} {
-       global ui_index ui_other file_states
+       global ui_index ui_other file_states file_lists
 
        $ui_index conf -state normal
        $ui_other conf -state normal
@@ -919,6 +924,7 @@ proc display_all_files {} {
                set s $file_states($path)
                set m [lindex $s 0]
                set w [mapcol $m $path]
+               lappend file_lists($w) $path
                $w image create end \
                        -align center -padx 5 -pady 1 \
                        -name [lindex $s 1] \
@@ -1463,8 +1469,9 @@ proc do_signoff {} {
 
        set str "Signed-off-by: $GIT_COMMITTER_IDENT"
        if {[$ui_comm get {end -1c linestart} {end -1c}] != $str} {
-               $ui_comm insert end "\n"
-               $ui_comm insert end $str
+               $ui_comm edit separator
+               $ui_comm insert end "\n$str"
+               $ui_comm edit separator
                $ui_comm see end
        }
 }
@@ -1480,19 +1487,16 @@ proc do_commit {} {
 # shift == 1: left click
 #          3: right click  
 proc click {w x y shift wx wy} {
-       global ui_index ui_other
+       global ui_index ui_other file_lists
 
        set pos [split [$w index @$x,$y] .]
        set lno [lindex $pos 0]
        set col [lindex $pos 1]
-       set path [$w get $lno.1 $lno.end]
+       set path [lindex $file_lists($w) [expr $lno - 1]]
        if {$path == {}} return
 
        if {$col > 0 && $shift == 1} {
-               $ui_index tag remove in_diff 0.0 end
-               $ui_other tag remove in_diff 0.0 end
-               $w tag add in_diff $lno.0 [expr $lno + 1].0
-               show_diff $path
+               show_diff $path $w $lno
        }
 }
 
@@ -1733,6 +1737,7 @@ trace add variable commit_type write {uplevel #0 {
 }}
 text $ui_comm -background white -borderwidth 1 \
        -undo true \
+       -maxundo 20 \
        -autoseparators true \
        -relief sunken \
        -width 75 -height 9 -wrap none \
@@ -1836,10 +1841,10 @@ bind $ui_diff <$M1B-Key-v> {break}
 bind $ui_diff <$M1B-Key-V> {break}
 bind $ui_diff <$M1B-Key-a> {%W tag add sel 0.0 end;break}
 bind $ui_diff <$M1B-Key-A> {%W tag add sel 0.0 end;break}
-bind $ui_diff <Key-Up>     {%W yview scroll -1 units}
-bind $ui_diff <Key-Down>   {%W yview scroll 1 units}
-bind $ui_diff <Key-Left>   {%W xview scroll -1 units}
-bind $ui_diff <Key-Right>  {%W xview scroll 1 units}
+bind $ui_diff <Key-Up>     {catch {%W yview scroll -1 units};break}
+bind $ui_diff <Key-Down>   {catch {%W yview scroll  1 units};break}
+bind $ui_diff <Key-Left>   {catch {%W xview scroll -1 units};break}
+bind $ui_diff <Key-Right>  {catch {%W xview scroll  1 units};break}
 
 bind .   <Destroy> do_quit
 bind all <Key-F5> do_rescan