@@ -2296,6 +2296,7 @@ proc makewindow {} {
2296
2296
global diff_menu
2297
2297
set diff_menu .diffctxmenu
2298
2298
makemenu $diff_menu {
2299
+ {mc " Show origin of this line" command show_line_source}
2299
2300
{mc " Run git gui blame on this line" command {external_blame_diff}}
2300
2301
}
2301
2302
$diff_menu configure -tearoff 0
@@ -2830,9 +2831,15 @@ proc treeclick {w x y} {
2830
2831
}
2831
2832
2832
2833
proc setfilelist {id} {
2833
- global treefilelist cflist
2834
+ global treefilelist cflist jump_to_here
2834
2835
2835
2836
treeview $cflist $treefilelist($id) 0
2837
+ if {$jump_to_here ne {}} {
2838
+ set f [lindex $jump_to_here 0]
2839
+ if {[lsearch -exact $treefilelist($id) $f ] >= 0} {
2840
+ showfile $f
2841
+ }
2842
+ }
2836
2843
}
2837
2844
2838
2845
image create bitmap tri-rt -background black -foreground blue -data {
@@ -3256,6 +3263,91 @@ proc external_blame {parent_idx {line {}}} {
3256
3263
}
3257
3264
}
3258
3265
3266
+ proc show_line_source {} {
3267
+ global cmitmode currentid parents curview blamestuff blameinst
3268
+ global diff_menu_line diff_menu_filebase flist_menu_file
3269
+
3270
+ if {$cmitmode eq " tree" } {
3271
+ set id $currentid
3272
+ set line [expr {$diff_menu_line - $diff_menu_filebase }]
3273
+ } else {
3274
+ set h [find_hunk_blamespec $diff_menu_filebase $diff_menu_line ]
3275
+ if {$h eq {}} return
3276
+ set pi [lindex $h 0]
3277
+ if {$pi == 0} {
3278
+ mark_ctext_line $diff_menu_line
3279
+ return
3280
+ }
3281
+ set id [lindex $parents($curview,$currentid) [expr {$pi - 1}]]
3282
+ set line [lindex $h 1]
3283
+ }
3284
+ if {[catch {
3285
+ set f [open [list | git blame -p -L$line ,+1 $id -- $flist_menu_file ] r]
3286
+ } err]} {
3287
+ error_popup [mc " Couldn't start git blame: %s" $err ]
3288
+ return
3289
+ }
3290
+ fconfigure $f -blocking 0
3291
+ set i [reg_instance $f ]
3292
+ set blamestuff($i ) {}
3293
+ set blameinst $i
3294
+ filerun $f [list read_line_source $f $i ]
3295
+ }
3296
+
3297
+ proc stopblaming {} {
3298
+ global blameinst
3299
+
3300
+ if {[info exists blameinst]} {
3301
+ stop_instance $blameinst
3302
+ unset blameinst
3303
+ }
3304
+ }
3305
+
3306
+ proc read_line_source {fd inst} {
3307
+ global blamestuff curview commfd blameinst
3308
+
3309
+ while {[gets $fd line] >= 0} {
3310
+ lappend blamestuff($inst ) $line
3311
+ }
3312
+ if {![eof $fd ]} {
3313
+ return 1
3314
+ }
3315
+ unset commfd($inst )
3316
+ unset blameinst
3317
+ fconfigure $fd -blocking 1
3318
+ if {[catch {close $fd } err]} {
3319
+ error_popup [mc " Error running git blame: %s" $err ]
3320
+ return 0
3321
+ }
3322
+
3323
+ set fname {}
3324
+ set line [split [lindex $blamestuff($inst) 0] " " ]
3325
+ set id [lindex $line 0]
3326
+ set lnum [lindex $line 1]
3327
+ if {[string length $id ] == 40 && [string is xdigit $id ] &&
3328
+ [string is digit -strict $lnum ]} {
3329
+ # look for "filename" line
3330
+ foreach l $blamestuff($inst) {
3331
+ if {[string match " filename *" $l ]} {
3332
+ set fname [string range $l 9 end]
3333
+ break
3334
+ }
3335
+ }
3336
+ }
3337
+ if {$fname ne {}} {
3338
+ # all looks good, select it
3339
+ if {[commitinview $id $curview ]} {
3340
+ selectline [rowofcommit $id ] 1 [list $fname $lnum ]
3341
+ } else {
3342
+ error_popup [mc " That line comes from commit %s, \
3343
+ which is not in this view" [shortids $id ]]
3344
+ }
3345
+ } else {
3346
+ puts " oops couldn't parse git blame output"
3347
+ }
3348
+ return 0
3349
+ }
3350
+
3259
3351
# delete $dir when we see eof on $f (presumably because the child has exited)
3260
3352
proc delete_at_eof {f dir} {
3261
3353
while {[gets $f line] >= 0} {}
@@ -5748,6 +5840,7 @@ proc stopfinding {} {
5748
5840
set fprogcoord 0
5749
5841
adjustprogress
5750
5842
}
5843
+ stopblaming
5751
5844
}
5752
5845
5753
5846
proc findmore {} {
@@ -6152,15 +6245,15 @@ proc make_secsel {l} {
6152
6245
$canv3 lower $t
6153
6246
}
6154
6247
6155
- proc selectline {l isnew} {
6248
+ proc selectline {l isnew {desired_loc {}} } {
6156
6249
global canv ctext commitinfo selectedline
6157
6250
global canvy0 linespc parents children curview
6158
6251
global currentid sha1entry
6159
6252
global commentend idtags linknum
6160
6253
global mergemax numcommits pending_select
6161
6254
global cmitmode showneartags allcommits
6162
6255
global targetrow targetid lastscrollrows
6163
- global autoselect
6256
+ global autoselect jump_to_here
6164
6257
6165
6258
catch {unset pending_select}
6166
6259
$canv delete hover
@@ -6299,6 +6392,7 @@ proc selectline {l isnew} {
6299
6392
$ctext conf -state disabled
6300
6393
set commentend [$ctext index " end - 1c" ]
6301
6394
6395
+ set jump_to_here $desired_loc
6302
6396
init_flist [mc " Comments" ]
6303
6397
if {$cmitmode eq " tree" } {
6304
6398
gettree $id
@@ -6546,26 +6640,45 @@ proc getblobline {bf id} {
6546
6640
$ctext insert end " $line \n "
6547
6641
}
6548
6642
if {[eof $bf ]} {
6643
+ global jump_to_here ctext_file_names commentend
6644
+
6549
6645
# delete last newline
6550
6646
$ctext delete " end - 2c" " end - 1c"
6551
6647
close $bf
6648
+ if {$jump_to_here ne {} &&
6649
+ [lindex $jump_to_here 0] eq [lindex $ctext_file_names 0]} {
6650
+ set lnum [expr {[lindex $jump_to_here 1] +
6651
+ [lindex [split $commentend .] 0]}]
6652
+ mark_ctext_line $lnum
6653
+ }
6552
6654
return 0
6553
6655
}
6554
6656
$ctext config -state disabled
6555
6657
return [expr {$nl >= 1000? 2: 1}]
6556
6658
}
6557
6659
6660
+ proc mark_ctext_line {lnum} {
6661
+ global ctext
6662
+
6663
+ $ctext tag delete omark
6664
+ $ctext tag add omark $lnum .0 " $lnum .0 + 1 line"
6665
+ $ctext tag conf omark -background " #e0e0ff"
6666
+ $ctext see $lnum .0
6667
+ }
6668
+
6558
6669
proc mergediff {id} {
6559
6670
global diffmergeid mdifffd
6560
6671
global diffids treediffs
6561
6672
global parents
6562
6673
global diffcontext
6563
6674
global diffencoding
6564
6675
global limitdiffs vfilelimit curview
6676
+ global targetline
6565
6677
6566
6678
set diffmergeid $id
6567
6679
set diffids $id
6568
6680
set treediffs($id ) {}
6681
+ set targetline {}
6569
6682
# this doesn't seem to actually affect anything...
6570
6683
set cmd [concat | git diff-tree --no-commit-id --cc -U$diffcontext $id ]
6571
6684
if {$limitdiffs && $vfilelimit($curview) ne {}} {
@@ -6587,7 +6700,7 @@ proc getmergediffline {mdf id np} {
6587
6700
global diffmergeid ctext cflist mergemax
6588
6701
global difffilestart mdifffd treediffs
6589
6702
global ctext_file_names ctext_file_lines
6590
- global diffencoding
6703
+ global diffencoding jump_to_here targetline diffline
6591
6704
6592
6705
$ctext conf -state normal
6593
6706
set nr 0
@@ -6611,9 +6724,17 @@ proc getmergediffline {mdf id np} {
6611
6724
set l [expr {(78 - [string length $fname ]) / 2}]
6612
6725
set pad [string range " ----------------------------------------" 1 $l ]
6613
6726
$ctext insert end " $pad $fname $pad \n " filesep
6727
+ set targetline {}
6728
+ if {$jump_to_here ne {} && [lindex $jump_to_here 0] eq $fname } {
6729
+ set targetline [lindex $jump_to_here 1]
6730
+ }
6731
+ set diffline 0
6614
6732
} elseif {[regexp {^@@} $line ]} {
6615
6733
set line [encoding convertfrom $diffencoding $line ]
6616
6734
$ctext insert end " $line \n " hunksep
6735
+ if {[regexp { \+(\d+),\d+ @@} $line m nl]} {
6736
+ set diffline $nl
6737
+ }
6617
6738
} elseif {[regexp {^[0-9a-f]{40}$} $line ] || [regexp {^index} $line ]} {
6618
6739
# do nothing
6619
6740
} else {
@@ -6653,6 +6774,15 @@ proc getmergediffline {mdf id np} {
6653
6774
lappend tags m$num
6654
6775
}
6655
6776
$ctext insert end " $line \n " $tags
6777
+ if {$targetline ne {} && $minuses eq {}} {
6778
+ if {$diffline == $targetline } {
6779
+ set here [$ctext index " end - 1 line" ]
6780
+ mark_ctext_line [lindex [split $here .] 0]
6781
+ set targetline {}
6782
+ } else {
6783
+ incr diffline
6784
+ }
6785
+ }
6656
6786
}
6657
6787
}
6658
6788
$ctext conf -state disabled
@@ -6840,7 +6970,7 @@ proc getblobdiffs {ids} {
6840
6970
global diffcontext
6841
6971
global ignorespace
6842
6972
global limitdiffs vfilelimit curview
6843
- global diffencoding
6973
+ global diffencoding targetline
6844
6974
6845
6975
set cmd [diffcmd $ids " -p -C --no-commit-id -U$diffcontext " ]
6846
6976
if {$ignorespace } {
@@ -6853,6 +6983,7 @@ proc getblobdiffs {ids} {
6853
6983
puts " error getting diffs: $err "
6854
6984
return
6855
6985
}
6986
+ set targetline {}
6856
6987
set diffinhdr 0
6857
6988
set diffencoding [get_path_encoding {}]
6858
6989
fconfigure $bdf -blocking 0 -encoding binary
@@ -6875,7 +7006,7 @@ proc setinlist {var i val} {
6875
7006
6876
7007
proc makediffhdr {fname ids} {
6877
7008
global ctext curdiffstart treediffs
6878
- global ctext_file_names
7009
+ global ctext_file_names jump_to_here targetline diffline
6879
7010
6880
7011
set i [lsearch -exact $treediffs($ids) $fname ]
6881
7012
if {$i >= 0} {
@@ -6885,14 +7016,19 @@ proc makediffhdr {fname ids} {
6885
7016
set l [expr {(78 - [string length $fname ]) / 2}]
6886
7017
set pad [string range " ----------------------------------------" 1 $l ]
6887
7018
$ctext insert $curdiffstart " $pad $fname $pad " filesep
7019
+ set targetline {}
7020
+ if {$jump_to_here ne {} && [lindex $jump_to_here 0] eq $fname } {
7021
+ set targetline [lindex $jump_to_here 1]
7022
+ }
7023
+ set diffline 0
6888
7024
}
6889
7025
6890
7026
proc getblobdiffline {bdf ids} {
6891
7027
global diffids blobdifffd ctext curdiffstart
6892
7028
global diffnexthead diffnextnote difffilestart
6893
7029
global ctext_file_names ctext_file_lines
6894
7030
global diffinhdr treediffs
6895
- global diffencoding
7031
+ global diffencoding jump_to_here targetline diffline
6896
7032
6897
7033
set nr 0
6898
7034
$ctext conf -state normal
@@ -6941,6 +7077,7 @@ proc getblobdiffline {bdf ids} {
6941
7077
set line [encoding convertfrom $diffencoding $line ]
6942
7078
$ctext insert end " $line \n " hunksep
6943
7079
set diffinhdr 0
7080
+ set diffline $f2l
6944
7081
6945
7082
} elseif {$diffinhdr } {
6946
7083
if {![string compare -length 12 " rename from " $line ]} {
@@ -6974,6 +7111,7 @@ proc getblobdiffline {bdf ids} {
6974
7111
} else {
6975
7112
set line [encoding convertfrom $diffencoding $line ]
6976
7113
set x [string range $line 0 0]
7114
+ set here [$ctext index " end - 1 chars" ]
6977
7115
if {$x == " -" || $x == " +" } {
6978
7116
set tag [expr {$x == " +" }]
6979
7117
$ctext insert end " $line \n " d$tag
@@ -6984,6 +7122,14 @@ proc getblobdiffline {bdf ids} {
6984
7122
# or something else we don't recognize
6985
7123
$ctext insert end " $line \n " hunksep
6986
7124
}
7125
+ if {$targetline ne {} && ($x eq " " || $x eq " +" )} {
7126
+ if {$diffline == $targetline } {
7127
+ mark_ctext_line [lindex [split $here .] 0]
7128
+ set targetline {}
7129
+ } else {
7130
+ incr diffline
7131
+ }
7132
+ }
6987
7133
}
6988
7134
}
6989
7135
$ctext conf -state disabled
0 commit comments