X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=lib%2Fblame.tcl;h=2137ec9684d0acdb386e6b50e1b41aa7705c9746;hb=9cb268c426ccb2bb836418caad669476b5dd1933;hp=1106975775e86cea028b42977521ea255d698468;hpb=823f7cf81dbed741c3a645913d7461e9bc04e0d2;p=git.git diff --git a/lib/blame.tcl b/lib/blame.tcl index 110697577..2137ec968 100644 --- a/lib/blame.tcl +++ b/lib/blame.tcl @@ -21,9 +21,11 @@ field w_amov ; # text column: annotations + move tracking field w_asim ; # text column: annotations (simple computation) field w_file ; # text column: actual file data field w_cviewer ; # pane showing commit message +field finder ; # find mini-dialog frame field status ; # status mega-widget instance field old_height ; # last known height of $w.file_pane + # Tk UI colors # variable active_color #c0edc5 @@ -58,8 +60,8 @@ field tooltip_t {} ; # Text widget in $tooltip_wm field tooltip_timer {} ; # Current timer event for our tooltip field tooltip_commit {} ; # Commit(s) in tooltip -constructor new {i_commit i_path} { - global cursor_ptr +constructor new {i_commit i_path i_jump} { + global cursor_ptr M1B M1T have_tk85 use_ttk NS variable active_color variable group_colors @@ -69,15 +71,17 @@ constructor new {i_commit i_path} { make_toplevel top w wm title $top [append "[appname] ([reponame]): " [mc "File Viewer"]] - frame $w.header -background gold - label $w.header.commit_l \ + set font_w [font measure font_diff "0"] + + gold_frame $w.header + tlabel $w.header.commit_l \ -text [mc "Commit:"] \ -background gold \ -foreground black \ -anchor w \ -justify left set w_back $w.header.commit_b - label $w_back \ + tlabel $w_back \ -image ::blame::img_back_arrow \ -borderwidth 0 \ -relief flat \ @@ -90,20 +94,20 @@ constructor new {i_commit i_path} { [cb _history_menu] } " - label $w.header.commit \ + tlabel $w.header.commit \ -textvariable @commit \ -background gold \ -foreground black \ -anchor w \ -justify left - label $w.header.path_l \ + tlabel $w.header.path_l \ -text [mc "File:"] \ -background gold \ -foreground black \ -anchor w \ -justify left set w_path $w.header.path - label $w_path \ + tlabel $w_path \ -background gold \ -foreground black \ -anchor w \ @@ -114,9 +118,9 @@ constructor new {i_commit i_path} { pack $w_path -fill x -side right pack $w.header.path_l -side right - panedwindow $w.file_pane -orient vertical - frame $w.file_pane.out - frame $w.file_pane.cm + panedwindow $w.file_pane -orient vertical -borderwidth 0 -sashwidth 3 + frame $w.file_pane.out -relief flat -borderwidth 1 + frame $w.file_pane.cm -relief sunken -borderwidth 1 $w.file_pane add $w.file_pane.out \ -sticky nsew \ -minsize 100 \ @@ -197,13 +201,18 @@ constructor new {i_commit i_path} { -width 80 \ -xscrollcommand [list $w.file_pane.out.sbx set] \ -font font_diff + if {$have_tk85} { + $w_file configure -inactiveselectbackground darkblue + } + $w_file tag conf found \ + -background yellow set w_columns [list $w_amov $w_asim $w_line $w_file] - scrollbar $w.file_pane.out.sbx \ + ${NS}::scrollbar $w.file_pane.out.sbx \ -orient h \ -command [list $w_file xview] - scrollbar $w.file_pane.out.sby \ + ${NS}::scrollbar $w.file_pane.out.sby \ -orient v \ -command [list scrollbar2many $w_columns yview] eval grid $w_columns $w.file_pane.out.sby -sticky nsew @@ -217,6 +226,11 @@ constructor new {i_commit i_path} { -weight 1 grid rowconfigure $w.file_pane.out 0 -weight 1 + set finder [::searchbar::new \ + $w.file_pane.out.ff $w_file \ + -column [expr {[llength $w_columns] - 1}] \ + ] + set w_cviewer $w.file_pane.cm.t text $w_cviewer \ -background white \ @@ -240,10 +254,10 @@ constructor new {i_commit i_path} { -background $active_color \ -font font_ui $w_cviewer tag raise sel - scrollbar $w.file_pane.cm.sbx \ + ${NS}::scrollbar $w.file_pane.cm.sbx \ -orient h \ -command [list $w_cviewer xview] - scrollbar $w.file_pane.cm.sby \ + ${NS}::scrollbar $w.file_pane.cm.sby \ -orient v \ -command [list $w_cviewer yview] pack $w.file_pane.cm.sby -side right -fill y @@ -256,9 +270,20 @@ constructor new {i_commit i_path} { $w.ctxm add command \ -label [mc "Copy Commit"] \ -command [cb _copycommit] + $w.ctxm add separator + $w.ctxm add command \ + -label [mc "Find Text..."] \ + -accelerator F7 \ + -command [list searchbar::show $finder] + menu $w.ctxm.enc + build_encoding_menu $w.ctxm.enc [cb _setencoding] + $w.ctxm add cascade \ + -label [mc "Encoding"] \ + -menu $w.ctxm.enc $w.ctxm add command \ -label [mc "Do Full Copy Detection"] \ -command [cb _fullcopyblame] + $w.ctxm add separator $w.ctxm add command \ -label [mc "Show History Context"] \ -command [cb _gitkcommit] @@ -271,9 +296,15 @@ constructor new {i_commit i_path} { $i tag conf color$g -background [lindex $group_colors $g] } + if {$i eq $w_file} { + $w_file tag raise found + } + $i tag raise sel + $i conf -cursor $cursor_ptr - $i conf -yscrollcommand [list many2scrollbar \ - $w_columns yview $w.file_pane.out.sby] + $i conf -yscrollcommand \ + "[list ::searchbar::scrolled $finder] + [list many2scrollbar $w_columns yview $w.file_pane.out.sby]" bind $i " [cb _hide_tooltip] [cb _click $i @%x,%y] @@ -290,7 +321,7 @@ constructor new {i_commit i_path} { tk_popup $w.ctxm %X %Y " bind $i "[list focus $w_cviewer];break" - bind $i "[list focus $w_cviewer];break" + bind $i "[cb _focus_search $w_cviewer];break" } foreach i [concat $w_columns $w_cviewer] { @@ -306,10 +337,15 @@ constructor new {i_commit i_path} { bind $i {catch {%W yview scroll 1 pages};break} } - bind $w_cviewer "[list focus $w_file];break" + bind $w_cviewer "[cb _focus_search $w_file];break" bind $w_cviewer "[list focus $w_file];break" - bind $w_cviewer [list focus $w_cviewer] - bind $w_file [list focus $w_file] + bind $w_cviewer [list focus $w_cviewer] + bind $w_file [cb _focus_search $w_file] + bind $top [list searchbar::show $finder] + bind $top [list searchbar::hide $finder] + bind $top [list searchbar::find_next $finder] + bind $top [list searchbar::find_prev $finder] + catch { bind $top [list searchbar::find_prev $finder] } grid configure $w.header -sticky ew grid configure $w.file_pane -sticky nsew @@ -321,9 +357,14 @@ constructor new {i_commit i_path} { set req_w [winfo reqwidth $top] set req_h [winfo reqheight $top] - set scr_h [expr {[winfo screenheight $top] - 100}] - if {$req_w < 600} {set req_w 600} + set scr_w [expr {[winfo screenwidth $top] - 40}] + set scr_h [expr {[winfo screenheight $top] - 120}] + set opt_w [expr {$font_w * (80 + 5*3 + 3)}] + if {$req_w < $opt_w} {set req_w $opt_w} + if {$req_w > $scr_w} {set req_w $scr_w} + set opt_h [expr {$req_w*4/3}] if {$req_h < $scr_h} {set req_h $scr_h} + if {$req_h > $opt_h} {set req_h $opt_h} set g "${req_w}x${req_h}" wm geometry $top $g update @@ -331,14 +372,29 @@ constructor new {i_commit i_path} { set old_height [winfo height $w.file_pane] $w.file_pane sash place 0 \ [lindex [$w.file_pane sash coord 0] 0] \ - [expr {int($old_height * 0.70)}] + [expr {int($old_height * 0.80)}] bind $w.file_pane \ "if {{$w.file_pane} eq {%W}} {[cb _resize %h]}" wm protocol $top WM_DELETE_WINDOW "destroy $top" - bind $top [cb _kill] + bind $top [cb _handle_destroy %W] + + _load $this $i_jump +} - _load $this {} +method _focus_search {win} { + if {[searchbar::visible $finder]} { + focus [searchbar::editor $finder] + } else { + focus $win + } +} + +method _handle_destroy {win} { + if {$win eq $w} { + _kill $this + delete_this + } } method _kill {} { @@ -393,13 +449,33 @@ method _load {jump} { $status show [mc "Reading %s..." "$commit:[escape_path $path]"] $w_path conf -text [escape_path $path] + + set do_textconv 0 + if {![is_config_false gui.textconv] && [git-version >= 1.7.2]} { + set filter [gitattr $path diff set] + set textconv [get_config [join [list diff $filter textconv] .]] + if {$filter ne {set} && $textconv ne {}} { + set do_textconv 1 + } + } if {$commit eq {}} { - set fd [open $path r] + if {$do_textconv ne 0} { + set fd [open |[list $textconv $path] r] + } else { + set fd [open $path r] + } fconfigure $fd -eofchar {} } else { - set fd [git_read cat-file blob "$commit:$path"] + if {$do_textconv ne 0} { + set fd [git_read cat-file --textconv "$commit:$path"] + } else { + set fd [git_read cat-file blob "$commit:$path"] + } } - fconfigure $fd -blocking 0 -translation lf -encoding binary + fconfigure $fd \ + -blocking 0 \ + -translation lf \ + -encoding [get_path_encoding $path] fileevent $fd readable [cb _read_file $fd $jump] set current_fd $fd } @@ -500,7 +576,7 @@ method _read_file {fd jump} { } ifdeleted { catch {close $fd} } method _exec_blame {cur_w cur_d options cur_s} { - lappend options --incremental + lappend options --incremental --encoding=utf-8 if {$commit eq {}} { lappend options --contents $path } else { @@ -508,7 +584,7 @@ method _exec_blame {cur_w cur_d options cur_s} { } lappend options -- $path set fd [eval git_read --nice blame $options] - fconfigure $fd -blocking 0 -translation lf -encoding binary + fconfigure $fd -blocking 0 -translation lf -encoding utf-8 fileevent $fd readable [cb _read_blame $fd $cur_w $cur_d] set current_fd $fd set blame_lines 0 @@ -788,6 +864,16 @@ method _click {cur_w pos} { _showcommit $this $cur_w $lno } +method _setencoding {enc} { + force_path_encoding $path $enc + _load $this [list \ + $highlight_column \ + $highlight_line \ + [lindex [$w_file xview] 0] \ + [lindex [$w_file yview] 0] \ + ] +} + method _load_commit {cur_w cur_d pos} { upvar #0 $cur_d line_data set lno [lindex [split [$cur_w index $pos] .] 0] @@ -846,6 +932,10 @@ method _showcommit {cur_w lno} { foreach i $w_columns { $i tag conf g$cmit -background $active_color $i tag raise g$cmit + if {$i eq $w_file} { + $w_file tag raise found + } + $i tag raise sel } set author_name {} @@ -867,9 +957,8 @@ method _showcommit {cur_w lno} { catch { set fd [git_read cat-file commit $cmit] fconfigure $fd -encoding binary -translation lf - if {[catch {set enc $repo_config(i18n.commitencoding)}]} { - set enc utf-8 - } + # By default commits are assumed to be in utf-8 + set enc utf-8 while {[gets $fd line] > 0} { if {[string match {encoding *} $line]} { set enc [string tolower [string range $line 9 end]] @@ -881,12 +970,6 @@ method _showcommit {cur_w lno} { set enc [tcl_encoding $enc] if {$enc ne {}} { set msg [encoding convertfrom $enc $msg] - set author_name [encoding convertfrom $enc $author_name] - set committer_name [encoding convertfrom $enc $committer_name] - set header($cmit,author) $author_name - set header($cmit,committer) $committer_name - set header($cmit,summary) \ - [encoding convertfrom $enc $header($cmit,summary)] } set msg [string trim $msg] } @@ -942,9 +1025,20 @@ method _format_offset_date {base offset} { } method _gitkcommit {} { + global nullid + set dat [_get_click_amov_info $this] if {$dat ne {}} { set cmit [lindex $dat 0] + + # If the line belongs to the working copy, use HEAD instead + if {$cmit eq $nullid} { + if {[catch {set cmit [git rev-parse --verify HEAD]} err]} { + error_popup [strcat [mc "Cannot find HEAD commit:"] "\n\n$err"] + return; + } + } + set radius [get_config gui.blamehistoryctx] set cmdline [list --select-commit=$cmit] @@ -981,12 +1075,20 @@ method _gitkcommit {} { } method _blameparent {} { + global nullid + set dat [_get_click_amov_info $this] if {$dat ne {}} { set cmit [lindex $dat 0] set new_path [lindex $dat 1] - if {[catch {set cparent [git rev-parse --verify "$cmit^"]}]} { + # Allow using Blame Parent on lines modified in the working copy + if {$cmit eq $nullid} { + set parent_ref "HEAD" + } else { + set parent_ref "$cmit^" + } + if {[catch {set cparent [git rev-parse --verify $parent_ref]} err]} { error_popup [strcat [mc "Cannot find parent commit:"] "\n\n$err"] return; } @@ -996,8 +1098,12 @@ method _blameparent {} { # Generate a diff between the commit and its parent, # and use the hunks to update the line number. # Request zero context to simplify calculations. - if {[catch {set fd [eval git_read diff-tree \ - --unified=0 $cparent $cmit $new_path]} err]} { + if {$cmit eq $nullid} { + set diffcmd [list diff-index --unified=0 $cparent -- $new_path] + } else { + set diffcmd [list diff-tree --unified=0 $cparent $cmit -- $new_path] + } + if {[catch {set fd [eval git_read $diffcmd]} err]} { $status stop [mc "Unable to display parent"] error_popup [strcat [mc "Error loading diff:"] "\n\n$err"] return @@ -1156,6 +1262,18 @@ method _open_tooltip {cur_w} { $tooltip_t conf -state disabled _position_tooltip $this + + # On MacOS raising a window causes it to acquire focus. + # Tk 8.5 on MacOS seems to properly support wm transient, + # so we can safely counter the effect there. + if {$::have_tk85 && [is_MacOSX]} { + update + if {$w eq {}} { + raise . + } else { + raise $w + } + } } method _position_tooltip {} { @@ -1179,7 +1297,9 @@ method _position_tooltip {} { append g $pos_y wm geometry $tooltip_wm $g - raise $tooltip_wm + if {![is_MacOSX]} { + raise $tooltip_wm + } } method _hide_tooltip {} {