From e76f1d6c1f5b2753fb758680384f3a65d9be9f9e Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Tue, 1 Apr 2025 16:14:10 +0200 Subject: [PATCH] Add user config gui.showSelectionInFocusedMainView --- docs/Config.md | 3 ++ pkg/config/user_config.go | 37 ++++++++++--------- pkg/gui/context/base_context.go | 4 ++ pkg/gui/context/main_context.go | 2 +- pkg/gui/controllers/main_view_controller.go | 4 ++ .../controllers/view_selection_controller.go | 30 ++++++++++++--- pkg/gui/gui.go | 5 +++ schema/config.json | 5 +++ 8 files changed, 67 insertions(+), 23 deletions(-) diff --git a/docs/Config.md b/docs/Config.md index 8fd1fd960..2b3fd1d44 100644 --- a/docs/Config.md +++ b/docs/Config.md @@ -113,6 +113,9 @@ gui: # paragraphs of markdown text. wrapLinesInStagingView: true + # If true, show a selection when the main view is focused. + showSelectionInFocusedMainView: false + # One of 'auto' (default) | 'en' | 'zh-CN' | 'zh-TW' | 'pl' | 'nl' | 'ja' | 'ko' | 'ru' language: auto diff --git a/pkg/config/user_config.go b/pkg/config/user_config.go index d35e35772..5458da476 100644 --- a/pkg/config/user_config.go +++ b/pkg/config/user_config.go @@ -105,6 +105,8 @@ type GuiConfig struct { // makes it much easier to work with diffs that have long lines, e.g. // paragraphs of markdown text. WrapLinesInStagingView bool `yaml:"wrapLinesInStagingView"` + // If true, show a selection when the main view is focused. + ShowSelectionInFocusedMainView bool `yaml:"showSelectionInFocusedMainView"` // One of 'auto' (default) | 'en' | 'zh-CN' | 'zh-TW' | 'pl' | 'nl' | 'ja' | 'ko' | 'ru' Language string `yaml:"language" jsonschema:"enum=auto,enum=en,enum=zh-TW,enum=zh-CN,enum=pl,enum=nl,enum=ja,enum=ko,enum=ru"` // Format used when displaying time e.g. commit time. @@ -735,23 +737,24 @@ type IconProperties struct { func GetDefaultConfig() *UserConfig { return &UserConfig{ Gui: GuiConfig{ - ScrollHeight: 2, - ScrollPastBottom: true, - ScrollOffMargin: 2, - ScrollOffBehavior: "margin", - TabWidth: 4, - MouseEvents: true, - SkipDiscardChangeWarning: false, - SkipStashWarning: false, - SidePanelWidth: 0.3333, - ExpandFocusedSidePanel: false, - ExpandedSidePanelWeight: 2, - MainPanelSplitMode: "flexible", - EnlargedSideViewLocation: "left", - WrapLinesInStagingView: true, - Language: "auto", - TimeFormat: "02 Jan 06", - ShortTimeFormat: time.Kitchen, + ScrollHeight: 2, + ScrollPastBottom: true, + ScrollOffMargin: 2, + ScrollOffBehavior: "margin", + TabWidth: 4, + MouseEvents: true, + SkipDiscardChangeWarning: false, + SkipStashWarning: false, + SidePanelWidth: 0.3333, + ExpandFocusedSidePanel: false, + ExpandedSidePanelWeight: 2, + MainPanelSplitMode: "flexible", + EnlargedSideViewLocation: "left", + WrapLinesInStagingView: true, + ShowSelectionInFocusedMainView: false, + Language: "auto", + TimeFormat: "02 Jan 06", + ShortTimeFormat: time.Kitchen, Theme: ThemeConfig{ ActiveBorderColor: []string{"green", "bold"}, SearchingActiveBorderColor: []string{"cyan", "bold"}, diff --git a/pkg/gui/context/base_context.go b/pkg/gui/context/base_context.go index b72374392..5c1fd05b0 100644 --- a/pkg/gui/context/base_context.go +++ b/pkg/gui/context/base_context.go @@ -228,3 +228,7 @@ func (self *BaseContext) Title() string { func (self *BaseContext) TotalContentHeight() int { return self.view.ViewLinesHeight() } + +func (self *BaseContext) SetHighlightOnFocus(value bool) { + self.highlightOnFocus = value +} diff --git a/pkg/gui/context/main_context.go b/pkg/gui/context/main_context.go index 66babac03..a0189ef0e 100644 --- a/pkg/gui/context/main_context.go +++ b/pkg/gui/context/main_context.go @@ -26,7 +26,7 @@ func NewMainContext( WindowName: windowName, Key: key, Focusable: true, - HighlightOnFocus: false, + HighlightOnFocus: c.UserConfig().Gui.ShowSelectionInFocusedMainView, })), SearchTrait: NewSearchTrait(c), } diff --git a/pkg/gui/controllers/main_view_controller.go b/pkg/gui/controllers/main_view_controller.go index e6b209286..8e82c2e0b 100644 --- a/pkg/gui/controllers/main_view_controller.go +++ b/pkg/gui/controllers/main_view_controller.go @@ -94,6 +94,10 @@ func (self *MainViewController) escape() error { } func (self *MainViewController) onClick(opts gocui.ViewMouseBindingOpts) error { + if self.context.GetView().Highlight && opts.Y != opts.PreviousY { + return nil + } + parentCtx := self.context.GetParentContext() if parentCtx.GetOnClickFocusedMainView() != nil { return parentCtx.GetOnClickFocusedMainView()(self.context.GetViewName(), opts.Y) diff --git a/pkg/gui/controllers/view_selection_controller.go b/pkg/gui/controllers/view_selection_controller.go index 638c46ba6..2f7f3b172 100644 --- a/pkg/gui/controllers/view_selection_controller.go +++ b/pkg/gui/controllers/view_selection_controller.go @@ -3,6 +3,7 @@ package controllers import ( "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/gui/types" + "github.com/samber/lo" ) type ViewSelectionControllerFactory struct { @@ -61,10 +62,21 @@ func (self *ViewSelectionController) handleLineChange(delta int) { } v := self.Context().GetView() - if delta < 0 { - v.ScrollUp(-delta) + if self.context.GetView().Highlight { + lineIdxBefore := v.CursorY() + v.OriginY() + lineIdxAfter := lo.Clamp(lineIdxBefore+delta, 0, v.ViewLinesHeight()-1) + if delta == -1 { + checkScrollUp(self.Context().GetViewTrait(), self.c.UserConfig(), lineIdxBefore, lineIdxAfter) + } else if delta == 1 { + checkScrollDown(self.Context().GetViewTrait(), self.c.UserConfig(), lineIdxBefore, lineIdxAfter) + } + v.FocusPoint(0, lineIdxAfter) } else { - v.ScrollDown(delta) + if delta < 0 { + v.ScrollUp(-delta) + } else { + v.ScrollDown(delta) + } } } @@ -90,7 +102,11 @@ func (self *ViewSelectionController) handleNextPage() error { func (self *ViewSelectionController) handleGotoTop() error { v := self.Context().GetView() - self.handleLineChange(-v.ViewLinesHeight()) + if self.context.GetView().Highlight { + v.FocusPoint(0, 0) + } else { + self.handleLineChange(-v.ViewLinesHeight()) + } return nil } @@ -99,7 +115,11 @@ func (self *ViewSelectionController) handleGotoBottom() error { manager.ReadToEnd(func() { self.c.OnUIThread(func() error { v := self.Context().GetView() - self.handleLineChange(v.ViewLinesHeight()) + if self.context.GetView().Highlight { + v.FocusPoint(0, v.ViewLinesHeight()-1) + } else { + self.handleLineChange(v.ViewLinesHeight()) + } return nil }) }) diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 90a2a64d4..d4eb97348 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -446,6 +446,11 @@ func (gui *Gui) onUserConfigLoaded() error { gui.g.Mouse = userConfig.Gui.MouseEvents + if gui.State != nil { + gui.Contexts().Normal.SetHighlightOnFocus(userConfig.Gui.ShowSelectionInFocusedMainView) + gui.Contexts().NormalSecondary.SetHighlightOnFocus(userConfig.Gui.ShowSelectionInFocusedMainView) + } + // originally we could only hide the command log permanently via the config // but now we do it via state. So we need to still support the config for the // sake of backwards compatibility. We're making use of short circuiting here diff --git a/schema/config.json b/schema/config.json index 96a968e4d..74e00bee4 100644 --- a/schema/config.json +++ b/schema/config.json @@ -528,6 +528,11 @@ "description": "If true, wrap lines in the staging view to the width of the view. This\nmakes it much easier to work with diffs that have long lines, e.g.\nparagraphs of markdown text.", "default": true }, + "showSelectionInFocusedMainView": { + "type": "boolean", + "description": "If true, show a selection when the main view is focused.", + "default": false + }, "language": { "type": "string", "enum": [