Allow rebinding the confirm key for search and prompt

The confirm action for the search/filter prompt and for text input
prompts (e.g. naming a stash or a new branch) was hard-coded to <enter>
in #4860, on the assumption that these wouldn't be remapped. That
assumption turned out to be wrong: users who rebind universal.confirm to
a key such as <c-j> could no longer confirm these two prompts.

Add ConfirmSearch and ConfirmPrompt keybindings, following the existing
pattern of context-specific confirm keys (confirmMenu, confirmSuggestion,
confirmInEditor). Both default to <enter>, so behaviour is unchanged for
users who don't remap them.

Fixes #5510
This commit is contained in:
mokashang 2026-05-26 09:19:41 -07:00
parent 53e39dc7b8
commit 65b69016b0
7 changed files with 109 additions and 4 deletions

View file

@ -644,6 +644,14 @@ keybinding:
confirmMenu: <enter>
confirmSuggestion: <enter>
# Key for confirming the search/filter prompt (the one opened with
# `startSearch`).
confirmSearch: <enter>
# Key for confirming a text input prompt (e.g. when naming a stash or a new
# branch).
confirmPrompt: <enter>
# <meta+enter> on Mac
confirmInEditor: [<ctrl+enter>, <ctrl+s>]
remove: d

View file

@ -474,7 +474,11 @@ type KeybindingUniversalConfig struct {
Confirm Keybinding `yaml:"confirm"`
ConfirmMenu Keybinding `yaml:"confirmMenu"`
ConfirmSuggestion Keybinding `yaml:"confirmSuggestion"`
ConfirmInEditor Keybinding `yaml:"confirmInEditor"` // <meta+enter> on Mac
// Key for confirming the search/filter prompt (the one opened with `startSearch`).
ConfirmSearch Keybinding `yaml:"confirmSearch"`
// Key for confirming a text input prompt (e.g. when naming a stash or a new branch).
ConfirmPrompt Keybinding `yaml:"confirmPrompt"`
ConfirmInEditor Keybinding `yaml:"confirmInEditor"` // <meta+enter> on Mac
// Deprecated: add the key to `confirmInEditor` instead.
ConfirmInEditorAlt Keybinding `yaml:"confirmInEditor-alt"`
Remove Keybinding `yaml:"remove"`
@ -986,6 +990,8 @@ func GetDefaultConfigForPlatform(platform string) *UserConfig {
Confirm: Keybinding{"<enter>"},
ConfirmMenu: Keybinding{"<enter>"},
ConfirmSuggestion: Keybinding{"<enter>"},
ConfirmSearch: Keybinding{"<enter>"},
ConfirmPrompt: Keybinding{"<enter>"},
ConfirmInEditor: Keybinding{platformKeyBinding(platform, map[string]string{"darwin": "<meta+enter>"}, "<ctrl+enter>")},
ConfirmInEditorAlt: Keybinding{"<ctrl+s>"},
Remove: Keybinding{"d"},

View file

@ -27,7 +27,7 @@ func NewPromptController(
func (self *PromptController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
bindings := []*types.Binding{
{
Keys: []gocui.Key{gocui.NewKeyName(gocui.KeyEnter)},
Keys: opts.GetKeys(opts.Config.Universal.ConfirmPrompt),
Handler: func() error { return self.context().State.OnConfirm() },
Description: self.c.Tr.Confirm,
DisplayOnScreen: true,

View file

@ -1,7 +1,6 @@
package controllers
import (
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
@ -24,7 +23,7 @@ func NewSearchPromptController(
func (self *SearchPromptController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
return []*types.Binding{
{
Keys: []gocui.Key{gocui.NewKeyName(gocui.KeyEnter)},
Keys: opts.GetKeys(opts.Config.Universal.ConfirmSearch),
Handler: self.confirm,
},
{

View file

@ -0,0 +1,61 @@
package config
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var RebindConfirmSearchAndPrompt = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Confirm a search and a text prompt using a rebound confirm keybinding",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(cfg *config.AppConfig) {
// The search and prompt confirm keys used to be hard-coded to <enter>,
// so they couldn't be rebound like the other confirm keybindings.
cfg.GetUserConfig().Keybinding.Universal.ConfirmSearch = []string{"<c-y>"}
cfg.GetUserConfig().Keybinding.Universal.ConfirmPrompt = []string{"<c-y>"}
},
SetupRepo: func(shell *Shell) {
shell.NewBranch("branch")
shell.EmptyCommit("one")
shell.EmptyCommit("two")
shell.EmptyCommit("three")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
// Confirming a search with the rebound key works.
t.Views().Commits().
Focus().
Lines(
Contains("three").IsSelected(),
Contains("two"),
Contains("one"),
).
Press(keys.Universal.StartSearch).
Tap(func() {
t.ExpectSearch().
Type("two")
t.GlobalPress(keys.Universal.ConfirmSearch)
t.Views().Search().IsVisible().Content(Contains("matches for 'two' (1 of 1)"))
}).
Lines(
Contains("three"),
Contains("two").IsSelected(),
Contains("one"),
)
// Confirming a text input prompt with the rebound key works.
t.Views().Branches().
Focus().
Press(keys.Universal.New)
t.ExpectPopup().Prompt().
Title(Contains("New branch name")).
Type("new-branch")
t.GlobalPress(keys.Universal.ConfirmPrompt)
t.Git().CurrentBranchName("new-branch")
},
})

View file

@ -160,6 +160,7 @@ var tests = []*components.IntegrationTest{
commit.Unstaged,
config.CustomCommandsInPerRepoConfig,
config.NegativeRefspec,
config.RebindConfirmSearchAndPrompt,
config.RemoteNamedStar,
conflicts.Filter,
conflicts.MergeFileBoth,

View file

@ -2786,6 +2786,36 @@
],
"default": "\u003center\u003e"
},
"confirmSearch": {
"oneOf": [
{
"type": "string"
},
{
"items": {
"type": "string"
},
"type": "array"
}
],
"description": "Key for confirming the search/filter prompt (the one opened with `startSearch`).",
"default": "\u003center\u003e"
},
"confirmPrompt": {
"oneOf": [
{
"type": "string"
},
{
"items": {
"type": "string"
},
"type": "array"
}
],
"description": "Key for confirming a text input prompt (e.g. when naming a stash or a new branch).",
"default": "\u003center\u003e"
},
"confirmInEditor": {
"oneOf": [
{