Skip to content

Commit 3e26be9

Browse files
committed
Optionally pass disabled commands on to next handler
If a DisabledReason has its AllowFurtherDispatching flag set, it is returned as a ErrKeybindingNotHandled error, instead of shown as a toast right away. This allows gocui to continue to dispatch the keybinding, and we can unwrap the error at the other end (in our global ErrorHandler) and display it then. This allows having keybindings for the same key at the local and global levels, and they will continue to be dispatched even if the first one returns a DisabledReason. It is opt-in, so we only use it for cases where we know that a local and a global handler share the same (default) keybinding.
1 parent 37b118f commit 3e26be9

File tree

4 files changed

+31
-0
lines changed

4 files changed

+31
-0
lines changed

pkg/gui/keybindings.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,10 @@ func (gui *Gui) SetMouseKeybinding(binding *gocui.ViewMouseBinding) error {
525525
func (gui *Gui) callKeybindingHandler(binding *types.Binding) error {
526526
if binding.GetDisabledReason != nil {
527527
if disabledReason := binding.GetDisabledReason(); disabledReason != nil {
528+
if disabledReason.AllowFurtherDispatching {
529+
return &types.ErrKeybindingNotHandled{DisabledReason: disabledReason}
530+
}
531+
528532
if disabledReason.ShowErrorInPanel {
529533
return errors.New(disabledReason.Text)
530534
}

pkg/gui/popup/popup_handler.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package popup
22

33
import (
44
"context"
5+
"errors"
56
"strings"
67

78
"github.com/jesseduffield/gocui"
@@ -80,6 +81,16 @@ func (self *PopupHandler) WithWaitingStatusSync(message string, f func() error)
8081
}
8182

8283
func (self *PopupHandler) ErrorHandler(err error) error {
84+
var notHandledError *types.ErrKeybindingNotHandled
85+
if errors.As(err, &notHandledError) {
86+
if !notHandledError.DisabledReason.ShowErrorInPanel {
87+
if msg := notHandledError.DisabledReason.Text; len(msg) > 0 {
88+
self.ErrorToast(self.Tr.DisabledMenuItemPrefix + msg)
89+
}
90+
return nil
91+
}
92+
}
93+
8394
// Need to set bold here explicitly; otherwise it gets cancelled by the red colouring.
8495
coloredMessage := style.FgRed.SetBold().Sprint(strings.TrimSpace(err.Error()))
8596
if err := self.onErrorFn(); err != nil {

pkg/gui/types/common.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,10 @@ type DisabledReason struct {
202202
// error panel instead. This is useful if the text is very long, or if it is
203203
// important enough to show it more prominently, or both.
204204
ShowErrorInPanel bool
205+
206+
// If true, the keybinding dispatch mechanism will continue to look for
207+
// other handlers for the keypress.
208+
AllowFurtherDispatching bool
205209
}
206210

207211
type MenuWidget int

pkg/gui/types/keybindings.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,15 @@ type KeybindingGuards struct {
5555
OutsideFilterMode Guard
5656
NoPopupPanel Guard
5757
}
58+
59+
type ErrKeybindingNotHandled struct {
60+
DisabledReason *DisabledReason
61+
}
62+
63+
func (e ErrKeybindingNotHandled) Error() string {
64+
return e.DisabledReason.Text
65+
}
66+
67+
func (e ErrKeybindingNotHandled) Unwrap() error {
68+
return gocui.ErrKeybindingNotHandled
69+
}

0 commit comments

Comments
 (0)