Replace gui.showSelectionInFocusedMainView config with on-demand selection

Instead of a user config that always shows a selection on focus, the
focused main view starts without a selection (matching master). Pressing
<space> shows a selection in the middle of the view (no scrolling);
pressing <esc> hides it again before falling through to exiting the view.
This commit is contained in:
Stefan Haller 2026-05-26 14:50:18 +02:00
parent 89b67cf938
commit 4ced2c0c24
20 changed files with 80 additions and 62 deletions

View file

@ -157,9 +157,6 @@ gui:
# staging view.
useHunkModeInStagingView: 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' | 'pt'
language: auto

View file

@ -224,6 +224,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
| `` <mouse wheel up> (fn+down) `` | Scroll up | |
| `` <tab> `` | Switch view | Switch to other view (staged/unstaged changes). |
| `` <esc> `` | Exit back to side panel | |
| `` <space> `` | Show/hide selection | |
| `` / `` | Search the current view by text | |
## Main panel (patch building)
@ -329,6 +330,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|-----|--------|-------------|
| `` <tab> `` | Switch view | Switch to other view (staged/unstaged changes). |
| `` <esc> `` | Exit back to side panel | |
| `` <space> `` | Show/hide selection | |
| `` / `` | Search the current view by text | |
## Stash

View file

@ -193,6 +193,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|-----|--------|-------------|
| `` <tab> `` | ビューを切り替え | 他のビュー(ステージされた変更/ステージされていない変更)に切り替えます。 |
| `` <esc> `` | サイドパネルに戻る | |
| `` <space> `` | Show/hide selection | |
| `` / `` | 現在のビューをテキストで検索 | |
## タグ
@ -306,6 +307,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
| `` <mouse wheel up> (fn+down) `` | 上にスクロール | |
| `` <tab> `` | ビューを切り替え | 他のビュー(ステージされた変更/ステージされていない変更)に切り替えます。 |
| `` <esc> `` | サイドパネルに戻る | |
| `` <space> `` | Show/hide selection | |
| `` / `` | 現在のビューをテキストで検索 | |
## メニュー

View file

@ -85,6 +85,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|-----|--------|-------------|
| `` <tab> `` | 패널 전환 | Switch to other view (staged/unstaged changes). |
| `` <esc> `` | Exit back to side panel | |
| `` <space> `` | Show/hide selection | |
| `` / `` | 검색 시작 | |
## Stash
@ -163,6 +164,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
| `` <mouse wheel up> (fn+down) `` | 위로 스크롤 | |
| `` <tab> `` | 패널 전환 | Switch to other view (staged/unstaged changes). |
| `` <esc> `` | Exit back to side panel | |
| `` <space> `` | Show/hide selection | |
| `` / `` | 검색 시작 | |
## 메인 패널 (Patch Building)

View file

@ -232,6 +232,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
| `` <mouse wheel up> (fn+down) `` | Scroll omhoog | |
| `` <tab> `` | Ga naar een ander paneel | Switch to other view (staged/unstaged changes). |
| `` <esc> `` | Exit back to side panel | |
| `` <space> `` | Show/hide selection | |
| `` / `` | Start met zoeken | |
## Patch bouwen
@ -307,6 +308,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|-----|--------|-------------|
| `` <tab> `` | Ga naar een ander paneel | Switch to other view (staged/unstaged changes). |
| `` <esc> `` | Exit back to side panel | |
| `` <space> `` | Show/hide selection | |
| `` / `` | Start met zoeken | |
## Staging

View file

@ -100,6 +100,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|-----|--------|-------------|
| `` <tab> `` | Przełącz widok | Przełącz na inny widok (zatwierdzone/niezatwierdzone zmiany). |
| `` <esc> `` | Exit back to side panel | |
| `` <space> `` | Show/hide selection | |
| `` / `` | Szukaj w bieżącym widoku po tekście | |
## Drzewa pracy
@ -202,6 +203,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
| `` <mouse wheel up> (fn+down) `` | Przewiń w górę | |
| `` <tab> `` | Przełącz widok | Przełącz na inny widok (zatwierdzone/niezatwierdzone zmiany). |
| `` <esc> `` | Exit back to side panel | |
| `` <space> `` | Show/hide selection | |
| `` / `` | Szukaj w bieżącym widoku po tekście | |
## Panel główny (scalanie)

