gitk: Add Return and Escape bindings to dialogs
[gitweb.git] / gitk
diff --git a/gitk b/gitk
index 477590eed6a460eeeac0ff13b8b41fa3faac6948..edef9e224eaca274efdc6904c577d9e0c6a0b2fe 100755 (executable)
--- a/gitk
+++ b/gitk
@@ -1746,6 +1746,8 @@ proc show_error {w top msg} {
     pack $w.ok -side bottom -fill x
     bind $top <Visibility> "grab $top; focus $top"
     bind $top <Key-Return> "destroy $top"
+    bind $top <Key-space>  "destroy $top"
+    bind $top <Key-Escape> "destroy $top"
     tkwait window $top
 }
 
@@ -1769,6 +1771,9 @@ proc confirm_popup msg {
     button $w.cancel -text [mc Cancel] -command "destroy $w"
     pack $w.cancel -side right -fill x
     bind $w <Visibility> "grab $w; focus $w"
+    bind $w <Key-Return> "set confirm_ok 1; destroy $w"
+    bind $w <Key-space>  "set confirm_ok 1; destroy $w"
+    bind $w <Key-Escape> "destroy $w"
     tkwait window $w
     return $confirm_ok
 }
@@ -2296,6 +2301,7 @@ proc makewindow {} {
     global diff_menu
     set diff_menu .diffctxmenu
     makemenu $diff_menu {
+       {mc "Show origin of this line" command show_line_source}
        {mc "Run git gui blame on this line" command {external_blame_diff}}
     }
     $diff_menu configure -tearoff 0
@@ -2414,7 +2420,7 @@ proc savestuff {w} {
     global viewname viewfiles viewargs viewargscmd viewperm nextviewnum
     global cmitmode wrapcomment datetimeformat limitdiffs
     global colors bgcolor fgcolor diffcolors diffcontext selectbgcolor
-    global autoselect extdifftool perfile_attrs
+    global autoselect extdifftool perfile_attrs markbgcolor
 
     if {$stuffsaved} return
     if {![winfo viewable .]} return
@@ -2438,6 +2444,7 @@ proc savestuff {w} {
        puts $f [list set fgcolor $fgcolor]
        puts $f [list set colors $colors]
        puts $f [list set diffcolors $diffcolors]
+       puts $f [list set markbgcolor $markbgcolor]
        puts $f [list set diffcontext $diffcontext]
        puts $f [list set selectbgcolor $selectbgcolor]
        puts $f [list set extdifftool $extdifftool]
@@ -2609,6 +2616,7 @@ proc keys {} {
            -justify left -bg white -border 2 -relief groove
     pack $w.m -side top -fill both -padx 2 -pady 2
     button $w.ok -text [mc "Close"] -command "destroy $w" -default active
+    bind $w <Key-Escape> [list destroy $w]
     pack $w.ok -side bottom
     bind $w <Visibility> "focus $w.ok"
     bind $w <Key-Escape> "destroy $w"
@@ -2830,9 +2838,15 @@ proc treeclick {w x y} {
 }
 
 proc setfilelist {id} {
-    global treefilelist cflist
+    global treefilelist cflist jump_to_here
 
     treeview $cflist $treefilelist($id) 0
+    if {$jump_to_here ne {}} {
+       set f [lindex $jump_to_here 0]
+       if {[lsearch -exact $treefilelist($id) $f] >= 0} {
+           showfile $f
+       }
+    }
 }
 
 image create bitmap tri-rt -background black -foreground blue -data {
@@ -3256,6 +3270,91 @@ proc external_blame {parent_idx {line {}}} {
     }
 }
 
+proc show_line_source {} {
+    global cmitmode currentid parents curview blamestuff blameinst
+    global diff_menu_line diff_menu_filebase flist_menu_file
+
+    if {$cmitmode eq "tree"} {
+       set id $currentid
+       set line [expr {$diff_menu_line - $diff_menu_filebase}]
+    } else {
+       set h [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
+       if {$h eq {}} return
+       set pi [lindex $h 0]
+       if {$pi == 0} {
+           mark_ctext_line $diff_menu_line
+           return
+       }
+       set id [lindex $parents($curview,$currentid) [expr {$pi - 1}]]
+       set line [lindex $h 1]
+    }
+    if {[catch {
+       set f [open [list | git blame -p -L$line,+1 $id -- $flist_menu_file] r]
+    } err]} {
+       error_popup [mc "Couldn't start git blame: %s" $err]
+       return
+    }
+    fconfigure $f -blocking 0
+    set i [reg_instance $f]
+    set blamestuff($i) {}
+    set blameinst $i
+    filerun $f [list read_line_source $f $i]
+}
+
+proc stopblaming {} {
+    global blameinst
+
+    if {[info exists blameinst]} {
+       stop_instance $blameinst
+       unset blameinst
+    }
+}
+
+proc read_line_source {fd inst} {
+    global blamestuff curview commfd blameinst
+
+    while {[gets $fd line] >= 0} {
+       lappend blamestuff($inst) $line
+    }
+    if {![eof $fd]} {
+       return 1
+    }
+    unset commfd($inst)
+    unset blameinst
+    fconfigure $fd -blocking 1
+    if {[catch {close $fd} err]} {
+       error_popup [mc "Error running git blame: %s" $err]
+       return 0
+    }
+
+    set fname {}
+    set line [split [lindex $blamestuff($inst) 0] " "]
+    set id [lindex $line 0]
+    set lnum [lindex $line 1]
+    if {[string length $id] == 40 && [string is xdigit $id] &&
+       [string is digit -strict $lnum]} {
+       # look for "filename" line
+       foreach l $blamestuff($inst) {
+           if {[string match "filename *" $l]} {
+               set fname [string range $l 9 end]
+               break
+           }
+       }
+    }
+    if {$fname ne {}} {
+       # all looks good, select it
+       if {[commitinview $id $curview]} {
+           selectline [rowofcommit $id] 1 [list $fname $lnum]
+       } else {
+           error_popup [mc "That line comes from commit %s, \
+                            which is not in this view" [shortids $id]]
+       }
+    } else {
+       puts "oops couldn't parse git blame output"
+    }
+    return 0
+}
+
 # delete $dir when we see eof on $f (presumably because the child has exited)
 proc delete_at_eof {f dir} {
     while {[gets $f line] >= 0} {}
@@ -3440,6 +3539,7 @@ proc vieweditor {top n title} {
     frame $top.buts
     button $top.buts.ok -text [mc "OK"] -command [list newviewok $top $n]
     button $top.buts.can -text [mc "Cancel"] -command [list destroy $top]
+    bind $top <Escape> [list destroy $top]
     grid $top.buts.ok $top.buts.can
     grid columnconfigure $top.buts 0 -weight 1 -uniform a
     grid columnconfigure $top.buts 1 -weight 1 -uniform a
@@ -5748,6 +5848,7 @@ proc stopfinding {} {
        set fprogcoord 0
        adjustprogress
     }
+    stopblaming
 }
 
 proc findmore {} {
@@ -6152,7 +6253,7 @@ proc make_secsel {l} {
     $canv3 lower $t
 }
 
-proc selectline {l isnew} {
+proc selectline {l isnew {desired_loc {}}} {
     global canv ctext commitinfo selectedline
     global canvy0 linespc parents children curview
     global currentid sha1entry
@@ -6160,7 +6261,7 @@ proc selectline {l isnew} {
     global mergemax numcommits pending_select
     global cmitmode showneartags allcommits
     global targetrow targetid lastscrollrows
-    global autoselect
+    global autoselect jump_to_here
 
     catch {unset pending_select}
     $canv delete hover
@@ -6299,6 +6400,7 @@ proc selectline {l isnew} {
     $ctext conf -state disabled
     set commentend [$ctext index "end - 1c"]
 
+    set jump_to_here $desired_loc
     init_flist [mc "Comments"]
     if {$cmitmode eq "tree"} {
        gettree $id
@@ -6546,15 +6648,32 @@ proc getblobline {bf id} {
        $ctext insert end "$line\n"
     }
     if {[eof $bf]} {
+       global jump_to_here ctext_file_names commentend
+
        # delete last newline
        $ctext delete "end - 2c" "end - 1c"
        close $bf
+       if {$jump_to_here ne {} &&
+           [lindex $jump_to_here 0] eq [lindex $ctext_file_names 0]} {
+           set lnum [expr {[lindex $jump_to_here 1] +
+                           [lindex [split $commentend .] 0]}]
+           mark_ctext_line $lnum
+       }
        return 0
     }
     $ctext config -state disabled
     return [expr {$nl >= 1000? 2: 1}]
 }
 
+proc mark_ctext_line {lnum} {
+    global ctext markbgcolor
+
+    $ctext tag delete omark
+    $ctext tag add omark $lnum.0 "$lnum.0 + 1 line"
+    $ctext tag conf omark -background $markbgcolor
+    $ctext see $lnum.0
+}
+
 proc mergediff {id} {
     global diffmergeid mdifffd
     global diffids treediffs
@@ -6562,10 +6681,12 @@ proc mergediff {id} {
     global diffcontext
     global diffencoding
     global limitdiffs vfilelimit curview
+    global targetline
 
     set diffmergeid $id
     set diffids $id
     set treediffs($id) {}
+    set targetline {}
     # this doesn't seem to actually affect anything...
     set cmd [concat | git diff-tree --no-commit-id --cc -U$diffcontext $id]
     if {$limitdiffs && $vfilelimit($curview) ne {}} {
@@ -6587,7 +6708,7 @@ proc getmergediffline {mdf id np} {
     global diffmergeid ctext cflist mergemax
     global difffilestart mdifffd treediffs
     global ctext_file_names ctext_file_lines
-    global diffencoding
+    global diffencoding jump_to_here targetline diffline
 
     $ctext conf -state normal
     set nr 0
@@ -6611,9 +6732,17 @@ proc getmergediffline {mdf id np} {
            set l [expr {(78 - [string length $fname]) / 2}]
            set pad [string range "----------------------------------------" 1 $l]
            $ctext insert end "$pad $fname $pad\n" filesep
+           set targetline {}
+           if {$jump_to_here ne {} && [lindex $jump_to_here 0] eq $fname} {
+               set targetline [lindex $jump_to_here 1]
+           }
+           set diffline 0
        } elseif {[regexp {^@@} $line]} {
            set line [encoding convertfrom $diffencoding $line]
            $ctext insert end "$line\n" hunksep
+           if {[regexp { \+(\d+),\d+ @@} $line m nl]} {
+               set diffline $nl
+           }
        } elseif {[regexp {^[0-9a-f]{40}$} $line] || [regexp {^index} $line]} {
            # do nothing
        } else {
@@ -6653,6 +6782,15 @@ proc getmergediffline {mdf id np} {
                lappend tags m$num
            }
            $ctext insert end "$line\n" $tags
+           if {$targetline ne {} && $minuses eq {}} {
+               if {$diffline == $targetline} {
+                   set here [$ctext index "end - 1 line"]
+                   mark_ctext_line [lindex [split $here .] 0]
+                   set targetline {}
+               } else {
+                   incr diffline
+               }
+           }
        }
     }
     $ctext conf -state disabled
@@ -6840,7 +6978,7 @@ proc getblobdiffs {ids} {
     global diffcontext
     global ignorespace
     global limitdiffs vfilelimit curview
-    global diffencoding
+    global diffencoding targetline
 
     set cmd [diffcmd $ids "-p -C --no-commit-id -U$diffcontext"]
     if {$ignorespace} {
@@ -6853,6 +6991,7 @@ proc getblobdiffs {ids} {
        puts "error getting diffs: $err"
        return
     }
+    set targetline {}
     set diffinhdr 0
     set diffencoding [get_path_encoding {}]
     fconfigure $bdf -blocking 0 -encoding binary
@@ -6875,7 +7014,7 @@ proc setinlist {var i val} {
 
 proc makediffhdr {fname ids} {
     global ctext curdiffstart treediffs
-    global ctext_file_names
+    global ctext_file_names jump_to_here targetline diffline
 
     set i [lsearch -exact $treediffs($ids) $fname]
     if {$i >= 0} {
@@ -6885,6 +7024,11 @@ proc makediffhdr {fname ids} {
     set l [expr {(78 - [string length $fname]) / 2}]
     set pad [string range "----------------------------------------" 1 $l]
     $ctext insert $curdiffstart "$pad $fname $pad" filesep
+    set targetline {}
+    if {$jump_to_here ne {} && [lindex $jump_to_here 0] eq $fname} {
+       set targetline [lindex $jump_to_here 1]
+    }
+    set diffline 0
 }
 
 proc getblobdiffline {bdf ids} {
@@ -6892,7 +7036,7 @@ proc getblobdiffline {bdf ids} {
     global diffnexthead diffnextnote difffilestart
     global ctext_file_names ctext_file_lines
     global diffinhdr treediffs
-    global diffencoding
+    global diffencoding jump_to_here targetline diffline
 
     set nr 0
     $ctext conf -state normal
@@ -6941,6 +7085,7 @@ proc getblobdiffline {bdf ids} {
            set line [encoding convertfrom $diffencoding $line]
            $ctext insert end "$line\n" hunksep
            set diffinhdr 0
+           set diffline $f2l
 
        } elseif {$diffinhdr} {
            if {![string compare -length 12 "rename from " $line]} {
@@ -6974,6 +7119,7 @@ proc getblobdiffline {bdf ids} {
        } else {
            set line [encoding convertfrom $diffencoding $line]
            set x [string range $line 0 0]
+           set here [$ctext index "end - 1 chars"]
            if {$x == "-" || $x == "+"} {
                set tag [expr {$x == "+"}]
                $ctext insert end "$line\n" d$tag
@@ -6984,6 +7130,14 @@ proc getblobdiffline {bdf ids} {
                # or something else we don't recognize
                $ctext insert end "$line\n" hunksep
            }
+           if {$targetline ne {} && ($x eq " " || $x eq "+")} {
+               if {$diffline == $targetline} {
+                   mark_ctext_line [lindex [split $here .] 0]
+                   set targetline {}
+               } else {
+                   incr diffline
+               }
+           }
        }
     }
     $ctext conf -state disabled
@@ -7646,6 +7800,8 @@ proc mkpatch {} {
     frame $top.buts
     button $top.buts.gen -text [mc "Generate"] -command mkpatchgo
     button $top.buts.can -text [mc "Cancel"] -command mkpatchcan
+    bind $top <Key-Return> mkpatchgo
+    bind $top <Key-Escape> mkpatchcan
     grid $top.buts.gen $top.buts.can
     grid columnconfigure $top.buts 0 -weight 1 -uniform a
     grid columnconfigure $top.buts 1 -weight 1 -uniform a
@@ -7717,6 +7873,8 @@ proc mktag {} {
     frame $top.buts
     button $top.buts.gen -text [mc "Create"] -command mktaggo
     button $top.buts.can -text [mc "Cancel"] -command mktagcan
+    bind $top <Key-Return> mktaggo
+    bind $top <Key-Escape> mktagcan
     grid $top.buts.gen $top.buts.can
     grid columnconfigure $top.buts 0 -weight 1 -uniform a
     grid columnconfigure $top.buts 1 -weight 1 -uniform a
@@ -7820,6 +7978,8 @@ proc writecommit {} {
     frame $top.buts
     button $top.buts.gen -text [mc "Write"] -command wrcomgo
     button $top.buts.can -text [mc "Cancel"] -command wrcomcan
+    bind $top <Key-Return> wrcomgo
+    bind $top <Key-Escape> wrcomcan
     grid $top.buts.gen $top.buts.can
     grid columnconfigure $top.buts 0 -weight 1 -uniform a
     grid columnconfigure $top.buts 1 -weight 1 -uniform a
@@ -7867,6 +8027,8 @@ proc mkbranch {} {
     frame $top.buts
     button $top.buts.go -text [mc "Create"] -command [list mkbrgo $top]
     button $top.buts.can -text [mc "Cancel"] -command "catch {destroy $top}"
+    bind $top <Key-Return> [list mkbrgo $top]
+    bind $top <Key-Escape> "catch {destroy $top}"
     grid $top.buts.go $top.buts.can
     grid columnconfigure $top.buts 0 -weight 1 -uniform a
     grid columnconfigure $top.buts 1 -weight 1 -uniform a
@@ -7991,6 +8153,7 @@ proc resethead {} {
     button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
     pack $w.ok -side left -fill x -padx 20 -pady 20
     button $w.cancel -text [mc Cancel] -command "destroy $w"
+    bind $w <Key-Escape> [list destroy $w]
     pack $w.cancel -side right -fill x -padx 20 -pady 20
     bind $w <Visibility> "grab $w; focus $w"
     tkwait window $w
@@ -8168,6 +8331,7 @@ proc showrefs {} {
     pack $top.f.l -side left
     grid $top.f - -sticky ew -pady 2
     button $top.close -command [list destroy $top] -text [mc "Close"]
+    bind $top <Key-Escape> [list destroy $top]
     grid $top.close -
     grid columnconfigure $top 0 -weight 1
     grid rowconfigure $top 0 -weight 1
@@ -9519,6 +9683,8 @@ proc choosefont {font which} {
        frame $top.buts
        button $top.buts.ok -text [mc "OK"] -command fontok -default active
        button $top.buts.can -text [mc "Cancel"] -command fontcan -default normal
+       bind $top <Key-Return> fontok
+       bind $top <Key-Escape> fontcan
        grid $top.buts.ok $top.buts.can
        grid columnconfigure $top.buts 0 -weight 1 -uniform a
        grid columnconfigure $top.buts 1 -weight 1 -uniform a
@@ -9585,7 +9751,7 @@ proc chg_fontparam {v sub op} {
 proc doprefs {} {
     global maxwidth maxgraphpct
     global oldprefs prefstop showneartags showlocalchanges
-    global bgcolor fgcolor ctext diffcolors selectbgcolor
+    global bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
     global tabstop limitdiffs autoselect extdifftool perfile_attrs
 
     set top .gitkprefs
@@ -9678,6 +9844,12 @@ proc doprefs {} {
                      "diff hunk header" \
                      [list $ctext tag conf hunksep -foreground]]
     grid x $top.hunksepbut $top.hunksep -sticky w
+    label $top.markbgsep -padx 40 -relief sunk -background $markbgcolor
+    button $top.markbgbut -text [mc "Marked line bg"] -font optionfont \
+       -command [list choosecolor markbgcolor {} $top.markbgsep \
+                     [mc "marked line background"] \
+                     [list $ctext tag conf omark -background]]
+    grid x $top.markbgbut $top.markbgsep -sticky w
     label $top.selbgsep -padx 40 -relief sunk -background $selectbgcolor
     button $top.selbgbut -text [mc "Select bg"] -font optionfont \
        -command [list choosecolor selectbgcolor {} $top.selbgsep background setselbg]
@@ -9692,6 +9864,8 @@ proc doprefs {} {
     frame $top.buts
     button $top.buts.ok -text [mc "OK"] -command prefsok -default active
     button $top.buts.can -text [mc "Cancel"] -command prefscan -default normal
+    bind $top <Key-Return> prefsok
+    bind $top <Key-Escape> prefscan
     grid $top.buts.ok $top.buts.can
     grid columnconfigure $top.buts 0 -weight 1 -uniform a
     grid columnconfigure $top.buts 1 -weight 1 -uniform a
@@ -10223,6 +10397,7 @@ set diffcolors {red "#00a000" blue}
 set diffcontext 3
 set ignorespace 0
 set selectbgcolor gray85
+set markbgcolor "#e0e0ff"
 
 set circlecolors {white blue gray blue blue}