Select the first hunk when focusing the main view in hunk mode

With hunk mode the default (gui.useHunkModeInStagingView, on by default),
focusing the main view now selects the whole first visible change block rather
than a single line, matching what entering the staging view does and what the
just-added hunk staging expects. In line mode it still anchors on a single line,
as before.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Haller 2026-06-18 11:54:53 +02:00
parent 4b57cc9efe
commit 26a784ef74
3 changed files with 72 additions and 12 deletions

View file

@ -223,16 +223,23 @@ func (self *MainViewController) togglePanel() error {
}
// showInitialDiffSelection turns on the focused main view's selection when entering
// a diff view without pointing at a specific line: on the first change line already
// visible (so the view doesn't jump), falling back to the current top line when none
// is visible (scrolled into trailing context, or not loaded that far yet). The
// select mode is reset to its default (a single line).
// a diff view without pointing at a specific line, anchored on the first change line
// already visible (so the view barely moves), falling back to the current top line
// when none is visible (scrolled into trailing context, or not loaded that far yet).
// With hunk mode configured as the default it selects the whole change block around
// that line, like entering the staging view does; otherwise a single line.
func showInitialDiffSelection(c *ControllerCommon, mainContext *context.MainContext) {
resetDiffSelectMode(mainContext)
view := mainContext.GetView()
target, ok := c.Helpers().Staging.FirstChangeLineInView(view)
if !ok {
target = view.OriginY()
showSelectionAtLine(view, view.OriginY(), true)
return
}
if c.UserConfig().Gui.UseHunkModeInStagingView {
mainContext.DiffSelectState().Mode = context.DiffSelectModeHunk
selectDiffHunk(c, mainContext, target)
return
}
showSelectionAtLine(view, target, true)
}
@ -365,16 +372,22 @@ func (self *MainViewController) prevFile() error {
// its last, so the native range highlight spans the block. With no change block
// there (the line is trailing context) it falls back to a single-line selection.
func (self *MainViewController) selectHunkAround(changeViewLine int) {
v := self.context.GetView()
start, end, ok := self.c.Helpers().Staging.ChangeBlockBounds(v, changeViewLine)
selectDiffHunk(self.c, self.context, changeViewLine)
}
// selectDiffHunk is the body of selectHunkAround, as a free function so the focus
// entry point (showInitialDiffSelection) can establish a hunk selection too.
func selectDiffHunk(c *ControllerCommon, mainContext *context.MainContext, changeViewLine int) {
view := mainContext.GetView()
start, end, ok := c.Helpers().Staging.ChangeBlockBounds(view, changeViewLine)
if !ok {
self.sel().Mode = context.DiffSelectModeLine
v.CancelRangeSelect()
showSelectionAtLine(v, changeViewLine, true)
mainContext.DiffSelectState().Mode = context.DiffSelectModeLine
view.CancelRangeSelect()
showSelectionAtLine(view, changeViewLine, true)
return
}
v.SetRangeSelectStart(end)
showSelectionAtLine(v, start, true)
view.SetRangeSelectStart(end)
showSelectionAtLine(view, start, true)
}
// moveCursor moves the selection cursor by delta view lines (negative = up), with

View file

@ -0,0 +1,46 @@
package staging
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var SelectHunkOnFocusingMainView = NewIntegrationTest(NewIntegrationTestArgs{
Description: "When hunk mode is the default, focusing the main view selects the first whole hunk, ready to stage",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {
config.GetUserConfig().Gui.UseHunkModeInStagingView = true
},
SetupRepo: func(shell *Shell) {
shell.CreateFileAndAdd("file1", "one\ntwo\nthree\nfour\nfive\nsix\nseven\neight\nnine\nten\n")
shell.Commit("one")
shell.UpdateFile("file1", "one\ntwo\nTHREE\nfour\nfive\nsix\nseven\neight\nNINE\nten\n")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Files().
IsFocused().
Lines(
Contains("file1").IsSelected(),
).
Press(keys.Universal.FocusMainView)
// No key press: the first hunk is selected just by focusing, so space
// stages it straight away.
t.Views().Main().
IsFocused().
SelectedLines(
Contains("-three"),
Contains("+THREE"),
).
PressPrimaryAction().
Tap(func() {
t.Views().Secondary().
ContainsLines(
Contains("-three"),
Contains("+THREE"),
)
})
},
})

View file

@ -410,6 +410,7 @@ var tests = []*components.IntegrationTest{
staging.DiffContextChange,
staging.DiscardAllChanges,
staging.Search,
staging.SelectHunkOnFocusingMainView,
staging.SelectNextLineAfterStagingInTwoHunkDiff,
staging.SelectNextLineAfterStagingIsolatedAddedLine,
staging.StageHunkFromMainView,