View file

@ -236,6 +236,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
| `` <mouse wheel up> (fn+down) `` | Rolar para cima | |
| `` <tab> `` | Mudar de visão | Alternar para outra visão (staged/não processadas alterações). |
| `` <esc> `` | Exit back to side panel | |
| `` <space> `` | Show/hide selection | |
| `` / `` | Pesquisar na visualização atual por texto | |
## Painel Principal (preparação)
@ -338,6 +339,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|-----|--------|-------------|
| `` <tab> `` | Mudar de visão | Alternar para outra visão (staged/não processadas alterações). |
| `` <esc> `` | Exit back to side panel | |
| `` <space> `` | Show/hide selection | |
| `` / `` | Pesquisar na visualização atual por texto | |
## Stash

View file

@ -75,6 +75,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|-----|--------|-------------|
| `` <tab> `` | Переключиться на другую панель (проиндексированные/непроиндексированные изменения) | Switch to other view (staged/unstaged changes). |
| `` <esc> `` | Exit back to side panel | |
| `` <space> `` | Show/hide selection | |
| `` / `` | Найти | |
## Главная панель (Индексирование)
@ -107,6 +108,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
| `` <mouse wheel up> (fn+down) `` | Прокрутить вверх | |
| `` <tab> `` | Переключиться на другую панель (проиндексированные/непроиндексированные изменения) | Switch to other view (staged/unstaged changes). |
| `` <esc> `` | Exit back to side panel | |
| `` <space> `` | Show/hide selection | |
| `` / `` | Найти | |
## Главная панель (Слияние)

View file

@ -287,6 +287,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|-----|--------|-------------|
| `` <tab> `` | 切换到其他面板 | 切换到其他视图(已暂存/未暂存的变更) |
| `` <esc> `` | 退出回到侧边面板 | |
| `` <space> `` | Show/hide selection | |
| `` / `` | 开始搜索 | |
## 正在合并
@ -335,6 +336,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
| `` <mouse wheel up> (fn+down) `` | 向上滚动 | |
| `` <tab> `` | 切换到其他面板 | 切换到其他视图(已暂存/未暂存的变更) |
| `` <esc> `` | 退出回到侧边面板 | |
| `` <space> `` | Show/hide selection | |
| `` / `` | 开始搜索 | |
## 状态

View file

@ -83,6 +83,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
| `` <mouse wheel up> (fn+down) `` | 向上捲動 | |
| `` <tab> `` | 切換至另一個面板 (已預存/未預存更改) | Switch to other view (staged/unstaged changes). |
| `` <esc> `` | Exit back to side panel | |
| `` <space> `` | Show/hide selection | |
| `` / `` | 搜尋 | |
## 主面板(合併)
@ -364,6 +365,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|-----|--------|-------------|
| `` <tab> `` | 切換至另一個面板 (已預存/未預存更改) | Switch to other view (staged/unstaged changes). |
| `` <esc> `` | Exit back to side panel | |
| `` <space> `` | Show/hide selection | |
| `` / `` | 搜尋 | |
## 狀態

View file

@ -157,9 +157,6 @@ gui:
# staging view.
useHunkModeInStagingView: 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' | 'pt'
language: auto

View file

