mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-08-24 10:13:41 -05:00
Use a slice of keys for each binding
This is a pure refactor in preparation for letting users configure multiple alternate bindings for a single command. Every Binding still has exactly one key, so nothing changes visibly: the cheatsheet, the on-screen options bar, and the keybindings menu all render identically. When a Binding ends up with multiple keys, the on-screen options bar will show only the first (to avoid clutter); the cheatsheet will show all of them (in a later commit). For now both paths take Key[0]. MenuItem.Key is changed in the same way, it also has a slice of keys now. In this commit we keep the name `Key` in Binding, KeybindingOpts and MenuItem, instead of renaming them to `Keys` right away, in order to keep the diff a bit more readable. We'll do the rename separately in the next commit.
This commit is contained in:
@@ -145,7 +145,7 @@ func getBindingSections(bindings []*types.Binding, tr *i18n.TranslationSet) []*b
|
||||
return false
|
||||
}
|
||||
|
||||
return (binding.Description != "" || binding.Alternative != "") && binding.Key.IsSet()
|
||||
return (binding.Description != "" || binding.Alternative != "") && len(binding.Key) > 0
|
||||
})
|
||||
|
||||
bindingsByHeader := lo.GroupBy(bindingsToDisplay, func(binding *types.Binding) header {
|
||||
@@ -156,7 +156,7 @@ func getBindingSections(bindings []*types.Binding, tr *i18n.TranslationSet) []*b
|
||||
bindingsByHeader,
|
||||
func(header header, hBindings []*types.Binding) headerWithBindings {
|
||||
uniqBindings := lo.UniqBy(hBindings, func(binding *types.Binding) string {
|
||||
return binding.Description + config.LabelForKey(binding.Key)
|
||||
return binding.Description + config.LabelForKey(binding.Key[0])
|
||||
})
|
||||
|
||||
return headerWithBindings{
|
||||
@@ -214,7 +214,7 @@ func formatTitle(title string) string {
|
||||
}
|
||||
|
||||
func formatBinding(binding *types.Binding) string {
|
||||
action := config.LabelForKey(binding.Key)
|
||||
action := config.LabelForKey(binding.Key[0])
|
||||
description := binding.Description
|
||||
if binding.Alternative != "" {
|
||||
action += fmt.Sprintf(" (%s)", binding.Alternative)
|
||||
|
||||
@@ -28,7 +28,7 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "stage file",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
},
|
||||
},
|
||||
expected: []*bindingSection{
|
||||
@@ -38,7 +38,7 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "stage file",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -50,7 +50,7 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "",
|
||||
Description: "quit",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
},
|
||||
},
|
||||
expected: []*bindingSection{
|
||||
@@ -60,7 +60,7 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "",
|
||||
Description: "quit",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -72,17 +72,17 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "stage file",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
},
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "unstage file",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
},
|
||||
{
|
||||
ViewName: "submodules",
|
||||
Description: "drop submodule",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
},
|
||||
},
|
||||
expected: []*bindingSection{
|
||||
@@ -92,12 +92,12 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "stage file",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
},
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "unstage file",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -107,7 +107,7 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "submodules",
|
||||
Description: "drop submodule",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -119,23 +119,23 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "stage file",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
},
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "unstage file",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
},
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "scroll",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
Tag: "navigation",
|
||||
},
|
||||
{
|
||||
ViewName: "commits",
|
||||
Description: "revert commit",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
},
|
||||
},
|
||||
expected: []*bindingSection{
|
||||
@@ -145,7 +145,7 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "scroll",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
Tag: "navigation",
|
||||
},
|
||||
},
|
||||
@@ -156,7 +156,7 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "commits",
|
||||
Description: "revert commit",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -166,12 +166,12 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "stage file",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
},
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "unstage file",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -183,34 +183,34 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "stage file",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
},
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "unstage file",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
},
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "scroll",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
Tag: "navigation",
|
||||
},
|
||||
{
|
||||
ViewName: "commits",
|
||||
Description: "revert commit",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
},
|
||||
{
|
||||
ViewName: "commits",
|
||||
Description: "scroll",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
Tag: "navigation",
|
||||
},
|
||||
{
|
||||
ViewName: "commits",
|
||||
Description: "page up",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
Tag: "navigation",
|
||||
},
|
||||
},
|
||||
@@ -221,13 +221,13 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "scroll",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
Tag: "navigation",
|
||||
},
|
||||
{
|
||||
ViewName: "commits",
|
||||
Description: "page up",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
Tag: "navigation",
|
||||
},
|
||||
},
|
||||
@@ -238,7 +238,7 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "commits",
|
||||
Description: "revert commit",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -248,12 +248,12 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "stage file",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
},
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "unstage file",
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('a')},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -205,3 +205,11 @@ func GetValidatedKeyBindingKey(label string) gocui.Key {
|
||||
|
||||
return key
|
||||
}
|
||||
|
||||
func GetValidatedKeyBindingKeys(label string) []gocui.Key {
|
||||
k := GetValidatedKeyBindingKey(label)
|
||||
if !k.IsSet() {
|
||||
return nil
|
||||
}
|
||||
return []gocui.Key{k}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/style"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/i18n"
|
||||
@@ -73,7 +74,11 @@ func NewMenuViewModel(c *ContextCommon) *MenuViewModel {
|
||||
func() []*types.MenuItem { return self.menuItems },
|
||||
func(item *types.MenuItem) []string {
|
||||
if filterKeybindings {
|
||||
return []string{config.LabelForKey(item.Key)}
|
||||
// Allow searching all configured keybindings of each item, even though only the
|
||||
// first one is shown in the menu.
|
||||
return lo.Map(item.Key, func(k gocui.Key, _ int) string {
|
||||
return config.LabelForKey(k)
|
||||
})
|
||||
}
|
||||
|
||||
return item.LabelColumns
|
||||
@@ -138,8 +143,8 @@ func (self *MenuViewModel) GetDisplayStrings(_ int, _ int) [][]string {
|
||||
}
|
||||
|
||||
keyLabel := ""
|
||||
if item.Key.IsSet() {
|
||||
keyLabel = style.FgCyan.Sprint(config.LabelForKey(item.Key))
|
||||
if len(item.Key) > 0 {
|
||||
keyLabel = style.FgCyan.Sprint(config.LabelForKey(item.Key[0]))
|
||||
}
|
||||
|
||||
checkMark := ""
|
||||
@@ -205,7 +210,7 @@ func (self *MenuViewModel) GetNonModelItems() []*NonModelItem {
|
||||
func (self *MenuContext) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||
basicBindings := self.ListContextTrait.GetKeybindings(opts)
|
||||
menuItemsWithKeys := lo.Filter(self.menuItems, func(item *types.MenuItem, _ int) bool {
|
||||
return item.Key.IsSet()
|
||||
return len(item.Key) > 0
|
||||
})
|
||||
|
||||
menuItemBindings := lo.Map(menuItemsWithKeys, func(item *types.MenuItem, _ int) *types.Binding {
|
||||
|
||||
@@ -3,9 +3,9 @@ package helpers
|
||||
import "github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
|
||||
// menuKey is a shorthand for constructing a key value for a menu item from a single rune literal,
|
||||
// avoiding the noise of `gocui.NewKeyRune('a')` at every call site. There is an intentionally
|
||||
// identical helper in the controllers package so that callers in either package can use the
|
||||
// unqualified form.
|
||||
func menuKey(r rune) gocui.Key {
|
||||
return gocui.NewKeyRune(r)
|
||||
// avoiding the noise of `[]gocui.Key{gocui.NewKeyRune('a')}` at every call site. There is an
|
||||
// intentionally identical helper in the controllers package so that callers in either package can
|
||||
// use the unqualified form.
|
||||
func menuKey(r rune) []gocui.Key {
|
||||
return []gocui.Key{gocui.NewKeyRune(r)}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ const (
|
||||
func (self *MergeAndRebaseHelper) CreateRebaseOptionsMenu() error {
|
||||
type optionAndKey struct {
|
||||
option string
|
||||
key gocui.Key
|
||||
key []gocui.Key
|
||||
}
|
||||
|
||||
options := []optionAndKey{
|
||||
|
||||
@@ -216,7 +216,7 @@ func (self *RefsHelper) ResetToRef(ref string, strength string, envVars []string
|
||||
|
||||
func (self *RefsHelper) CreateSortOrderMenu(sortOptionsOrder []string, menuPrompt string, onSelected func(sortOrder string) error, currentValue string) error {
|
||||
type sortMenuOption struct {
|
||||
key gocui.Key
|
||||
key []gocui.Key
|
||||
label string
|
||||
description string
|
||||
sortOrder string
|
||||
@@ -260,7 +260,7 @@ func (self *RefsHelper) CreateGitResetMenu(name string, ref string) error {
|
||||
type strengthWithKey struct {
|
||||
strength string
|
||||
label string
|
||||
key gocui.Key
|
||||
key []gocui.Key
|
||||
tooltip string
|
||||
}
|
||||
strengths := []strengthWithKey{
|
||||
@@ -318,7 +318,7 @@ func (self *RefsHelper) CreateCheckoutMenu(commit *models.Commit) error {
|
||||
|
||||
if len(branches) > 0 {
|
||||
menuItems = append(menuItems, lo.Map(branches, func(branch *models.Branch, index int) *types.MenuItem {
|
||||
var key gocui.Key
|
||||
var key []gocui.Key
|
||||
if index < 9 {
|
||||
key = menuKey(rune(index + 1 + '0')) // Convert 1-based index to key
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@ package controllers
|
||||
import "github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
|
||||
// menuKey is a shorthand for constructing a key value for a menu item from a single rune literal,
|
||||
// avoiding the noise of `gocui.NewKeyRune('a')` at every call site. There is an intentionally
|
||||
// identical helper in the helpers package so that callers in either package can use the unqualified
|
||||
// form.
|
||||
func menuKey(r rune) gocui.Key {
|
||||
return gocui.NewKeyRune(r)
|
||||
// avoiding the noise of `[]gocui.Key{gocui.NewKeyRune('a')}` at every call site. There is an
|
||||
// intentionally identical helper in the helpers package so that callers in either package can use
|
||||
// the unqualified form.
|
||||
func menuKey(r rune) []gocui.Key {
|
||||
return []gocui.Key{gocui.NewKeyRune(r)}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ func NewPromptController(
|
||||
func (self *PromptController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||
bindings := []*types.Binding{
|
||||
{
|
||||
Key: gocui.NewKeyName(gocui.KeyEnter),
|
||||
Key: []gocui.Key{gocui.NewKeyName(gocui.KeyEnter)},
|
||||
Handler: func() error { return self.context().State.OnConfirm() },
|
||||
Description: self.c.Tr.Confirm,
|
||||
DisplayOnScreen: true,
|
||||
|
||||
@@ -24,7 +24,7 @@ func NewSearchPromptController(
|
||||
func (self *SearchPromptController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||
return []*types.Binding{
|
||||
{
|
||||
Key: gocui.NewKeyName(gocui.KeyEnter),
|
||||
Key: []gocui.Key{gocui.NewKeyName(gocui.KeyEnter)},
|
||||
Handler: self.confirm,
|
||||
},
|
||||
{
|
||||
|
||||
@@ -15,7 +15,7 @@ func (gui *Gui) handleCreateExtrasMenuPanel() error {
|
||||
Items: []*types.MenuItem{
|
||||
{
|
||||
Label: gui.c.Tr.ToggleShowCommandLog,
|
||||
Key: gocui.NewKeyRune('t'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('t')},
|
||||
OnPress: func() error {
|
||||
currentContext := gui.c.Context().CurrentStatic()
|
||||
if gui.c.State().GetShowExtrasWindow() && currentContext.GetKey() == context.COMMAND_LOG_CONTEXT_KEY {
|
||||
@@ -30,7 +30,7 @@ func (gui *Gui) handleCreateExtrasMenuPanel() error {
|
||||
},
|
||||
{
|
||||
Label: gui.c.Tr.FocusCommandLog,
|
||||
Key: gocui.NewKeyRune('f'),
|
||||
Key: []gocui.Key{gocui.NewKeyRune('f')},
|
||||
OnPress: gui.handleFocusCommandLog,
|
||||
},
|
||||
},
|
||||
|
||||
+14
-12
@@ -69,7 +69,7 @@ func (gui *Gui) keybindingOpts() types.KeybindingsOpts {
|
||||
}
|
||||
|
||||
return types.KeybindingsOpts{
|
||||
GetKey: config.GetValidatedKeyBindingKey,
|
||||
GetKey: config.GetValidatedKeyBindingKeys,
|
||||
Config: keybindingConfig,
|
||||
Guards: guards,
|
||||
}
|
||||
@@ -176,7 +176,7 @@ func (gui *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBin
|
||||
},
|
||||
{
|
||||
ViewName: "information",
|
||||
Key: gocui.NewKeyName(gocui.MouseLeft),
|
||||
Key: []gocui.Key{gocui.NewKeyName(gocui.MouseLeft)},
|
||||
Handler: gui.handleInfoClick,
|
||||
},
|
||||
{
|
||||
@@ -196,26 +196,26 @@ func (gui *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBin
|
||||
},
|
||||
{
|
||||
ViewName: "main",
|
||||
Key: gocui.NewKeyName(gocui.MouseWheelDown),
|
||||
Key: []gocui.Key{gocui.NewKeyName(gocui.MouseWheelDown)},
|
||||
Handler: gui.scrollDownMain,
|
||||
Description: gui.c.Tr.ScrollDown,
|
||||
Alternative: "fn+up",
|
||||
},
|
||||
{
|
||||
ViewName: "main",
|
||||
Key: gocui.NewKeyName(gocui.MouseWheelUp),
|
||||
Key: []gocui.Key{gocui.NewKeyName(gocui.MouseWheelUp)},
|
||||
Handler: gui.scrollUpMain,
|
||||
Description: gui.c.Tr.ScrollUp,
|
||||
Alternative: "fn+down",
|
||||
},
|
||||
{
|
||||
ViewName: "secondary",
|
||||
Key: gocui.NewKeyName(gocui.MouseWheelDown),
|
||||
Key: []gocui.Key{gocui.NewKeyName(gocui.MouseWheelDown)},
|
||||
Handler: gui.scrollDownSecondary,
|
||||
},
|
||||
{
|
||||
ViewName: "secondary",
|
||||
Key: gocui.NewKeyName(gocui.MouseWheelUp),
|
||||
Key: []gocui.Key{gocui.NewKeyName(gocui.MouseWheelUp)},
|
||||
Handler: gui.scrollUpSecondary,
|
||||
},
|
||||
{
|
||||
@@ -240,12 +240,12 @@ func (gui *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBin
|
||||
},
|
||||
{
|
||||
ViewName: "confirmation",
|
||||
Key: gocui.NewKeyName(gocui.MouseWheelUp),
|
||||
Key: []gocui.Key{gocui.NewKeyName(gocui.MouseWheelUp)},
|
||||
Handler: gui.scrollUpConfirmationPanel,
|
||||
},
|
||||
{
|
||||
ViewName: "confirmation",
|
||||
Key: gocui.NewKeyName(gocui.MouseWheelDown),
|
||||
Key: []gocui.Key{gocui.NewKeyName(gocui.MouseWheelDown)},
|
||||
Handler: gui.scrollDownConfirmationPanel,
|
||||
},
|
||||
{
|
||||
@@ -287,12 +287,12 @@ func (gui *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBin
|
||||
},
|
||||
{
|
||||
ViewName: "extras",
|
||||
Key: gocui.NewKeyName(gocui.MouseWheelUp),
|
||||
Key: []gocui.Key{gocui.NewKeyName(gocui.MouseWheelUp)},
|
||||
Handler: gui.scrollUpExtra,
|
||||
},
|
||||
{
|
||||
ViewName: "extras",
|
||||
Key: gocui.NewKeyName(gocui.MouseWheelDown),
|
||||
Key: []gocui.Key{gocui.NewKeyName(gocui.MouseWheelDown)},
|
||||
Handler: gui.scrollDownExtra,
|
||||
},
|
||||
{
|
||||
@@ -352,7 +352,7 @@ func (gui *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBin
|
||||
{
|
||||
ViewName: "extras",
|
||||
Tag: "navigation",
|
||||
Key: gocui.NewKeyName(gocui.MouseLeft),
|
||||
Key: []gocui.Key{gocui.NewKeyName(gocui.MouseLeft)},
|
||||
Handler: gui.handleFocusCommandLog,
|
||||
},
|
||||
}
|
||||
@@ -448,7 +448,9 @@ func (gui *Gui) SetKeybinding(binding *types.Binding) {
|
||||
return gui.callKeybindingHandler(binding)
|
||||
}
|
||||
|
||||
gui.g.SetKeybinding(binding.ViewName, binding.Key, handler)
|
||||
for _, key := range binding.Key {
|
||||
gui.g.SetKeybinding(binding.ViewName, key, handler)
|
||||
}
|
||||
}
|
||||
|
||||
func (gui *Gui) SetMouseKeybinding(binding *gocui.ViewMouseBinding) error {
|
||||
|
||||
@@ -46,8 +46,10 @@ func (gui *Gui) createMenu(opts types.CreateMenuOptions) error {
|
||||
maxColumnSize = max(maxColumnSize, len(item.LabelColumns))
|
||||
|
||||
// Remove all item keybindings that are the same as one of the essential bindings
|
||||
if !opts.KeepConflictingKeybindings && lo.Contains(essentialKeys, item.Key) {
|
||||
item.Key = gocui.Key{}
|
||||
if !opts.KeepConflictingKeybindings {
|
||||
item.Key = lo.Filter(item.Key, func(k gocui.Key, _ int) bool {
|
||||
return !lo.Contains(essentialKeys, k)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,12 +41,12 @@ func (self *OptionsMapMgr) renderContextOptionsMap() {
|
||||
globalBindings := self.c.Contexts().Global.GetKeybindings(self.c.KeybindingsOpts())
|
||||
|
||||
currentContextKeys := set.NewFromSlice(
|
||||
lo.Map(currentContextBindings, func(binding *types.Binding, _ int) gocui.Key {
|
||||
lo.FlatMap(currentContextBindings, func(binding *types.Binding, _ int) []gocui.Key {
|
||||
return binding.Key
|
||||
}))
|
||||
|
||||
allBindings := append(currentContextBindings, lo.Filter(globalBindings, func(b *types.Binding, _ int) bool {
|
||||
return !currentContextKeys.Includes(b.Key)
|
||||
return len(b.Key) == 0 || !currentContextKeys.Includes(b.Key[0])
|
||||
})...)
|
||||
|
||||
bindingsToDisplay := lo.Filter(allBindings, func(binding *types.Binding, _ int) bool {
|
||||
@@ -60,7 +60,7 @@ func (self *OptionsMapMgr) renderContextOptionsMap() {
|
||||
}
|
||||
|
||||
return bindingInfo{
|
||||
key: config.LabelForKey(binding.Key),
|
||||
key: config.LabelForKey(binding.Key[0]),
|
||||
description: binding.GetShortDescription(),
|
||||
style: displayStyle,
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package custom_commands
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/i18n"
|
||||
@@ -45,7 +46,7 @@ func (self *Client) GetCustomCommandKeybindings() ([]*types.Binding, error) {
|
||||
}
|
||||
bindings = append(bindings, &types.Binding{
|
||||
ViewName: "", // custom commands menus are global; we filter the commands inside by context
|
||||
Key: config.GetValidatedKeyBindingKey(customCommand.Key),
|
||||
Key: []gocui.Key{config.GetValidatedKeyBindingKey(customCommand.Key)},
|
||||
Handler: handler,
|
||||
Description: getCustomCommandsMenuDescription(customCommand, self.c.Tr),
|
||||
OpensMenu: true,
|
||||
@@ -72,7 +73,7 @@ func (self *Client) showCustomCommandsMenu(customCommand config.CustomCommand) e
|
||||
}
|
||||
menuItems = append(menuItems, &types.MenuItem{
|
||||
Label: subCommand.GetDescription(),
|
||||
Key: config.GetValidatedKeyBindingKey(subCommand.Key),
|
||||
Key: []gocui.Key{config.GetValidatedKeyBindingKey(subCommand.Key)},
|
||||
OnPress: handler,
|
||||
OpensMenu: true,
|
||||
})
|
||||
@@ -92,7 +93,7 @@ func (self *Client) showCustomCommandsMenu(customCommand config.CustomCommand) e
|
||||
|
||||
menuItems = append(menuItems, &types.MenuItem{
|
||||
Label: subCommand.GetDescription(),
|
||||
Key: config.GetValidatedKeyBindingKey(subCommand.Key),
|
||||
Key: []gocui.Key{config.GetValidatedKeyBindingKey(subCommand.Key)},
|
||||
OnPress: self.handlerCreator.call(subCommand),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ func (self *HandlerCreator) menuPrompt(prompt *config.CustomCommandPrompt, wrapp
|
||||
OnPress: func() error {
|
||||
return wrappedF(option.Value)
|
||||
},
|
||||
Key: config.GetValidatedKeyBindingKey(option.Key),
|
||||
Key: []gocui.Key{config.GetValidatedKeyBindingKey(option.Key)},
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
@@ -35,7 +36,7 @@ func (self *KeybindingCreator) call(customCommand config.CustomCommand, handler
|
||||
return lo.Map(viewNames, func(viewName string, _ int) *types.Binding {
|
||||
return &types.Binding{
|
||||
ViewName: viewName,
|
||||
Key: config.GetValidatedKeyBindingKey(customCommand.Key),
|
||||
Key: []gocui.Key{config.GetValidatedKeyBindingKey(customCommand.Key)},
|
||||
Handler: handler,
|
||||
Description: customCommand.GetDescription(),
|
||||
}
|
||||
|
||||
@@ -259,9 +259,10 @@ type MenuItem struct {
|
||||
// Only applies when Label is used
|
||||
OpensMenu bool
|
||||
|
||||
// If Key is defined it allows the user to press the key to invoke the menu
|
||||
// item, as opposed to having to navigate to it
|
||||
Key gocui.Key
|
||||
// If Key is non-empty, the user can press any of these keys to invoke the
|
||||
// menu item, as opposed to having to navigate to it. Only the first key is
|
||||
// shown in the menu; the alternates are matched silently.
|
||||
Key []gocui.Key
|
||||
|
||||
// A widget to show in front of the menu item. Supported widget types are
|
||||
// checkboxes and radio buttons,
|
||||
|
||||
@@ -239,7 +239,7 @@ type OnFocusLostOpts struct {
|
||||
type ContextKey string
|
||||
|
||||
type KeybindingsOpts struct {
|
||||
GetKey func(key string) gocui.Key
|
||||
GetKey func(key string) []gocui.Key
|
||||
Config config.KeybindingConfig
|
||||
Guards KeybindingGuards
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
type Binding struct {
|
||||
ViewName string
|
||||
Handler func() error
|
||||
Key gocui.Key
|
||||
Key []gocui.Key
|
||||
Description string
|
||||
// DescriptionFunc is used instead of Description if non-nil, and is useful for dynamic
|
||||
// descriptions that change depending on context. Important: this must not be an expensive call.
|
||||
|
||||
Reference in New Issue
Block a user