From e53354a73876e3ba721589bfc4a667adc4c16a34 Mon Sep 17 00:00:00 2001 From: ayn2op Date: Thu, 27 Aug 2026 15:06:10 -0400 Subject: [PATCH] feat: allow disabling keybind help (#832) --- internal/config/config.go | 1 + internal/config/config.toml | 2 ++ internal/config/config_test.go | 5 +++- internal/ui/root/model.go | 40 +++++++++++++++----------- internal/ui/root/model_test.go | 52 ++++++++++++++++++++++++++++++++++ 5 files changed, 83 insertions(+), 17 deletions(-) create mode 100644 internal/ui/root/model_test.go diff --git a/internal/config/config.go b/internal/config/config.go index 9eacb79..247b1e0 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -64,6 +64,7 @@ type ( } HelpConfig struct { + Enabled bool `toml:"enabled"` CompactModifiers bool `toml:"compact_modifiers"` Padding [2]int `toml:"padding"` Separator string `toml:"separator"` diff --git a/internal/config/config.toml b/internal/config/config.toml index 1c037a5..332e943 100644 --- a/internal/config/config.toml +++ b/internal/config/config.toml @@ -34,6 +34,8 @@ mask_spoilers = false theme = "monokai" [help] +# Whether to show keybind help. +enabled = false # Show compact key modifiers in help, e.g. "^x" instead of "ctrl+x". compact_modifiers = true # [left, right] diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 8a2ceda..79377c1 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -53,7 +53,7 @@ func TestLoad(t *testing.T) { t.Run("valid config does not return error", func(t *testing.T) { path := filepath.Join(t.TempDir(), "good.toml") - if err := os.WriteFile(path, []byte("mouse = false"), os.ModePerm); err != nil { + if err := os.WriteFile(path, []byte("mouse = false\n[help]\nenabled = true"), os.ModePerm); err != nil { t.Fatal(err) } @@ -65,6 +65,9 @@ func TestLoad(t *testing.T) { if cfg.Mouse != false { t.Fatalf("got = %v, want = false", cfg.Mouse) } + if !cfg.Help.Enabled { + t.Fatal("help enabled = false, want true") + } }) // Keys live in config.toml, descriptions in defaultKeybinds(); fail if either is missing. diff --git a/internal/ui/root/model.go b/internal/ui/root/model.go index 2cd2f57..c1c3322 100644 --- a/internal/ui/root/model.go +++ b/internal/ui/root/model.go @@ -44,27 +44,31 @@ func NewModel(cfg *config.Config) *Model { m := &Model{ Layers: layers.New(), rootFlex: flex.NewModel(), - help: help.NewModel(), - - cfg: cfg, + cfg: cfg, } m.SetBackgroundLayerStyle(cfg.Theme.Dialog.BackgroundStyle.Style) - m.rootFlex.SetDirection(flex.DirectionRow) + if cfg.Help.Enabled { + m.help = newHelpModel(cfg, m) + } + m.buildLayout() + return m +} +func newHelpModel(cfg *config.Config, keyMap help.KeyMap) *help.Model { styles := help.DefaultStyles() styles.ShortKey = cfg.Theme.Help.ShortKeyStyle.Style styles.ShortDesc = cfg.Theme.Help.ShortDescStyle.Style styles.FullKey = cfg.Theme.Help.FullKeyStyle.Style styles.FullDesc = cfg.Theme.Help.FullDescStyle.Style - m.help.SetStyles(styles) - m.help.SetKeyMap(m) - m.help.SetCompactModifiers(cfg.Help.CompactModifiers) - m.help.SetShortSeparator(cfg.Help.Separator) - m.help.SetBorderPadding(0, 0, cfg.Help.Padding[0], cfg.Help.Padding[1]) - m.buildLayout() - return m + h := help.NewModel() + h.SetStyles(styles). + SetKeyMap(keyMap). + SetCompactModifiers(cfg.Help.CompactModifiers). + SetShortSeparator(cfg.Help.Separator) + h.SetBorderPadding(0, 0, cfg.Help.Padding[0], cfg.Help.Padding[1]) + return h } func (m *Model) showLogin() tview.Cmd { @@ -89,9 +93,10 @@ func (m *Model) buildLayout() { if m.inner != nil { m.rootFlex.AddItem(m.inner, 0, 1, true) } - m.rootFlex.AddItem(m.help, 1, 0, false) + if m.help != nil { + m.rootFlex.AddItem(m.help, m.helpHeight(), 0, false) + } m.AddLayer(m.rootFlex, layers.WithName(contentLayerName), layers.WithResize(true), layers.WithVisible(true)) - m.updateHelpHeight() } var _ tview.Model = (*Model)(nil) @@ -144,8 +149,11 @@ func (m *Model) Update(msg tview.Msg) tview.Cmd { } switch { case keybind.Matches(msg, m.cfg.Keybinds.ToggleHelp.Keybind): + if m.help == nil { + return nil + } m.help.SetShowAll(!m.help.ShowAll()) - m.updateHelpHeight() + m.rootFlex.ResizeItem(m.help, m.helpHeight(), 0) return nil case keybind.Matches(msg, m.cfg.Keybinds.Suspend.Keybind): return suspend() @@ -231,10 +239,10 @@ func (m *Model) finishModal(done modal.DoneMsg) tview.Cmd { return tview.Sequence(focus, func() tview.Msg { return result }) } -func (m *Model) updateHelpHeight() { +func (m *Model) helpHeight() int { height := 1 if m.help.ShowAll() { height = max(len(m.help.FullHelpLines(m.FullHelp(), 0)), 1) } - m.rootFlex.ResizeItem(m.help, height, 0) + return height } diff --git a/internal/ui/root/model_test.go b/internal/ui/root/model_test.go new file mode 100644 index 0000000..75b3774 --- /dev/null +++ b/internal/ui/root/model_test.go @@ -0,0 +1,52 @@ +package root + +import ( + "path/filepath" + "testing" + + "github.com/ayn2op/discordo/internal/config" + "github.com/gdamore/tcell/v3" +) + +func TestHelpEnabled(t *testing.T) { + cfg, err := config.Load(filepath.Join(t.TempDir(), "missing.toml")) + if err != nil { + t.Fatal(err) + } + + t.Run("enabled", func(t *testing.T) { + cfg := *cfg + cfg.Help.Enabled = true + m := NewModel(&cfg) + if m.help == nil { + t.Fatal("help model was not created") + } + if count := m.rootFlex.GetItemCount(); count != 1 { + t.Fatalf("layout item count = %d, want 1", count) + } + if height := m.helpHeight(); height != 1 { + t.Fatalf("height = %d, want 1", height) + } + + m.Update(tcell.NewEventKey(tcell.KeyRune, ".", tcell.ModCtrl)) + if !m.help.ShowAll() { + t.Fatal("toggle_help did not enable full help") + } + }) + + t.Run("disabled", func(t *testing.T) { + m := NewModel(cfg) + + if m.help != nil { + t.Fatal("help model was created") + } + if count := m.rootFlex.GetItemCount(); count != 0 { + t.Fatalf("layout item count = %d, want 0", count) + } + + m.Update(tcell.NewEventKey(tcell.KeyRune, ".", tcell.ModCtrl)) + if m.help != nil { + t.Fatal("toggle_help created help model") + } + }) +}