From e592d81b601d19d429ab61b7f3bd478de9844204 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Tue, 5 Sep 2023 22:27:28 +0200 Subject: [PATCH] Add Enabled func to Binding --- pkg/gui/controllers/options_menu_action.go | 13 +++++++++---- pkg/gui/gui_common.go | 4 ++++ pkg/gui/keybindings.go | 16 +++++++++++++++- pkg/gui/types/common.go | 1 + pkg/gui/types/keybindings.go | 7 +++++++ 5 files changed, 36 insertions(+), 5 deletions(-) diff --git a/pkg/gui/controllers/options_menu_action.go b/pkg/gui/controllers/options_menu_action.go index 341fe8fb3..27a2915b8 100644 --- a/pkg/gui/controllers/options_menu_action.go +++ b/pkg/gui/controllers/options_menu_action.go @@ -25,6 +25,10 @@ func (self *OptionsMenuAction) Call() error { appendBindings := func(bindings []*types.Binding, section *types.MenuSection) { menuItems = append(menuItems, lo.Map(bindings, func(binding *types.Binding, _ int) *types.MenuItem { + disabledReason := "" + if binding.GetDisabledReason != nil { + disabledReason = binding.GetDisabledReason() + } return &types.MenuItem{ OpensMenu: binding.OpensMenu, Label: binding.Description, @@ -33,11 +37,12 @@ func (self *OptionsMenuAction) Call() error { return nil } - return binding.Handler() + return self.c.IGuiCommon.CallKeybindingHandler(binding) }, - Key: binding.Key, - Tooltip: binding.Tooltip, - Section: section, + Key: binding.Key, + Tooltip: binding.Tooltip, + DisabledReason: disabledReason, + Section: section, } })...) } diff --git a/pkg/gui/gui_common.go b/pkg/gui/gui_common.go index bad0957ec..0abe94f4c 100644 --- a/pkg/gui/gui_common.go +++ b/pkg/gui/gui_common.go @@ -171,6 +171,10 @@ func (self *guiCommon) KeybindingsOpts() types.KeybindingsOpts { return self.gui.keybindingOpts() } +func (self *guiCommon) CallKeybindingHandler(binding *types.Binding) error { + return self.gui.callKeybindingHandler(binding) +} + func (self *guiCommon) IsAnyModeActive() bool { return self.gui.helpers.Mode.IsAnyModeActive() } diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index cb14d0266..afb12ce85 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -375,7 +375,10 @@ func (gui *Gui) wrappedHandler(f func() error) func(g *gocui.Gui, v *gocui.View) } func (gui *Gui) SetKeybinding(binding *types.Binding) error { - handler := binding.Handler + handler := func() error { + return gui.callKeybindingHandler(binding) + } + // TODO: move all mouse-ey stuff into new mouse approach if gocui.IsMouseKey(binding.Key) { handler = func() error { @@ -406,3 +409,14 @@ func (gui *Gui) SetMouseKeybinding(binding *gocui.ViewMouseBinding) error { return gui.g.SetViewClickBinding(binding) } + +func (gui *Gui) callKeybindingHandler(binding *types.Binding) error { + disabledReason := "" + if binding.GetDisabledReason != nil { + disabledReason = binding.GetDisabledReason() + } + if disabledReason != "" { + return gui.c.ErrorMsg(disabledReason) + } + return binding.Handler() +} diff --git a/pkg/gui/types/common.go b/pkg/gui/types/common.go index 21ba78d9a..5f1363f03 100644 --- a/pkg/gui/types/common.go +++ b/pkg/gui/types/common.go @@ -104,6 +104,7 @@ type IGuiCommon interface { State() IStateAccessor KeybindingsOpts() KeybindingsOpts + CallKeybindingHandler(binding *Binding) error // hopefully we can remove this once we've moved all our keybinding stuff out of the gui god struct. GetInitialKeybindingsWithCustomCommands() ([]*Binding, []*gocui.ViewMouseBinding) diff --git a/pkg/gui/types/keybindings.go b/pkg/gui/types/keybindings.go index 95978e762..4c3d02c6f 100644 --- a/pkg/gui/types/keybindings.go +++ b/pkg/gui/types/keybindings.go @@ -25,6 +25,13 @@ type Binding struct { // to be displayed if the keybinding is highlighted from within a menu Tooltip string + + // Function to decide whether the command is enabled, and why. If this + // returns an empty string, it is; if it returns a non-empty string, it is + // disabled and we show the given text in an error message when trying to + // invoke it. When left nil, the command is always enabled. Note that this + // function must not do expensive calls. + GetDisabledReason func() string } // A guard is a decorator which checks something before executing a handler