Stop at the end of the diff when jumping to a file from a panel

With gui.scrollPastBottom set to false, picking the last file of a long
diff from the jump-to-file menu of the commits panel scrolls that file
to the top of the view. This leaves blank space below the end of the
diff.

A jump in a pane that isn't focused puts the file at the top of the view
and leaves it to the layout to stop at the end of the diff. But the
layout doesn't do this while the view is loading. Picking an item from
the menu closes the menu first, and the commits panel starts a re-render
of the diff as it gets the focus back. So the view is loading when the
jump happens, and the layout corrects the position only in a later pass
after the re-render has finished. For a long diff the re-render never
finishes; a later commit fixes this. Clicking a file in the diffstat
doesn't close a menu, so it doesn't have the problem.

Stop the jump at the last screenful of the diff, as a jump in the
focused pane does. Like that one, it stops there whatever
gui.scrollPastBottom is set to.

The diff in click_a_file_in_a_diff_stat_that_comes_first fits on
screen, so the jump doesn't scroll it any more. Make it longer than the
view.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Haller
2026-10-13 16:26:38 +02:00
co-authored by Claude Opus 5.5
parent d198ce56f1
commit 56b6c5af31
3 changed files with 9 additions and 7 deletions
@@ -65,8 +65,9 @@ func (self *DiffLineHelper) EstablishSelection(mainContext *context.MainContext,
// PlaceNavigationTarget moves the pane's selection to the row a jump found, bringing
// it on screen if it isn't already. With no selection to move — a pane that isn't
// focused, or one showing a diff with nothing selectable in it — the row goes to the
// top of the view instead, that being all a jump can do there.
// focused, or one showing a diff with nothing selectable in it — all a jump can do is
// scroll the row to the top of the view, or as close to the top as the end of the diff
// allows.
//
// alignTop asks for the target to become the view's top line, so that everything that
// begins there is on screen. It only applies to a target the view has to scroll to: a
@@ -84,7 +85,7 @@ func (self *DiffLineHelper) PlaceNavigationTarget(
) {
view := pane.GetView()
if !view.Highlight {
view.SetOrigin(0, target)
view.SetOrigin(0, originYWithTargetAtTop(pane, target))
return
}
if alignTop {
@@ -1,6 +1,8 @@
package main_view
import (
"strings"
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
@@ -23,7 +25,9 @@ var ClickAFileInADiffStatThatComesFirst = NewIntegrationTest(NewIntegrationTestA
SetupRepo: func(shell *Shell) {
shell.CreateFileAndAdd("aaa.txt", "one\n")
shell.Commit("one")
shell.CreateFileAndAdd("zzz.txt", "one\n")
// Longer than the view, so that the diff can be scrolled to put aaa.txt at the
// top.
shell.CreateFileAndAdd("zzz.txt", strings.Repeat("line\n", 40))
shell.Commit("two")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
@@ -45,9 +45,6 @@ var JumpToTheLastFileOfALongDiff = NewIntegrationTest(NewIntegrationTestArgs{
// The view shows the last screenful of the diff: the end of long.txt's diff,
// and all of short.txt's below it.
t.Views().Main().
/* EXPECTED:
TopVisibleLine(Equals("+line5994"))
ACTUAL: */
TopVisibleLine(Equals("diff --git a/short.txt b/short.txt"))
},
})