@ -133,8 +133,6 @@ type GuiConfig struct {
WrapLinesInStagingView bool `yaml:"wrapLinesInStagingView"`
// If true, hunk selection mode will be enabled by default when entering the staging view.
UseHunkModeInStagingView bool `yaml:"useHunkModeInStagingView"`
// 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' | 'pt'
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.
@ -876,14 +874,13 @@ func GetDefaultConfigForPlatform(platform string) *UserConfig {
{"commits", "reflog"},
{"stash"},
},
MainPanelSplitMode: "flexible",
EnlargedSideViewLocation: "left",
WrapLinesInStagingView: true,
UseHunkModeInStagingView: true,
ShowSelectionInFocusedMainView: false,
Language: "auto",
TimeFormat: "02 Jan 06",
ShortTimeFormat: time.Kitchen,
MainPanelSplitMode: "flexible",
EnlargedSideViewLocation: "left",
WrapLinesInStagingView: true,
UseHunkModeInStagingView: true,
Language: "auto",
TimeFormat: "02 Jan 06",
ShortTimeFormat: time.Kitchen,
Theme: ThemeConfig{
ActiveBorderColor: []string{"green", "bold"},
SearchingActiveBorderColor: []string{"cyan", "bold"},

View file

@ -253,7 +253,3 @@ func (self *BaseContext) Title() string {
func (self *BaseContext) TotalContentHeight() int {
return self.view.ViewLinesHeight()
}
func (self *BaseContext) SetHighlightOnFocus(value bool) {
self.highlightOnFocus = value
}

View file

@ -26,7 +26,7 @@ func NewMainContext(
WindowName: windowName,
Key: key,
Focusable: true,
HighlightOnFocus: c.UserConfig().Gui.ShowSelectionInFocusedMainView,
HighlightOnFocus: false,
})),
SearchTrait: NewSearchTrait(c),
}

View file

