multiselect

package
v0.23.0 Latest Latest
Warning

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

Go to latest
Published: Sep 6, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package multiselect demonstrates marking — the multi-selection a user builds with space — on a table.Model, and the action.Set that acts on it.

Press space to mark the cursor row (it toggles both ways), X to extend the selection from the last-marked row down to the cursor, A to mark every row the filter currently shows, D to drop the selection, or click the ✓ gutter. Then press "a" or right-click to open the menu: it is titled with what it will act on ("3 items"), and every verb that did not declare Multi is dimmed with a reason.

X spans either direction from the anchor, which stays put — so ranging again from the same anchor grows or shrinks one span rather than walking it along. Shift+click does the same thing with the mouse. Both are additive, so a range extends a selection rather than replacing it.

Marking is keyed, or it is wrong

Marks are held by the row's Key, not its index, which is why this screen populates the table with SetKeyedRows. On anonymous rows (SetRows) every mark operation is a deliberate no-op: an inert feature is recoverable, and a selection that has silently drifted onto its neighbours is not. That drift is not hypothetical — it is what an index-held mark does the moment a polled refresh reorders the set between the user marking rows and picking a verb.

Two things worth doing to this screen

Mark a row, then filter it out of sight. The count in the title does not move, because a key does not care whether its row is currently visible — so the marked row is still in the selection, and the menu still says "2 items" while one of them is off screen. Correct, and a genuine surprise, which is why the menu's title is the disclosure rather than a decoration.

Then cycle the theme with "t". The marks survive, because SetTheme carries them across the rebuild with SetMarks the same way it carries the cursor and the filter (rule 4). Forgetting that line is invisible until a user loses a twelve-row selection to a keypress that was supposed to change the colours.

Selection() is the accessor to reach for

Not Marks(). Selection() is "the marked keys, or the cursor's key when nothing is marked", which is the branch every caller would otherwise write by hand and some would forget — and whose failure mode is a verb quietly acting on one row when the user had marked six.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func New

func New(t theme.Theme) screen.Screen

New returns the multi-select demo's root screen.

Types

type Screen

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

Screen is an ordinary table screen. Marking is one Options field; acting on the marks is the Actions method at the bottom.

func (*Screen) Actions

func (s *Screen) Actions() action.Set

Actions satisfies action.Provider. It is rebuilt per call, so it reports on whatever is selected right now.

Every verb reads Selection() identically whether the user marked six rows or marked nothing and left the cursor on one. The arity difference lives in the Multi field, and the menu — not this code — is what enforces it.

func (*Screen) Help

func (s *Screen) Help() []key.Binding

Help leans on the table, which already advertises x, X, A and D because Markable is set — the bindings and the hints come from the same Keys struct (rule 26), so nothing here restates them. The verbs are absent on purpose: moving discovery off the footer and into the menu is most of the point.

func (*Screen) Init

func (s *Screen) Init() tea.Cmd

func (*Screen) IsCapturingKeys

func (s *Screen) IsCapturingKeys() bool

func (*Screen) Layout

func (s *Screen) Layout() layout.Node

func (*Screen) OnEnter

func (s *Screen) OnEnter(any) tea.Cmd

func (*Screen) SetTheme

func (s *Screen) SetTheme(t theme.Theme)

func (*Screen) Title

func (s *Screen) Title() string

func (*Screen) Update

func (s *Screen) Update(msg tea.Msg) (screen.Screen, tea.Cmd)

Jump to

Keyboard shortcuts

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