X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=lib%2Fblame.tcl;h=352aa19421034033968f6a311b1e8948ac01e25f;hb=66c75a5c9f7434d857d836440dc1c3046c59b5f3;hp=44c2bb9d841735f0c99f45f773289c363afe7a61;hpb=0dfed77b3cc81342aee4c81e477d636a378c51cb;p=git.git diff --git a/lib/blame.tcl b/lib/blame.tcl index 44c2bb9d8..352aa1942 100644 --- a/lib/blame.tcl +++ b/lib/blame.tcl @@ -21,18 +21,25 @@ 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 status ; # text variable bound to status bar +field status ; # status mega-widget instance field old_height ; # last known height of $w.file_pane # Tk UI colors # -field active_color #c0edc5 -field group_colors { +variable active_color #c0edc5 +variable group_colors { #d6d6d6 #e1e1e1 #ececec } +# Switches for original location detection +# +variable original_options [list -C -C] +if {[git-version >= 1.5.3]} { + lappend original_options -w ; # ignore indentation changes +} + # Current blame data; cleared/reset on each load # field commit ; # input commit to blame @@ -42,11 +49,9 @@ field current_fd {} ; # background process running field highlight_line -1 ; # current line selected field highlight_column {} ; # current commit column selected field highlight_commit {} ; # sha1 of commit selected -field old_bgcolor {} ; # background of current selection field total_lines 0 ; # total length of file field blame_lines 0 ; # number of lines computed -field have_commit ; # array commit -> 1 field amov_data ; # list of {commit origfile origline} field asim_data ; # list of {commit origfile origline} @@ -62,17 +67,19 @@ field tooltip_commit {} ; # Commit(s) in tooltip constructor new {i_commit i_path} { global cursor_ptr + variable active_color + variable group_colors set commit $i_commit set path $i_path make_toplevel top w - wm title $top "[appname] ([reponame]): File Viewer" + wm title $top [append "[appname] ([reponame]): " [mc "File Viewer"]] - frame $w.header -background orange + frame $w.header -background gold label $w.header.commit_l \ - -text {Commit:} \ - -background orange \ + -text [mc "Commit:"] \ + -background gold \ -anchor w \ -justify left set w_back $w.header.commit_b @@ -81,8 +88,8 @@ constructor new {i_commit i_path} { -borderwidth 0 \ -relief flat \ -state disabled \ - -background orange \ - -activebackground orange + -background gold \ + -activebackground gold bind $w_back " if {\[$w_back cget -state\] eq {normal}} { [cb _history_menu] @@ -90,17 +97,17 @@ constructor new {i_commit i_path} { " label $w.header.commit \ -textvariable @commit \ - -background orange \ + -background gold \ -anchor w \ -justify left label $w.header.path_l \ - -text {File:} \ - -background orange \ + -text [mc "File:"] \ + -background gold \ -anchor w \ -justify left set w_path $w.header.path label $w_path \ - -background orange \ + -background gold \ -anchor w \ -justify left pack $w.header.commit_l -side left @@ -235,21 +242,18 @@ constructor new {i_commit i_path} { pack $w.file_pane.cm.sbx -side bottom -fill x pack $w_cviewer -expand 1 -fill both - frame $w.status \ - -borderwidth 1 \ - -relief sunken - label $w.status.l \ - -textvariable @status \ - -anchor w \ - -justify left - pack $w.status.l -side left + set status [::status_bar::new $w.status] menu $w.ctxm -tearoff 0 $w.ctxm add command \ - -label "Copy Commit" \ + -label [mc "Copy Commit"] \ -command [cb _copycommit] foreach i $w_columns { + for {set g 0} {$g < [llength $group_colors]} {incr g} { + $i tag conf color$g -background [lindex $group_colors $g] + } + $i conf -cursor $cursor_ptr $i conf -yscrollcommand [list many2scrollbar \ $w_columns yview $w.file_pane.out.sby] @@ -268,6 +272,8 @@ constructor new {i_commit i_path} { set cursorW %W tk_popup $w.ctxm %X %Y " + bind $i "[list focus $w_cviewer];break" + bind $i "[list focus $w_cviewer];break" } foreach i [concat $w_columns $w_cviewer] { @@ -283,9 +289,10 @@ 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 "[list focus $w_file];break" bind $w_cviewer [list focus $w_cviewer] - bind $top [list focus $top] - bind $w_file [list delete_this $this] + bind $w_file [list focus $w_file] grid configure $w.header -sticky ew grid configure $w.file_pane -sticky nsew @@ -297,8 +304,9 @@ 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} - if {$req_h < 400} {set req_h 400} + if {$req_h < $scr_h} {set req_h $scr_h} set g "${req_w}x${req_h}" wm geometry $top $g update @@ -314,6 +322,8 @@ constructor new {i_commit i_path} { } method _load {jump} { + variable group_colors + _hide_tooltip $this if {$total_lines != 0 || $current_fd ne {}} { @@ -325,8 +335,10 @@ method _load {jump} { foreach i $w_columns { $i conf -state normal $i delete 0.0 end - foreach cmit [array names have_commit] { - $i tag delete g$cmit + foreach g [$i tag names] { + if {[regexp {^g[0-9a-f]{40}$} $g]} { + $i tag delete $g + } } $i conf -state disabled } @@ -339,20 +351,6 @@ method _load {jump} { set highlight_column {} set highlight_commit {} set total_lines 0 - array unset have_commit - } - - if {[winfo exists $w.status.c]} { - $w.status.c coords bar 0 0 0 20 - } else { - canvas $w.status.c \ - -width 100 \ - -height [expr {int([winfo reqheight $w.status.l] * 0.6)}] \ - -borderwidth 1 \ - -relief groove \ - -highlightt 0 - $w.status.c create rectangle 0 0 0 20 -tags bar -fill navy - pack $w.status.c -side right } if {$history eq {}} { @@ -368,13 +366,13 @@ method _load {jump} { set amov_data [list [list]] set asim_data [list [list]] - set status "Loading $commit:[escape_path $path]..." + $status show [mc "Reading %s..." "$commit:[escape_path $path]"] $w_path conf -text [escape_path $path] if {$commit eq {}} { set fd [open $path r] + fconfigure $fd -eofchar {} } else { - set cmd [list git cat-file blob "$commit:$path"] - set fd [open "| $cmd" r] + set fd [git_read cat-file blob "$commit:$path"] } fconfigure $fd -blocking 0 -translation lf -encoding binary fileevent $fd readable [cb _read_file $fd $jump] @@ -470,30 +468,35 @@ method _read_file {fd jump} { $w_file yview moveto [lindex $jump 3] } - _exec_blame $this $w_asim @asim_data [list] {} + _exec_blame $this $w_asim @asim_data \ + [list] \ + { copy/move tracking} } } ifdeleted { catch {close $fd} } method _exec_blame {cur_w cur_d options cur_s} { - set cmd [list nice git blame] - set cmd [concat $cmd $options] - lappend cmd --incremental + lappend options --incremental if {$commit eq {}} { - lappend cmd --contents $path + lappend options --contents $path } else { - lappend cmd $commit + lappend options $commit } - lappend cmd -- $path - set fd [open "| $cmd" r] + lappend options -- $path + set fd [eval git_read --nice blame $options] fconfigure $fd -blocking 0 -translation lf -encoding binary - fileevent $fd readable [cb _read_blame $fd $cur_w $cur_d $cur_s] + fileevent $fd readable [cb _read_blame $fd $cur_w $cur_d] set current_fd $fd set blame_lines 0 - _status $this $cur_s + + $status start \ + "Loading$cur_s annotations..." \ + {lines annotated} } -method _read_blame {fd cur_w cur_d cur_s} { +method _read_blame {fd cur_w cur_d} { upvar #0 $cur_d line_data + variable group_colors + variable original_options if {$fd ne $current_fd} { catch {close $fd} @@ -508,16 +511,6 @@ method _read_blame {fd cur_w cur_d cur_s} { set r_orig_line $original_line set r_final_line $final_line set r_line_count $line_count - - if {[catch {set g $have_commit($cmit)}]} { - set bg [lindex $group_colors 0] - set group_colors [lrange $group_colors 1 end] - lappend group_colors $bg - foreach i $w_columns { - $i tag conf g$cmit -background $bg - } - set have_commit($cmit) 1 - } } elseif {[string match {filename *} $line]} { set file [string range $line 9 end] set n $r_line_count @@ -540,6 +533,10 @@ method _read_blame {fd cur_w cur_d cur_s} { set a_name {} catch {set a_name $header($cmit,author)} while {$a_name ne {}} { + if {$author_abbr ne {} + && [string index $a_name 0] eq {'}} { + regsub {^'[^']+'\s+} $a_name {} a_name + } if {![regexp {^([[:upper:]])} $a_name _a]} break append author_abbr $_a unset _a @@ -563,6 +560,30 @@ method _read_blame {fd cur_w cur_d cur_s} { incr first_lno -1 } + set color {} + if {$first_lno < $lno} { + foreach g [$w_file tag names $first_lno.0] { + if {[regexp {^color[0-9]+$} $g]} { + set color $g + break + } + } + } else { + set i [lsort [concat \ + [$w_file tag names "[expr {$first_lno - 1}].0"] \ + [$w_file tag names "[expr {$lno + $n}].0"] \ + ]] + for {set g 0} {$g < [llength $group_colors]} {incr g} { + if {[lsearch -sorted -exact $i color$g] == -1} { + set color color$g + break + } + } + } + if {$color eq {}} { + set color color0 + } + while {$n > 0} { set lno_e "$lno.0 lineend + 1c" if {[lindex $line_data $lno] ne {}} { @@ -583,6 +604,14 @@ method _read_blame {fd cur_w cur_d cur_s} { } foreach i $w_columns { + if {$cur_w eq $w_amov} { + for {set g 0} \ + {$g < [llength $group_colors]} \ + {incr g} { + $i tag remove color$g $lno.0 $lno_e + } + $i tag add $color $lno.0 $lno_e + } $i tag add g$cmit $lno.0 $lno_e } @@ -616,6 +645,18 @@ method _read_blame {fd cur_w cur_d cur_s} { } else { $cur_w insert $lno.0 { |} } + + if {$cur_w eq $w_amov} { + foreach i $w_columns { + for {set g 0} \ + {$g < [llength $group_colors]} \ + {incr g} { + $i tag remove color$g $lno.0 $lno_e + } + $i tag add $color $lno.0 $lno_e + } + } + incr lno } @@ -629,30 +670,17 @@ method _read_blame {fd cur_w cur_d cur_s} { close $fd if {$cur_w eq $w_asim} { _exec_blame $this $w_amov @amov_data \ - [list -M -C -C] \ - { move/copy tracking} + $original_options \ + { original location} } else { set current_fd {} - set status {Annotation complete.} - destroy $w.status.c + $status stop {Annotation complete.} } } else { - _status $this $cur_s + $status update $blame_lines $total_lines } } ifdeleted { catch {close $fd} } -method _status {cur_s} { - set have $blame_lines - set total $total_lines - set pdone 0 - if {$total} {set pdone [expr {100 * $have / $total}]} - - set status [format \ - "Loading%s annotations... %i of %i lines annotated (%2i%%)" \ - $cur_s $have $total $pdone] - $w.status.c coords bar 0 0 $pdone 20 -} - method _click {cur_w pos} { set lno [lindex [split [$cur_w index $pos] .] 0] _showcommit $this $cur_w $lno @@ -678,20 +706,21 @@ method _load_commit {cur_w cur_d pos} { method _showcommit {cur_w lno} { global repo_config + variable active_color if {$highlight_commit ne {}} { foreach i $w_columns { - $i tag conf g$highlight_commit -background $old_bgcolor + $i tag conf g$highlight_commit -background {} $i tag lower g$highlight_commit } } - if {$cur_w eq $w_amov} { - set dat [lindex $amov_data $lno] - set highlight_column $w_amov - } else { + if {$cur_w eq $w_asim} { set dat [lindex $asim_data $lno] set highlight_column $w_asim + } else { + set dat [lindex $amov_data $lno] + set highlight_column $w_amov } $w_cviewer conf -state normal @@ -704,7 +733,6 @@ method _showcommit {cur_w lno} { set cmit [lindex $dat 0] set file [lindex $dat 1] - set old_bgcolor [$w_file tag cget g$cmit -background] foreach i $w_columns { $i tag conf g$cmit -background $active_color $i tag raise g$cmit @@ -715,25 +743,19 @@ method _showcommit {cur_w lno} { set author_time {} catch {set author_name $header($cmit,author)} catch {set author_email $header($cmit,author-mail)} - catch {set author_time [clock format \ - $header($cmit,author-time) \ - -format {%Y-%m-%d %H:%M:%S} - ]} + catch {set author_time [format_date $header($cmit,author-time)]} set committer_name {} set committer_email {} set committer_time {} catch {set committer_name $header($cmit,committer)} catch {set committer_email $header($cmit,committer-mail)} - catch {set committer_time [clock format \ - $header($cmit,committer-time) \ - -format {%Y-%m-%d %H:%M:%S} - ]} + catch {set committer_time [format_date $header($cmit,committer-time)]} if {[catch {set msg $header($cmit,message)}]} { set msg {} catch { - set fd [open "| git cat-file commit $cmit" r] + 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 @@ -743,15 +765,20 @@ method _showcommit {cur_w lno} { set enc [string tolower [string range $line 9 end]] } } - set msg [encoding convertfrom $enc [read $fd]] - set msg [string trim $msg] + set msg [read $fd] close $fd - 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 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] } set header($cmit,message) $msg } @@ -846,6 +873,11 @@ method _open_tooltip {cur_w} { set org [lindex $amov_data $lno] } + if {$dat eq {}} { + _hide_tooltip $this + return + } + set cmit [lindex $dat 0] set tooltip_commit [list $cmit] @@ -854,17 +886,16 @@ method _open_tooltip {cur_w} { set author_time {} catch {set author_name $header($cmit,author)} catch {set summary $header($cmit,summary)} - catch {set author_time [clock format \ - $header($cmit,author-time) \ - -format {%Y-%m-%d %H:%M:%S} - ]} + catch {set author_time [format_date $header($cmit,author-time)]} $tooltip_t insert end "commit $cmit\n" $tooltip_t insert end "$author_name $author_time\n" $tooltip_t insert end "$summary" if {$org ne {} && [lindex $org 0] ne $cmit} { - $tooltip_t insert 0.0 "Moved Here By:\n" section_header + set save [$tooltip_t get 0.0 end] + $tooltip_t delete 0.0 end + set cmit [lindex $org 0] set file [lindex $org 1] lappend tooltip_commit $cmit @@ -874,22 +905,21 @@ method _open_tooltip {cur_w} { set author_time {} catch {set author_name $header($cmit,author)} catch {set summary $header($cmit,summary)} - catch {set author_time [clock format \ - $header($cmit,author-time) \ - -format {%Y-%m-%d %H:%M:%S} - ]} + catch {set author_time [foramt_date $header($cmit,author-time)]} - $tooltip_t insert end "\n\n" $tooltip_t insert end "Originally By:\n" section_header $tooltip_t insert end "commit $cmit\n" $tooltip_t insert end "$author_name $author_time\n" - $tooltip_t insert end "$summary" + $tooltip_t insert end "$summary\n" if {$file ne $path} { - $tooltip_t insert end "\n" - $tooltip_t insert end "File: " section_header - $tooltip_t insert end $file + $tooltip_t insert end "In File: " section_header + $tooltip_t insert end "$file\n" } + + $tooltip_t insert end "\n" + $tooltip_t insert end "Copied Or Moved Here By:\n" section_header + $tooltip_t insert end $save } $tooltip_t conf -state disabled