palette

package
v0.2.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 19, 2026 License: MIT Imports: 5 Imported by: 0

Documentation

Overview

Package palette is a fuzzy, type-to-filter command list for a command-palette dialog. Typing narrows the visible commands with subsequence (fuzzy) matching - the sibling list package uses substring - up/down (and ctrl+p/ctrl+n) move the cursor, and the caller reads Selected() on its own accept key. Like the list, the palette never consumes enter or esc: accept and cancel belong to the wrapping dialog.

Selecting a command yields its Entry, whose Key is the literal keybinding the caller replays via key.Replay (e.g. "t", "c", "tab"). The palette executes nothing itself, so an invocation routes through the exact keyboard path the user could have typed - a command surfaced here can never drift from the key it is bound to.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Entry

type Entry struct {
	Name string // command name shown first, e.g. "transition"
	Desc string // one-line description
	Key  string // keybinding to replay on selection
}

Entry is one palette command. Key is the literal keybinding the caller replays when this entry is chosen (e.g. "t", "c", "tab") - the palette never executes anything itself, so an invocation can never drift from the keyboard.

type Model

type Model struct {
	// contains filtered or unexported fields
}

Model is a filterable command list. Zero value is unusable; construct with New.

func New

func New(title string, entries []Entry, styles Styles) Model

New builds a palette over entries, titled title, cursor on the first match and an empty (all-matching) filter.

func (*Model) CursorLine

func (m *Model) CursorLine() int

CursorLine returns the zero-based line offset of the selected row within View(), so a scrolling container can keep the selection in view. The layout is title, query, then one line per match, and the rows are short single-line commands (no wrapping), so the cursor sits two lines below the top plus its position among the matches. Zero when nothing matches.

func (*Model) Query

func (m *Model) Query() string

Query returns the current filter text, for tests and callers that echo it.

func (*Model) Selected

func (m *Model) Selected() (Entry, bool)

Selected returns the entry under the cursor; ok is false when the filter matches nothing (or the palette is empty). Meaningful after the caller decides to accept.

func (*Model) Update

func (m *Model) Update(msg tea.Msg) tea.Cmd

Update handles filter typing (runes, backspace) and cursor movement (up/ctrl+p, down/ctrl+n). It deliberately does NOT handle enter or esc: the caller (a dialog wrapper) owns accept and cancel. A palette that swallowed enter could accept a command its wrapper meant to veto, and one that swallowed esc could trap a user who wanted out - keeping both keys with the caller makes the accept/cancel contract single-owned. Returns a cmd (currently always nil) and is a no-op for messages it does not recognize.

func (*Model) View

func (m *Model) View() string

View renders the title, the query line, and the filtered rows. Each row is "name - desc" with the fuzzy-matched runes styled via Match, the replay key styled via KeyHint at the row end, and the cursor row wrapped in Selected. Rows appear in input order among matches (a stable filter); non-matches are hidden. An empty match set renders a muted placeholder line.

type Styles

type Styles struct {
	Title    lg.Style
	Query    lg.Style // the typed filter text / prompt
	Name     lg.Style
	Match    lg.Style // fuzzy-matched runes within the name
	Desc     lg.Style
	Selected lg.Style // the highlighted row
	KeyHint  lg.Style // the entry's replay key, shown at the row end
}

Styles are injected so the widget stays theme-agnostic.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL