diff --git a/pkg/gui/controllers/commits_files_controller.go b/pkg/gui/controllers/commits_files_controller.go index 85e377996..e42aa6e21 100644 --- a/pkg/gui/controllers/commits_files_controller.go +++ b/pkg/gui/controllers/commits_files_controller.go @@ -580,7 +580,7 @@ func (self *CommitFilesController) GetOnClickFocusedMainView() func(mainViewName } // Entered from the focused main view, so escaping returns there. - return self.c.Helpers().CommitFiles.EnterCommitFile(node, snapshot, types.OnFocusOpts{ClickedWindowName: "main", ClickedViewLineIdx: line, ClickedViewRealLineIdx: line}) + return self.c.Helpers().CommitFiles.EnterCommitFile(node, snapshot, types.OnFocusOpts{ClickedWindowName: "main", ClickedViewLineIdx: line, ClickedViewRealLineIdx: line, SelectLineInDefaultMode: true}) } } diff --git a/pkg/gui/controllers/files_controller.go b/pkg/gui/controllers/files_controller.go index 122eabfc1..d3dc4a304 100644 --- a/pkg/gui/controllers/files_controller.go +++ b/pkg/gui/controllers/files_controller.go @@ -439,7 +439,7 @@ func (self *FilesController) GetOnClickFocusedMainView() func(mainViewName strin } } - return self.EnterFile(snapshot, types.OnFocusOpts{ClickedWindowName: mainViewName, ClickedViewLineIdx: line, ClickedViewRealLineIdx: line}) + return self.EnterFile(snapshot, types.OnFocusOpts{ClickedWindowName: mainViewName, ClickedViewLineIdx: line, ClickedViewRealLineIdx: line, SelectLineInDefaultMode: true}) } } diff --git a/pkg/gui/controllers/helpers/patch_building_helper.go b/pkg/gui/controllers/helpers/patch_building_helper.go index 69a48f188..55b6dbe1b 100644 --- a/pkg/gui/controllers/helpers/patch_building_helper.go +++ b/pkg/gui/controllers/helpers/patch_building_helper.go @@ -159,7 +159,7 @@ func (self *PatchBuildingHelper) RefreshPatchBuildingPanel(opts types.OnFocusOpt oldState := context.GetState() - state := patch_exploring.NewState(diff, selectedLineIdx, selectedRealLineIdx, context.GetView(), oldState, self.c.UserConfig().Gui.UseHunkModeInStagingView) + state := patch_exploring.NewState(diff, selectedLineIdx, selectedRealLineIdx, context.GetView(), oldState, self.c.UserConfig().Gui.UseHunkModeInStagingView, opts.SelectLineInDefaultMode) context.SetState(state) if state == nil { self.Escape() diff --git a/pkg/gui/controllers/helpers/staging_helper.go b/pkg/gui/controllers/helpers/staging_helper.go index 2c5aeddce..16b21e777 100644 --- a/pkg/gui/controllers/helpers/staging_helper.go +++ b/pkg/gui/controllers/helpers/staging_helper.go @@ -74,11 +74,11 @@ func (self *StagingHelper) RefreshStagingPanel(focusOpts types.OnFocusOpts) { hunkMode := self.c.UserConfig().Gui.UseHunkModeInStagingView mainContext.SetState( - patch_exploring.NewState(mainDiff, mainSelectedLineIdx, mainSelectedRealLineIdx, mainContext.GetView(), mainContext.GetState(), hunkMode), + patch_exploring.NewState(mainDiff, mainSelectedLineIdx, mainSelectedRealLineIdx, mainContext.GetView(), mainContext.GetState(), hunkMode, focusOpts.SelectLineInDefaultMode), ) secondaryContext.SetState( - patch_exploring.NewState(secondaryDiff, secondarySelectedLineIdx, secondarySelectedRealLineIdx, secondaryContext.GetView(), secondaryContext.GetState(), hunkMode), + patch_exploring.NewState(secondaryDiff, secondarySelectedLineIdx, secondarySelectedRealLineIdx, secondaryContext.GetView(), secondaryContext.GetState(), hunkMode, focusOpts.SelectLineInDefaultMode), ) mainState := mainContext.GetState() diff --git a/pkg/gui/controllers/switch_to_diff_files_controller.go b/pkg/gui/controllers/switch_to_diff_files_controller.go index 6624aac12..3528f2613 100644 --- a/pkg/gui/controllers/switch_to_diff_files_controller.go +++ b/pkg/gui/controllers/switch_to_diff_files_controller.go @@ -88,7 +88,7 @@ func (self *SwitchToDiffFilesController) GetOnClickFocusedMainView() func(mainVi context.GetViewTrait().FocusPoint( context.ModelIndexToViewIndex(idx), false) node = context.GetSelected() - return self.c.Helpers().CommitFiles.EnterCommitFile(node, snapshot, types.OnFocusOpts{ClickedWindowName: "main", ClickedViewLineIdx: line, ClickedViewRealLineIdx: line}) + return self.c.Helpers().CommitFiles.EnterCommitFile(node, snapshot, types.OnFocusOpts{ClickedWindowName: "main", ClickedViewLineIdx: line, ClickedViewRealLineIdx: line, SelectLineInDefaultMode: true}) } } diff --git a/pkg/gui/patch_exploring/state.go b/pkg/gui/patch_exploring/state.go index 0f2d1a4e7..3d1be981c 100644 --- a/pkg/gui/patch_exploring/state.go +++ b/pkg/gui/patch_exploring/state.go @@ -45,7 +45,7 @@ const ( HUNK ) -func NewState(diff string, selectedLineIdx int, selectedRealLineIdx int, view *gocui.View, oldState *State, useHunkModeByDefault bool) *State { +func NewState(diff string, selectedLineIdx int, selectedRealLineIdx int, view *gocui.View, oldState *State, useHunkModeByDefault bool, selectLineInDefaultMode bool) *State { if oldState != nil && diff == oldState.diff && selectedLineIdx == -1 { // if we're here then we can return the old state. If selectedLineIdx was not -1 // then that would mean we were trying to click and potentially drag a range, which @@ -84,14 +84,28 @@ func NewState(diff string, selectedLineIdx int, selectedRealLineIdx int, view *g userEnabledHunkMode = oldState.userEnabledHunkMode } - // if we have clicked from the outside to focus the main view we'll pass in a non-negative line index so that we can instantly select that line + // A non-negative line index means we were given a specific line to select: + // either by clicking or pressing enter on a line in a focused main view, or + // by clicking directly on the patch explorer view to focus it. if selectedLineIdx >= 0 { // Clamp to the number of wrapped view lines; index might be out of // bounds if a custom diff renderer is being used which produces more lines selectedLineIdx = min(selectedLineIdx, len(patchLineIndices)-1) - selectMode = RANGE - rangeStartLineIdx = selectedLineIdx + if selectLineInDefaultMode { + // Diving in from a focused main view: keep the default select mode + // computed above. In hunk mode the selection covers the block of + // changes around the line, so snap to a change line if the given one + // is a context line (just as toggling hunk mode does). + if selectMode == HUNK { + selectedLineIdx = viewLineIndices[patch.GetNextChangeIdx(patchLineIndices[selectedLineIdx])] + } + } else { + // Clicking directly on the view starts a range selection that can be + // extended by dragging. + selectMode = RANGE + rangeStartLineIdx = selectedLineIdx + } } else if oldState != nil { // if we previously had a selectMode of RANGE, we want that to now be line again (or hunk, if that's the default) if oldState.selectMode != RANGE { diff --git a/pkg/gui/types/context.go b/pkg/gui/types/context.go index 40883fc04..0e2d551c2 100644 --- a/pkg/gui/types/context.go +++ b/pkg/gui/types/context.go @@ -261,6 +261,14 @@ type OnFocusOpts struct { // If not -1, takes precedence over ClickedViewLineIdx. ClickedViewRealLineIdx int + // When entering a patch explorer (staging or patch building) by clicking or + // pressing enter on a line in a focused main view, we select that line using + // the default select mode (hunk or line, per the UseHunkModeInStagingView + // config), the same as when entering through the side panel. Clicking + // directly on the patch explorer view instead starts a range selection that + // can be extended by dragging. + SelectLineInDefaultMode bool + ScrollSelectionIntoView bool }