@ -4,6 +4,7 @@ import (
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
)
type MainViewController struct {
@ -30,11 +31,13 @@ func NewMainViewController(
}
func (self *MainViewController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
var goIntoDescription string
// We only want to show the "enter" menu item if the user config is true;
// leaving the description empty causes it to be hidden
if self.c.UserConfig().Gui.ShowSelectionInFocusedMainView {
goIntoDescription = self.c.Tr.EnterStaging
// When a selection is shown, we surface the bindings that act on it
// (enter to dive into staging, escape to hide the selection).
selectionShown := self.context.GetView().Highlight
var enterDescription string
if selectionShown {
enterDescription = self.c.Tr.EnterStaging
}
return []*types.Binding{
@ -52,9 +55,16 @@ func (self *MainViewController) GetKeybindings(opts types.KeybindingsOpts) []*ty
DisplayOnScreen: true,
},
{
Keys: opts.GetKeys(opts.Config.Universal.GoInto),
Handler: self.enter,
Description: goIntoDescription,
Keys: opts.GetKeys(opts.Config.Universal.Select),
Handler: self.toggleSelection,
Description: self.c.Tr.ToggleSelectionInFocusedMainView,
DisplayOnScreen: !selectionShown,
},
{
Keys: opts.GetKeys(opts.Config.Universal.GoInto),
Handler: self.enter,
Description: enterDescription,
DisplayOnScreen: selectionShown,
},
{
// overriding this because we want to read all of the task's output before we start searching
@ -87,11 +97,14 @@ func (self *MainViewController) Context() types.Context {
return self.context
}
// Transient focus shifts (popups, search) leave HighlightInactive=true on our
// view (set by ContextMgr.Activate when a different view becomes current). Our
// context's highlightOnFocus is false, so SimpleContext.HandleFocus never
// resets it. Reset it here on the way back in, so that if we still hold a
// selection it's drawn as active. The flag is a no-op when Highlight is false.
func (self *MainViewController) GetOnFocus() func(types.OnFocusOpts) {
return func(opts types.OnFocusOpts) {
if opts.ClickedWindowName != "" {
self.context.GetView().FocusPoint(0, opts.ClickedViewLineIdx, false)
}
return func(types.OnFocusOpts) {
self.context.GetView().HighlightInactive = false
}
}
@ -104,11 +117,33 @@ func (self *MainViewController) togglePanel() error {
}
func (self *MainViewController) escape() error {
v := self.context.GetView()
if v.Highlight {
v.Highlight = false
return nil
}
self.c.Context().Pop()
return nil
}
func (self *MainViewController) toggleSelection() error {
v := self.context.GetView()
if v.Highlight {
v.Highlight = false
return nil
}
v.Highlight = true
v.HighlightInactive = false
lineIdx := v.OriginY() + v.InnerHeight()/2
lineIdx = lo.Clamp(lineIdx, 0, v.ViewLinesHeight()-1)
v.FocusPoint(0, lineIdx, false)
return nil
}
func (self *MainViewController) enter() error {
if !self.context.GetView().Highlight {
return nil
}
sidePanelContext := self.c.Context().NextInStack(self.context)
if sidePanelContext != nil && sidePanelContext.GetOnClickFocusedMainView() != nil {
return sidePanelContext.GetOnClickFocusedMainView()(

View file

@ -3,7 +3,6 @@ package controllers
import (
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
)
// This controller is for all contexts that can focus their main view.
@ -62,29 +61,21 @@ func (self *SwitchToFocusedMainViewController) Context() types.Context {
}
func (self *SwitchToFocusedMainViewController) onClickMain(opts gocui.ViewMouseBindingOpts) error {
return self.focusMainView(self.c.Contexts().Normal, opts.Y)
return self.focusMainView(self.c.Contexts().Normal)
}
func (self *SwitchToFocusedMainViewController) onClickSecondary(opts gocui.ViewMouseBindingOpts) error {
return self.focusMainView(self.c.Contexts().NormalSecondary, opts.Y)
return self.focusMainView(self.c.Contexts().NormalSecondary)
}
func (self *SwitchToFocusedMainViewController) handleFocusMainView() error {
return self.focusMainView(self.c.Contexts().Normal, -1)
return self.focusMainView(self.c.Contexts().Normal)
}
func (self *SwitchToFocusedMainViewController) focusMainView(mainViewContext types.Context, clickedViewLineIdx int) error {
func (self *SwitchToFocusedMainViewController) focusMainView(mainViewContext types.Context) error {
if context, ok := mainViewContext.(types.ISearchableContext); ok {
context.ClearSearchString()
}
onFocusOpts := types.OnFocusOpts{ClickedWindowName: mainViewContext.GetWindowName()}
if clickedViewLineIdx >= 0 {
onFocusOpts.ClickedViewLineIdx = clickedViewLineIdx
} else {
mainView := mainViewContext.GetView()
lineIdx := mainView.OriginY() + mainView.Height()/2
onFocusOpts.ClickedViewLineIdx = lo.Clamp(lineIdx, 0, mainView.LinesHeight()-1)
}
self.c.Context().Push(mainViewContext, onFocusOpts)
self.c.Context().Push(mainViewContext, types.OnFocusOpts{})
return nil
}

View file

@ -517,11 +517,6 @@ 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

View file

@ -551,6 +551,7 @@ type TranslationSet struct {
EnterStaging string
ExitCustomPatchBuilder string
ExitFocusedMainView string
ToggleSelectionInFocusedMainView string
EnterUpstream string
InvalidUpstream string
NewRemote string
@ -1716,6 +1717,7 @@ func EnglishTranslationSet() *TranslationSet {
EnterStaging: "Enter staging/patch building",
ExitCustomPatchBuilder: `Exit custom patch builder`,
ExitFocusedMainView: "Exit back to side panel",
ToggleSelectionInFocusedMainView: "Show/hide selection",
EnterUpstream: `Enter upstream as '<remote> <branchname>'`,
InvalidUpstream: "Invalid upstream. Must be in the format '<remote> <branchname>'",
NewRemote: `New remote`,

View file

@ -693,11 +693,6 @@
"description": "If true, hunk selection mode will be enabled by default when entering the staging view.",
"default": true
},
"showSelectionInFocusedMainView": {
"type": "boolean",
"description": "If true, show a selection when the main view is focused.",
"default": false
},
"language": {
"type": "string",
"enum": [

View file

@ -693,11 +693,6 @@
"description": "If true, hunk selection mode will be enabled by default when entering the staging view.",
"default": true
},
"showSelectionInFocusedMainView": {
"type": "boolean",
"description": "If true, show a selection when the main view is focused.",
"default": false
},
"language": {
"type": "string",
"enum": [