Documentation
¶
Overview ¶
Package palette provides a command-palette bubble for Bubble Tea programs. Hosts compose one or more Modes: each Mode owns its own Match (which inputs it claims), Items (the candidate list), and optionally an async Search dispatcher and typeable Facets. With no WithModes, the palette uses a single empty catch-all mode; the palette renders cleanly but shows no items until hosts wire one up.
Index ¶
- func ParseFacets(input string, facets []Facet) (text string, parsed map[string][]string)
- type Command
- type DefaultDelegate
- type DefaultItem
- type DelegateStyles
- type Facet
- type FacetResultMsg
- type Item
- type ItemDelegate
- type KeyMap
- type Mode
- type Model
- func (m *Model) Blur()
- func (m Model) Cursor() int
- func (m *Model) Focus() tea.Cmd
- func (m Model) FullHelp() [][]key.Binding
- func (m Model) Init() tea.Cmd
- func (m Model) InnerWidth() int
- func (m Model) IsSelected(visibleIndex int) bool
- func (m Model) Items() []Item
- func (m Model) Loading() bool
- func (m Model) Mode() Mode
- func (m Model) Page() int
- func (m Model) Query() string
- func (m *Model) Reset()
- func (m Model) Results(modeName string) []Item
- func (m Model) Selected() Item
- func (m *Model) SetHeight(h int)
- func (m *Model) SetWidth(w int)
- func (m Model) ShortHelp() []key.Binding
- func (m Model) TotalPages() int
- func (m Model) Update(msg tea.Msg) (Model, tea.Cmd)
- func (m Model) Value() string
- func (m Model) View() string
- func (m Model) Width() int
- type Option
- func WithDelegate(d ItemDelegate) Option
- func WithEmptyMessage(s string) Option
- func WithHelp(show bool) Option
- func WithKeyMap(km KeyMap) Option
- func WithModes(modes ...Mode) Option
- func WithOnExecute(fn func(Item) tea.Cmd) Option
- func WithPageSize(n int) Option
- func WithPaginatorType(t paginator.Type) Option
- func WithPlaceholder(s string) Option
- func WithStyles(s Styles) Option
- func WithTitle(s string) Option
- type SearchResultMsg
- type SelectedMsg
- type Styles
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ParseFacets ¶
ParseFacets tokenizes input on whitespace and returns the free-text portion (tokens that aren't registered facets, joined with single spaces) plus a map of facet name → values. Use this from a Mode's Items/Search closures to apply facet filters without re-implementing the parser.
Types ¶
type Command ¶
type Command struct {
ID string
Name string
Desc string
// Run is invoked when the user selects this command and presses
// Enter. It may return nil if there's nothing to dispatch.
Run func() tea.Cmd
}
Command is a built-in Item for command-style palettes. Implements DefaultItem so the DefaultDelegate renders it without extra work, and carries an optional Run hook the host can fire on Enter.
func (Command) Description ¶
Description is rendered as the secondary line by DefaultDelegate.
func (Command) FilterValue ¶
FilterValue is what fuzzy matching is performed against.
type DefaultDelegate ¶
type DefaultDelegate struct {
Styles DelegateStyles
ShowDescription bool
}
DefaultDelegate renders DefaultItems with a title/description layout and a selection marker. When ShowDescription is false, only the title line is drawn.
func NewDefaultDelegate ¶
func NewDefaultDelegate() DefaultDelegate
NewDefaultDelegate returns a DefaultDelegate with sensible defaults. Selected rows are rendered with reverse-video so the highlight reads against any terminal palette without picking a brand color.
func (DefaultDelegate) Height ¶
func (d DefaultDelegate) Height() int
Height reports two rows when ShowDescription is on, one otherwise.
func (DefaultDelegate) Render ¶
Render draws one item: a selection marker followed by the title, and (when ShowDescription is on and the item exposes one) a faint description line indented under the title. Selected rows fill the palette's width so the highlight background reaches the right edge. Text is truncated to the palette's current width when known.
func (DefaultDelegate) Spacing ¶
func (d DefaultDelegate) Spacing() int
Spacing reports zero blank rows between items by default.
type DefaultItem ¶
DefaultItem is the convention DefaultDelegate knows how to render. Implement this if you want title/description rendering out of the box.
type DelegateStyles ¶
type DelegateStyles struct {
Title lipgloss.Style
Description lipgloss.Style
SelectedTitle lipgloss.Style
SelectedDesc lipgloss.Style
SelectionMarker string
UnselectedMarker string
}
DelegateStyles holds the styles used by DefaultDelegate.
type Facet ¶
type Facet struct {
// Name is the prefix users type before ":" to trigger completion.
// Should not contain whitespace or ":".
Name string
// Desc is an optional context hint shown above the value list
// while completing this facet.
Desc string
// Items returns sync values for the given partial. The host owns
// the filtering; the palette doesn't post-filter the returned
// slice.
Items func(partial string) []Item
// Resolve dispatches an async value lookup. The returned tea.Cmd
// must eventually emit a FacetResultMsg whose Facet and Partial
// match the inputs. The ctx is canceled when the partial changes,
// the cursor leaves the token, or the palette is Reset.
Resolve func(ctx context.Context, partial string) tea.Cmd
// Debounce delays Resolve dispatch after the partial last changed.
// Ignored when Resolve is nil.
Debounce time.Duration
}
Facet defines a token-based filter inside a Mode. When the cursor sits inside a "<Name>:<partial>" token in the input, the palette enters a value-completion sub-state listing this facet's matching values. Exactly one of Items or Resolve must be set; if both are, Items wins.
type FacetResultMsg ¶
FacetResultMsg is what Facet.Resolve eventually emits. The palette drops it as stale when Facet/Partial no longer match the cursor's current token.
type Item ¶
type Item interface {
FilterValue() string
}
Item is anything that can appear in the palette list. Both predefined commands and async search results implement it.
func FilterFuzzy ¶
FilterFuzzy returns items whose FilterValue is a fuzzy-subsequence match for query, ordered by relevance (best first). An empty query returns the input unchanged. Exported so a Mode's Items closure can fuzzy-filter its own item slice without re-implementing the matcher.
type ItemDelegate ¶
type ItemDelegate interface {
// Height is the number of terminal rows one item occupies.
Height() int
// Spacing is the number of blank rows between adjacent items.
Spacing() int
// Update receives messages while the delegate is active. Implement
// item-level keybindings here, or return nil to opt out.
Update(msg tea.Msg, m *Model) tea.Cmd
// Render draws one item at the given visible index to w.
Render(w io.Writer, m Model, index int, item Item)
}
ItemDelegate controls how an Item is rendered and how key events reach the currently selected item. Mirrors bubbles/list.ItemDelegate.
type KeyMap ¶
type KeyMap struct {
Execute key.Binding
Cancel key.Binding
Down key.Binding
Up key.Binding
NextPage key.Binding
PrevPage key.Binding
// combined arrow legend (default "↑↓ navigate"). It's never
// matched in Update — Up/Down/Ctrl+P/Ctrl+N do the actual cursor
// work. Override the help text (e.g. "↑↓ select") by reassigning
// this field.
Navigate key.Binding
}
KeyMap holds the palette's keybindings. Override individual fields to remap; pass the whole struct via WithKeyMap to swap wholesale.
type Mode ¶
type Mode struct {
// Name identifies the mode for logging and host status displays.
// Also used as the cache key for Search results — see
// Model.Results.
Name string
// Prompt is the glyph rendered before the input field. Should be
// the same display width as the configured spinner so the input
// text doesn't shift when the spinner swaps in during search. An
// empty Prompt falls back to defaultPrompt ("⣿ ").
Prompt string
// Placeholder is the hint text shown in the input while it's empty
// and this mode is active. Empty falls back to the palette-level
// placeholder set via WithPlaceholder.
Placeholder string
// EmptyMessage is shown in place of the item list when this mode
// is active, the user has typed a query, and Items returns no
// candidates. Empty falls back to the palette-level message set
// via WithEmptyMessage; when both are empty no message is rendered.
EmptyMessage string
// Debounce is how long the palette waits after the input stops
// changing before invoking Search. Zero means dispatch on the
// next tick. Ignored when Search is nil.
Debounce time.Duration
// Match reports whether this mode applies to the given raw input.
// A nil Match matches anything.
Match func(input string) bool
// Query extracts the meaningful query string from the raw input —
// typically by stripping a leading prefix. A nil Query returns
// the input unchanged.
Query func(input string) string
// Items returns the candidate items for this mode given the
// palette state and the extracted query. For sync modes it does
// the filtering inline; for async modes it typically reads from
// the palette's Results cache that Search populates. A nil Items
// returns nil.
Items func(m Model, query string) []Item
// Search is the async dispatcher. When the input changes inside
// this mode and the debounce window elapses, the palette calls
// Search and the returned tea.Cmd must eventually yield a
// SearchResultMsg with the matching Mode name. The ctx is
// canceled when a newer search supersedes this one or when the
// active mode changes — implementations should pass it through
// to their HTTP/DB call. Nil means the mode is purely synchronous.
Search func(ctx context.Context, query string) tea.Cmd
// Facets registers typeable "<Name>:<value>" filters for this
// mode. When the cursor sits inside such a token, the palette
// swaps the item list for a value picker scoped to the matching
// Facet. See palette.ParseFacets to apply parsed filters from a
// Mode's Items/Search closure.
Facets []Facet
}
Mode describes how the palette interprets the current input. The active mode is the first one in the configured list whose Match returns true; a nil Match matches anything, so it's typically used as the fallback (last entry).
type Model ¶
Model is the palette bubble.
func (Model) Cursor ¶
Cursor returns the absolute index of the highlighted item in the currently visible items list. Stable across page changes and safe to call from inside ItemDelegate.Render.
func (Model) FullHelp ¶
FullHelp returns the expanded key groups for help bubbles displaying the full layout (not used by the palette itself by default, but available for hosts that wire up "?"-toggled help).
func (Model) Init ¶
Init is part of the tea.Model contract. The palette emits no startup command — callers compose it into their own program's Init.
func (Model) InnerWidth ¶
InnerWidth is the usable width inside the Container border/padding. Returns 0 when the outer width has not yet been set.
func (Model) IsSelected ¶
IsSelected reports whether the given visible-row index in the current page is the highlighted row. ItemDelegate.Render implementations should use this instead of comparing against a raw cursor field — it's correct on every page and zero outside a Render call (so it's safe to call defensively).
func (Model) Items ¶
Items returns the candidate items currently visible in the palette. During facet completion this is the active Facet's value list (sync via Facet.Items or the cached async results); otherwise it's the active Mode's items.
func (Model) Mode ¶
Mode returns the currently active Mode — the first in the configured list whose Match returns true (or whose Match is nil). Returns a zero Mode when no modes are configured.
func (Model) Query ¶
Query returns the active mode's interpretation of the input value (typically with a leading prefix stripped). Falls back to the raw input when the active mode has no Query function.
func (*Model) Reset ¶
func (m *Model) Reset()
Reset clears the input and result state, and cancels any in-flight Search or facet Resolve.
func (Model) Results ¶
Results returns the cached items for the named mode (typically populated by that mode's Search closure via SearchResultMsg). A mode's Items closure usually reads from here.
func (*Model) SetHeight ¶
SetHeight overrides the palette's outer height. Currently advisory — pagination is driven by WithPageSize.
func (*Model) SetWidth ¶
SetWidth overrides the palette's outer width. Useful when the palette is laid out manually (e.g., as a fixed-width modal overlay) rather than filling the host's WindowSizeMsg.
func (Model) ShortHelp ¶
ShortHelp returns the compact key list rendered by the help bubble at the bottom of the palette. Combines Up/Down into a single synthetic "↑↓ navigate" entry for legibility; the actual KeyMap bindings remain split since they're separate actions.
func (Model) Update ¶
Update handles cursor navigation, the async search lifecycle (debounce → dispatch → result), spinner ticks, and forwards remaining messages to the textinput.
func (Model) View ¶
View composes the palette layout: an optional title, the text input, and the visible items rendered through the configured ItemDelegate, wrapped in the Container style. Items are passed the inner width so the delegate's selection background can fill the row. The spinner row and paginator footer land in later milestones.
func (Model) Width ¶
Width returns the column width available for rendering a row. During ItemDelegate.Render this is the inner row width (set by the palette for that render pass); elsewhere it falls back to InnerWidth so callers can ask "how wide is my content area?" with one method regardless of context.
type Option ¶
type Option func(*Model)
Option configures a palette Model. Apply with New(...Option).
func WithDelegate ¶
func WithDelegate(d ItemDelegate) Option
WithDelegate overrides the ItemDelegate used to render items.
func WithEmptyMessage ¶
WithEmptyMessage sets the default text shown in place of the item list when the user has typed a query but the active mode returns no candidates. Modes can override this for their own context via Mode.EmptyMessage. The message is suppressed while a search is in flight (the spinner is the loading indicator) and while a facet completion is active.
func WithModes ¶
WithModes replaces the default empty mode with the supplied modes, in priority order — the first whose Match returns true wins. Make the last entry a fallback (Match: nil) so some mode always applies.
func WithOnExecute ¶
WithOnExecute registers a callback fired synchronously inside the palette's Update when the user presses Execute (Enter) on a highlighted item. The returned tea.Cmd is batched alongside the SelectedMsg dispatch and any Command.Run() cmd, so hosts can:
- read the selected Item without pattern-matching on SelectedMsg;
- return a "close overlay" / "dispatch action" cmd in the same tick the keypress was received;
- keep Command.Run chaining cleanly (the hook is additive).
Return nil to opt out of adding a cmd for a particular item.
func WithPageSize ¶
WithPageSize sets a fixed number of items per page. Pass 0 to auto-fit to the available terminal height (the default).
func WithPaginatorType ¶
WithPaginatorType selects between dot indicators and "1/N" numeric.
func WithPlaceholder ¶
WithPlaceholder sets the default hint text shown in the input while it's empty. Modes can override this for their own context via Mode.Placeholder.
type SearchResultMsg ¶
SearchResultMsg is the message a Mode's Search closure eventually emits with the items matching a given query. Mode is the Name of the mode that produced this result — the palette uses it to route the items into the right per-mode cache and to reject results from a mode that's no longer active. Err is non-nil if the search failed; Results should be ignored in that case.
type SelectedMsg ¶
type SelectedMsg struct {
Item Item
}
SelectedMsg is dispatched when the user presses Execute (Enter by default) on a highlighted item. The host program type-switches on Item to decide how to react — close the palette, log, navigate, etc. When the item is a Command with a non-nil Run, the palette also fires Run()'s tea.Cmd in the same batch.
type Styles ¶
type Styles struct {
// Container wraps the whole palette. The default is a rounded
// border with no padding — padding is applied manually as a
// per-line indent so selection backgrounds can fill the full row.
Container lipgloss.Style
// Title styles the optional section header at the top of the
// palette (see WithTitle).
Title lipgloss.Style
// Indent is the per-line left margin inside the container, as a
// literal string. Two spaces by default.
Indent string
// Prompt styles the leading mode-prompt glyph rendered in front of
// the input. Not applied while the spinner is in flight (the
// spinner owns its own styling).
Prompt lipgloss.Style
// Placeholder styles the textinput's placeholder text shown while
// the input is empty. Propagated into the underlying textinput's
// Focused / Blurred placeholder styles.
Placeholder lipgloss.Style
// EmptyMessage styles the no-results message rendered in place of
// the item list when the active mode returns no candidates for the
// current query. See Mode.EmptyMessage and WithEmptyMessage.
EmptyMessage lipgloss.Style
// SpinnerLabel styles the text next to the spinner glyph while a
// search is in flight.
SpinnerLabel lipgloss.Style
// FacetHeader styles the facet-completion hint shown in the footer
// row while the palette is completing a facet token.
FacetHeader lipgloss.Style
Footer lipgloss.Style
}
Styles holds the lipgloss styles the palette uses to render itself.
func DefaultStyles ¶
func DefaultStyles() Styles
DefaultStyles returns sensible defaults. Override fields individually or pass a whole struct via WithStyles.