diff --git a/pkg/gui/controllers/helpers/diff_line_navigation.go b/pkg/gui/controllers/helpers/diff_line_navigation.go index 6b17643eb..9d583f6ab 100644 --- a/pkg/gui/controllers/helpers/diff_line_navigation.go +++ b/pkg/gui/controllers/helpers/diff_line_navigation.go @@ -95,6 +95,14 @@ func (self *StagingHelper) ViewHasChangeLines(view *gocui.View) bool { return false } +// IsChangeLine reports whether the given view line of view's displayed diff is a +// change line (an addition or deletion) rather than context, a header, or an +// unparseable row — i.e. whether a click there points at something stageable. +func (self *StagingHelper) IsChangeLine(view *gocui.View, viewLineIdx int) bool { + info, ok := self.GetDiffLineInfoForView(view, viewLineIdx) + return ok && info.IsChange() +} + // ChangeBlockBounds returns the view-line range [start, end] of the change block // (lazygit's notion of a hunk; see AdjacentChangeBlock) to select when entering or // moving in hunk mode in view's displayed diff. The block is the one containing diff --git a/pkg/gui/controllers/main_view_controller.go b/pkg/gui/controllers/main_view_controller.go index 0c67fc011..d5679049e 100644 --- a/pkg/gui/controllers/main_view_controller.go +++ b/pkg/gui/controllers/main_view_controller.go @@ -282,8 +282,11 @@ func establishFocusedDiffSelection(c *ControllerCommon, mainContext *context.Mai // placeOrHideInitialDiffSelection puts the focused main view's selection on the clicked // line (clickedViewLine >= 0) or, for keyboard focus, on the first change line at or // below the top of the viewport — so the view barely moves — falling back to the top -// line when none is visible. With hunk mode configured as the default, keyboard focus -// selects the whole change block around that line, like entering the staging view does. +// line when none is visible. With hunk mode configured as the default the selection +// widens to the whole change block, like entering the staging view does: keyboard focus +// snaps to the block at the first visible change, and a click on a change line selects +// that line's block, ready to stage. A click on context still selects just that line — +// the click points at it precisely, so it can be edited (e) rather than staged. // When the diff has nothing to act on (a placeholder, a binary file, an all-context // diff) it shows no selection rather than highlighting a stray line. func placeOrHideInitialDiffSelection(c *ControllerCommon, mainContext *context.MainContext, clickedViewLine int, scrollIntoView bool) { @@ -293,6 +296,11 @@ func placeOrHideInitialDiffSelection(c *ControllerCommon, mainContext *context.M return } if clickedViewLine >= 0 { + if c.UserConfig().Gui.UseHunkModeInStagingView && c.Helpers().Staging.IsChangeLine(view, clickedViewLine) { + mainContext.DiffSelectState().Mode = context.DiffSelectModeHunk + selectDiffHunk(c, mainContext, clickedViewLine) + return + } showSelectionAtLine(view, clickedViewLine, scrollIntoView) return }