mirror of
https://github.com/jesseduffield/lazygit.git
synced 2024-12-12 11:15:00 +02:00
e1fc90615d
If a given menu item has an associated keybinding of 'enter', hitting enter won't actually execute that item unless your cursor is on it. This creates confusion, and so we're going to use a strikethrough style to communicate that the keybinding is reserved for something else.
137 lines
3.5 KiB
Go
137 lines
3.5 KiB
Go
package context
|
|
|
|
import (
|
|
"github.com/jesseduffield/generics/slices"
|
|
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
|
"github.com/jesseduffield/lazygit/pkg/gui/style"
|
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
|
"github.com/samber/lo"
|
|
)
|
|
|
|
type MenuContext struct {
|
|
c *ContextCommon
|
|
|
|
*MenuViewModel
|
|
*ListContextTrait
|
|
}
|
|
|
|
var _ types.IListContext = (*MenuContext)(nil)
|
|
|
|
func NewMenuContext(
|
|
c *ContextCommon,
|
|
) *MenuContext {
|
|
viewModel := NewMenuViewModel(c)
|
|
|
|
return &MenuContext{
|
|
c: c,
|
|
MenuViewModel: viewModel,
|
|
ListContextTrait: &ListContextTrait{
|
|
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
|
|
View: c.Views().Menu,
|
|
WindowName: "menu",
|
|
Key: "menu",
|
|
Kind: types.TEMPORARY_POPUP,
|
|
Focusable: true,
|
|
HasUncontrolledBounds: true,
|
|
})),
|
|
getDisplayStrings: viewModel.GetDisplayStrings,
|
|
list: viewModel,
|
|
c: c,
|
|
},
|
|
}
|
|
}
|
|
|
|
// TODO: remove this thing.
|
|
func (self *MenuContext) GetSelectedItemId() string {
|
|
item := self.GetSelected()
|
|
if item == nil {
|
|
return ""
|
|
}
|
|
|
|
return item.Label
|
|
}
|
|
|
|
type MenuViewModel struct {
|
|
c *ContextCommon
|
|
menuItems []*types.MenuItem
|
|
*BasicViewModel[*types.MenuItem]
|
|
}
|
|
|
|
func NewMenuViewModel(c *ContextCommon) *MenuViewModel {
|
|
self := &MenuViewModel{
|
|
menuItems: nil,
|
|
c: c,
|
|
}
|
|
|
|
self.BasicViewModel = NewBasicViewModel(func() []*types.MenuItem { return self.menuItems })
|
|
|
|
return self
|
|
}
|
|
|
|
func (self *MenuViewModel) SetMenuItems(items []*types.MenuItem) {
|
|
self.menuItems = items
|
|
}
|
|
|
|
// TODO: move into presentation package
|
|
func (self *MenuViewModel) GetDisplayStrings(_startIdx int, _length int) [][]string {
|
|
showKeys := slices.Some(self.menuItems, func(item *types.MenuItem) bool {
|
|
return item.Key != nil
|
|
})
|
|
|
|
return slices.Map(self.menuItems, func(item *types.MenuItem) []string {
|
|
displayStrings := item.LabelColumns
|
|
|
|
if !showKeys {
|
|
return displayStrings
|
|
}
|
|
|
|
// These keys are used for general navigation so we'll strike them out to
|
|
// avoid confusion
|
|
reservedKeys := []string{
|
|
self.c.UserConfig.Keybinding.Universal.Confirm,
|
|
self.c.UserConfig.Keybinding.Universal.Select,
|
|
self.c.UserConfig.Keybinding.Universal.Return,
|
|
}
|
|
keyLabel := keybindings.LabelFromKey(item.Key)
|
|
keyStyle := style.FgCyan
|
|
if lo.Contains(reservedKeys, keyLabel) {
|
|
keyStyle = style.FgDefault.SetStrikethrough()
|
|
}
|
|
|
|
displayStrings = slices.Prepend(displayStrings, keyStyle.Sprint(keyLabel))
|
|
return displayStrings
|
|
})
|
|
}
|
|
|
|
func (self *MenuContext) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
|
basicBindings := self.ListContextTrait.GetKeybindings(opts)
|
|
menuItemsWithKeys := slices.Filter(self.menuItems, func(item *types.MenuItem) bool {
|
|
return item.Key != nil
|
|
})
|
|
|
|
menuItemBindings := slices.Map(menuItemsWithKeys, func(item *types.MenuItem) *types.Binding {
|
|
return &types.Binding{
|
|
Key: item.Key,
|
|
Handler: func() error { return self.OnMenuPress(item) },
|
|
}
|
|
})
|
|
|
|
// appending because that means the menu item bindings have lower precedence.
|
|
// So if a basic binding is to escape from the menu, we want that to still be
|
|
// what happens when you press escape. This matters when we're showing the menu
|
|
// for all keybindings of say the files context.
|
|
return append(basicBindings, menuItemBindings...)
|
|
}
|
|
|
|
func (self *MenuContext) OnMenuPress(selectedItem *types.MenuItem) error {
|
|
if err := self.c.PopContext(); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := selectedItem.OnPress(); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|