diff --git a/menu/model.go b/menu/model.go index e52acf7..7b79842 100644 --- a/menu/model.go +++ b/menu/model.go @@ -49,8 +49,75 @@ type Model struct { help help.Model } +// Option is an optional [Model] configuration function. +type Option func(*Model) + +// WithShowPagination returns an [Option] +// whether the list shows pagination indictors. +func WithShowPagination(show bool) Option { + return func(mod *Model) { mod.list.SetShowPagination(show) } +} + +// WithShowTitle returns an [Option] +// whether to show the list title. +func WithShowTitle(show bool) Option { + return func(mod *Model) { mod.list.SetShowTitle(show) } +} + +// WithFilteringEnabled returns an [Option] +// whether the list allows filtering. +func WithFilteringEnabled(enabled bool) Option { + return func(mod *Model) { mod.list.SetFilteringEnabled(enabled) } +} + +// WithShowFilter returns an [Option] +// whether the list shows the active filter. +func WithShowFilter(show bool) Option { + return func(mod *Model) { mod.list.SetShowFilter(show) } +} + +// WithShowStatusBar returns an [Option] +// whether to show the list's status bar. +func WithShowStatusBar(show bool) Option { + return func(mod *Model) { mod.list.SetShowStatusBar(show) } +} + +// WithShowHelp returns an [Option] +// whether to always show help for active keybindings. +func WithShowHelp(show bool) Option { + return func(mod *Model) { mod.list.SetShowHelp(show) } +} + +// WithAdditionalFullHelpKeys returns an [Option] +// that replaces the lists's [list.Model.AdditionalFullHelpKeys]. +// +// The list's current slice is passed as argument to the given keys function. +// The keys function can then choose to return a new or modified slice. +func WithAdditionalFullHelpKeys(keys func([]key.Binding) []key.Binding) Option { + return func(mod *Model) { + prev := mod.list.AdditionalFullHelpKeys() + mod.list.AdditionalFullHelpKeys = func() []key.Binding { + return keys(prev) + } + } +} + +// WithAdditionalShortHelpKeys returns an [Option] +// that replaces the lists's [list.Model.AdditionalShortHelpKeys]. +// +// The list's current slice is passed as argument to the given keys function. +// The keys function can then choose to return a new or modified slice. +func WithAdditionalShortHelpKeys(keys func([]key.Binding) []key.Binding) Option { + return func(mod *Model) { + prev := mod.list.AdditionalShortHelpKeys() + mod.list.AdditionalShortHelpKeys = func() []key.Binding { + return keys(prev) + } + } +} + // New setups up a new menu model -func New(title string, choices []Choice, selected *Choice) Model { +func New(title string, choices []Choice, selected *Choice, options ...Option) Model { styles := MenuStyles{ ListTitleStyle: styles.ListTitleStyle, @@ -94,6 +161,10 @@ func New(title string, choices []Choice, selected *Choice) Model { model.SetChoices(choices, selected) + for _, opt := range options { + opt(&model) + } + return model } @@ -127,14 +198,18 @@ func (m Model) SetStyles(s MenuStyles) { } func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { case tea.WindowSizeMsg: m.SetSize(msg) case tea.KeyMsg: - return m.handleKeyMsg(msg, msg) + // Make sure we do not trap keybindings required for editing filters. + // While editing, all messages should be forwarded on to [list.Model]. + if !m.list.SettingFilter() { + if mod, cmd := m.handleKeyMsg(msg, msg); cmd != nil { + return mod, cmd + } + } } - // No selection made yet so update the list var cmd tea.Cmd m.list, cmd = m.list.Update(msg)