Skip to content

Commit 0dfed77

Browse files
committed
git-gui: Jump to original line in blame viewer
When the user clicks on a commit link within one of the columns in the blame viewer we now jump them not just to that commit/file pair but also to the line of the original file. This saves the user a lot of time, as they don't need to search through the new file data for the chunk they were previously looking at. We also restore the prior view when the user clicks the back button to return to a pior commit/file pair that they were looking at. Turned out this was quite tricky to get working in Tk. Every time I tried to jump the text widgets to the correct locations by way of the "yview moveto" or "see" subcommands Tk performed the change until the current event finished dispatching, and then reset the views back to 0, making the change never take place. Forcing Tk to run the pending events before we jump the UI resolves the issue. Signed-off-by: Shawn O. Pearce <[email protected]>
1 parent 383d4e0 commit 0dfed77

File tree

1 file changed

+42
-13
lines changed

1 file changed

+42
-13
lines changed

lib/blame.tcl

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -310,10 +310,10 @@ constructor new {i_commit i_path} {
310310
bind $w.file_pane <Configure> \
311311
"if {{$w.file_pane} eq {%W}} {[cb _resize %h]}"
312312

313-
_load $this
313+
_load $this {}
314314
}
315315

316-
method _load {} {
316+
method _load {jump} {
317317
_hide_tooltip $this
318318

319319
if {$total_lines != 0 || $current_fd ne {}} {
@@ -331,6 +331,10 @@ method _load {} {
331331
$i conf -state disabled
332332
}
333333

334+
$w_cviewer conf -state normal
335+
$w_cviewer delete 0.0 end
336+
$w_cviewer conf -state disabled
337+
334338
set highlight_line -1
335339
set highlight_column {}
336340
set highlight_commit {}
@@ -356,7 +360,6 @@ method _load {} {
356360
} else {
357361
$w_back conf -state normal
358362
}
359-
lappend history [list $commit $path]
360363

361364
# Index 0 is always empty. There is never line 0 as
362365
# we use only 1 based lines, as that matches both with
@@ -374,7 +377,7 @@ method _load {} {
374377
set fd [open "| $cmd" r]
375378
}
376379
fconfigure $fd -blocking 0 -translation lf -encoding binary
377-
fileevent $fd readable [cb _read_file $fd]
380+
fileevent $fd readable [cb _read_file $fd $jump]
378381
set current_fd $fd
379382
}
380383

@@ -386,7 +389,7 @@ method _history_menu {} {
386389
menu $m -tearoff 0
387390
}
388391

389-
for {set i [expr {[llength $history] - 2}]
392+
for {set i [expr {[llength $history] - 1}]
390393
} {$i >= 0} {incr i -1} {
391394
set e [lindex $history $i]
392395
set c [lindex $e 0]
@@ -406,21 +409,22 @@ method _history_menu {} {
406409
}
407410
}
408411

409-
$m add command -label $t -command [cb _goback $i $c $f]
412+
$m add command -label $t -command [cb _goback $i]
410413
}
411414
set X [winfo rootx $w_back]
412415
set Y [expr {[winfo rooty $w_back] + [winfo height $w_back]}]
413416
tk_popup $m $X $Y
414417
}
415418

416-
method _goback {i c f} {
419+
method _goback {i} {
420+
set dat [lindex $history $i]
417421
set history [lrange $history 0 [expr {$i - 1}]]
418-
set commit $c
419-
set path $f
420-
_load $this
422+
set commit [lindex $dat 0]
423+
set path [lindex $dat 1]
424+
_load $this [lrange $dat 2 5]
421425
}
422426

423-
method _read_file {fd} {
427+
method _read_file {fd jump} {
424428
if {$fd ne $current_fd} {
425429
catch {close $fd}
426430
return
@@ -450,6 +454,22 @@ method _read_file {fd} {
450454

451455
if {[eof $fd]} {
452456
close $fd
457+
458+
# If we don't force Tk to update the widgets *right now*
459+
# none of our jump commands will cause a change in the UI.
460+
#
461+
update
462+
463+
if {[llength $jump] == 1} {
464+
set highlight_line [lindex $jump 0]
465+
$w_file see "$highlight_line.0"
466+
} elseif {[llength $jump] == 4} {
467+
set highlight_column [lindex $jump 0]
468+
set highlight_line [lindex $jump 1]
469+
$w_file xview moveto [lindex $jump 2]
470+
$w_file yview moveto [lindex $jump 3]
471+
}
472+
453473
_exec_blame $this $w_asim @asim_data [list] {}
454474
}
455475
} ifdeleted { catch {close $fd} }
@@ -502,6 +522,7 @@ method _read_blame {fd cur_w cur_d cur_s} {
502522
set file [string range $line 9 end]
503523
set n $r_line_count
504524
set lno $r_final_line
525+
set oln $r_orig_line
505526
set cmit $r_commit
506527

507528
if {[regexp {^0{40}$} $cmit]} {
@@ -550,7 +571,7 @@ method _read_blame {fd cur_w cur_d cur_s} {
550571
$i tag remove g$g $lno.0 $lno_e
551572
}
552573
}
553-
lset line_data $lno [list $cmit $file]
574+
lset line_data $lno [list $cmit $file $oln]
554575

555576
$cur_w delete $lno.0 "$lno.0 lineend"
556577
if {$lno == $first_lno} {
@@ -578,6 +599,7 @@ method _read_blame {fd cur_w cur_d cur_s} {
578599

579600
incr n -1
580601
incr lno
602+
incr oln
581603
incr blame_lines
582604
}
583605

@@ -641,9 +663,16 @@ method _load_commit {cur_w cur_d pos} {
641663
set lno [lindex [split [$cur_w index $pos] .] 0]
642664
set dat [lindex $line_data $lno]
643665
if {$dat ne {}} {
666+
lappend history [list \
667+
$commit $path \
668+
$highlight_column \
669+
$highlight_line \
670+
[lindex [$w_file xview] 0] \
671+
[lindex [$w_file yview] 0] \
672+
]
644673
set commit [lindex $dat 0]
645674
set path [lindex $dat 1]
646-
_load $this
675+
_load $this [list [lindex $dat 2]]
647676
}
648677
}
649678

0 commit comments

Comments
 (0)