Documentation
¶
Index ¶
- Constants
- Variables
- func BindingHints(r *Runtime, focus string) string
- func Call(ctx context.Context, path string, q Request) (any, error)
- func ComposeModal(background, title, body, footer string, width, height int, styles Styles) string
- func InputView(in *Input, width, height int) string
- func IntArg(a Arguments, name string, fallback int) int
- func JSONPointer(value any, path string) (any, error)
- func JobsTicker(jobs []JobInfo, width int) []string
- func ModalSize(width, height int) (contentWidth, contentHeight int)
- func PanelContentSize(width, height int) (int, int)
- func ParseSchemes(data []byte) (map[string]Scheme, []string)
- func RegisterInputOperations(r *Runtime)
- func StringArg(a Arguments, name, fallback string) string
- func TableText(cols []Column, rows [][]string, width int) []string
- type Action
- type Align
- type AppHandler
- type Appearance
- type ArgumentError
- type Arguments
- type Argv
- type Binding
- func (b Binding) Captured() Binding
- func (b Binding) FromKey(arg string) Binding
- func (b Binding) FromPayload(arg, source string) Binding
- func (b Binding) FromRow(arg, field string) Binding
- func (b Binding) Guard(name string) Binding
- func (b Binding) Hide() Binding
- func (b Binding) Hinted(text string) Binding
- func (b Binding) Join(arg string, sources ...string) Binding
- type BindingTimeoutMsg
- type Block
- type CallMsg
- type Choice
- type Chooser
- func (c *Chooser) Close()
- func (c *Chooser) HandleMessage(tea.Msg) bool
- func (c *Chooser) Highlighted() (ChooserRow, bool)
- func (c *Chooser) Kind() string
- func (c *Chooser) Matches() []ChooserRow
- func (c *Chooser) ModalBlock(_ Styles, width, height int) Block
- func (c *Chooser) ModalTitle() string
- func (c *Chooser) Moved() bool
- func (c *Chooser) PendingCommand() tea.Cmd
- func (c *Chooser) Query() string
- func (c *Chooser) SetRows(rows []ChooserRow)
- func (c *Chooser) Title() string
- func (c *Chooser) View(width, height int) Block
- type ChooserRow
- type ChooserSpec
- type Column
- type Completer
- func (c *Completer) Close()
- func (c *Completer) DebounceCurrent(msg CompletionDebounceMsg) bool
- func (c *Completer) DebounceTick() (CompletionDebounceMsg, bool)
- func (c *Completer) Err() error
- func (c *Completer) HandleMessage(msg tea.Msg) bool
- func (c *Completer) Highlighted() int
- func (c *Completer) Input() string
- func (c *Completer) Open() bool
- func (c *Completer) PendingCommand() tea.Cmd
- func (c *Completer) Searching() bool
- func (c *Completer) State() map[string]any
- func (c *Completer) Suggestions() []Suggestion
- func (c *Completer) Token() (CompletionToken, bool)
- type Completion
- type CompletionDebounceMsg
- type CompletionSearch
- type CompletionToken
- type CompletionTrigger
- type Component
- type Config
- func (c *Config) ActionProblems() []string
- func (c *Config) BindingProblems() []string
- func (c *Config) Close()
- func (c *Config) Directory() string
- func (c *Config) Disable()
- func (c *Config) Flush() error
- func (c *Config) FrameworkTheme() bool
- func (c *Config) HandleMessage(tea.Msg) bool
- func (c *Config) HistoryPath() string
- func (c *Config) PanesPath() string
- func (c *Config) Path(name string) string
- func (c *Config) Paths() ConfigPaths
- func (c *Config) PendingCommand() tea.Cmd
- func (c *Config) Schemes() map[string]Scheme
- func (c *Config) StateDirectory() string
- type ConfigExport
- type ConfigPaths
- type Context
- type Ctx
- type Detail
- type EditNode
- type FocusTargeter
- type Footer
- type Guard
- type Handler
- type Header
- type HelpRow
- type HistoryContext
- type HistoryEntry
- type HistoryMove
- type HistoryPlace
- type HistoryResult
- type Input
- type Instance
- type InstanceOption
- func CloseOnDetach() InstanceOption
- func Columns(cols ...Column) InstanceOption
- func Completions(triggers ...CompletionTrigger) InstanceOption
- func Focus(id string) InstanceOption
- func FocusOnClose(id string) InstanceOption
- func Kind(noun string) InstanceOption
- func NoMarks() InstanceOption
- func NoSpill() InstanceOption
- func Parent(id string) InstanceOption
- type JobInfo
- type JobLingerMsg
- type KeyEvent
- type Layout
- func (l Layout) BodySize() (width, height int)
- func (l Layout) BodySizeWith(f Footer) (width, height int)
- func (l Layout) Divide(first, total, least int) int
- func (l Layout) Page(title, subtitle, body, footer string) string
- func (l Layout) PageBlock(title, subtitle string, body Block, footer string) Block
- func (l Layout) Panel(title, body string, width, height int, focused bool) string
- func (l Layout) PanelBlock(title string, body Block, width, height int, focused bool) Block
- func (l Layout) Shell(h Header, body Block, f Footer) Block
- func (l Layout) Sidebar(title string, items []string, selected int, mainTitle, mainBody string) string
- func (l Layout) SidebarBlock(title string, items []string, selected int, mainTitle string, mainBody Block) Block
- func (l Layout) Split(leftTitle, leftBody, rightTitle, rightBody string) string
- func (l Layout) SplitBlock(leftTitle string, leftBody Block, rightTitle string, rightBody Block) Block
- func (l Layout) SplitFocusBlock(focused SplitSide, leftTitle string, leftBody Block, rightTitle string, ...) Block
- func (l Layout) TickerRule(jobs []string, width int) string
- type Lines
- type List
- func (l *List) ColumnOffset() int
- func (l *List) Columns() []Column
- func (l *List) Filter() string
- func (l *List) Filtering() bool
- func (l *List) Focus() error
- func (l *List) FocusTarget() string
- func (l *List) Focused() bool
- func (l *List) Height() int
- func (l *List) Items() []ListItem
- func (l *List) Len() int
- func (l *List) Marked() []ListItem
- func (l *List) Move(delta int)
- func (l *List) Patch(p ListPatch) error
- func (l *List) Select(id string) error
- func (l *List) Selected() (ListItem, bool)
- func (l *List) SetColumns(cols ...Column)
- func (l *List) SetFilter(query string)
- func (l *List) SetItems(items []ListItem) error
- func (l *List) Shown() int
- func (l *List) Snapshot() map[string]any
- func (l *List) ToggleMark(id string) error
- func (l *List) View(width, height int) string
- type ListItem
- type ListPatch
- type MacroKey
- type MacroState
- type ModalBody
- type ModalOption
- type ModalView
- type ModeBuilder
- func (m *ModeBuilder) Bind(keys string, row Binding) *ModeBuilder
- func (m *ModeBuilder) Extends(parent string) *ModeBuilder
- func (m *ModeBuilder) Pattern(pattern string, row Binding) *ModeBuilder
- func (m *ModeBuilder) Unbind(keysOrPattern string) *ModeBuilder
- func (m *ModeBuilder) UnbindGuarded(keysOrPattern, guard string) *ModeBuilder
- func (m *ModeBuilder) When(guard string) *ModeBuilder
- type ModeObserver
- type ModeState
- type Model
- type NoticeID
- type Noun
- type NounBuilder
- func (b *NounBuilder) Action(key string, h Handler) *NounBuilder
- func (b *NounBuilder) Columns(cols ...Column) *NounBuilder
- func (b *NounBuilder) Completions(triggers ...CompletionTrigger) *NounBuilder
- func (b *NounBuilder) Confirm(prompt string) *NounBuilder
- func (b *NounBuilder) Fetch() *NounBuilder
- func (b *NounBuilder) Focusable() *NounBuilder
- func (b *NounBuilder) Mode(mode string) *ModeBuilder
- func (b *NounBuilder) Motion() *NounBuilder
- func (b *NounBuilder) Noun() *Noun
- func (b *NounBuilder) PersistArgs() *NounBuilder
- func (b *NounBuilder) Pin(mode string) *NounBuilder
- func (b *NounBuilder) Positional(names ...string) *NounBuilder
- func (b *NounBuilder) Quiet() *NounBuilder
- func (b *NounBuilder) Region() *NounBuilder
- func (b *NounBuilder) Rows(noun string) *NounBuilder
- func (b *NounBuilder) State() *NounBuilder
- func (b *NounBuilder) Verb(verb string, h any, description ...string) *NounBuilder
- func (b *NounBuilder) Verbs(verbs ...string) *NounBuilder
- func (b *NounBuilder) When(guard string) *NounBuilder
- type Operation
- type Page
- type Palette
- func (p *Palette) Close()
- func (p *Palette) HandleKey(key string) (bool, error)
- func (p *Palette) IsActive() bool
- func (p *Palette) IsOpen() bool
- func (p *Palette) Open() error
- func (p *Palette) RegisterNoun(noun string, config PaletteNoun) error
- func (p *Palette) Text() string
- func (p *Palette) View() string
- func (p *Palette) ViewSized(width, height int) string
- type PaletteEntry
- type PaletteInstance
- type PaletteNoun
- type PaletteSource
- type PaletteWord
- type Parameter
- type Payload
- type Picker
- type PickerEntry
- type Placement
- type Pos
- type Predicate
- func AllOf(of ...Predicate) Predicate
- func AnyOf(of ...Predicate) Predicate
- func ByID(id string) Predicate
- func ByKind(kind string) Predicate
- func ByNoun(noun string) Predicate
- func ChildOf(id string) Predicate
- func InState(mode string) Predicate
- func IsFocusable() Predicate
- func IsRegion() Predicate
- func Not(of ...Predicate) Predicate
- func ParsePredicates(v any) ([]Predicate, error)
- func Where(name, arg string) Predicate
- func Within(id string) Predicate
- type PredicateFunc
- type QueryMatch
- type Record
- type RecordDebounceMsg
- type RecordEditor
- func (e *RecordEditor) Block(width, height int) Block
- func (e *RecordEditor) Close()
- func (e *RecordEditor) Closed() bool
- func (e *RecordEditor) DebounceCurrent(tick RecordDebounceMsg) bool
- func (e *RecordEditor) Failure() error
- func (e *RecordEditor) Flush() error
- func (e *RecordEditor) Focus() error
- func (e *RecordEditor) FocusTarget() string
- func (e *RecordEditor) HandleMessage(msg tea.Msg) bool
- func (e *RecordEditor) ID() string
- func (e *RecordEditor) ModalBlock(s Styles, width, height int) Block
- func (e *RecordEditor) ModalTitle() string
- func (e *RecordEditor) PendingCommand() tea.Cmd
- func (e *RecordEditor) Problem(name string) string
- func (e *RecordEditor) Values() Record
- func (e *RecordEditor) WriteError() string
- func (e *RecordEditor) Written() Record
- type RecordField
- type RecordSpec
- type RecordWrite
- type RecordingSink
- type Register
- type Registers
- type Request
- type Response
- type Result
- type Runtime
- func (r *Runtime) Accepts(t Ticket) bool
- func (r *Runtime) ActionFor(focus, key string) Handler
- func (r *Runtime) AddDetail(id string, item func() string, opts ...InstanceOption) (*Detail, error)
- func (r *Runtime) AddInput(in *Input, opts ...InstanceOption) error
- func (r *Runtime) AddList(id string, items []ListItem, opts ...InstanceOption) (*List, error)
- func (r *Runtime) AddPage(id, title string, render func(*Runtime, int, int) Block, ...) (*Page, error)
- func (r *Runtime) AddRecordEditor(id string, spec RecordSpec, opts ...InstanceOption) (*RecordEditor, error)
- func (r *Runtime) AddSettingsPage() (*Page, error)
- func (r *Runtime) AddTerminal(id string, stream TerminalStream, opts ...InstanceOption) (*Terminal, error)
- func (r *Runtime) AddTree(id string, nodes []TreeNode, opts ...InstanceOption) (*Tree, error)
- func (r *Runtime) Ancestry(id string) []string
- func (r *Runtime) BaseFocus() string
- func (r *Runtime) BaseMode() string
- func (r *Runtime) Bind(rows ...Binding) error
- func (r *Runtime) BindingTimeoutCommand() tea.Cmd
- func (r *Runtime) Builtin(register func())
- func (r *Runtime) CancelPendingBinding()
- func (r *Runtime) Catalog() []Operation
- func (r *Runtime) CheckUserBindings() []string
- func (r *Runtime) Children(id string) []*Instance
- func (r *Runtime) Choices(c Context, p Parameter) ([]Choice, error)
- func (r *Runtime) Chooser(kind string) *Chooser
- func (r *Runtime) Completer() *Completer
- func (r *Runtime) CompletionTriggers(id string) []CompletionTrigger
- func (r *Runtime) Config() *Config
- func (r *Runtime) Context() Context
- func (r *Runtime) DeclareSetting(settings ...Setting) error
- func (r *Runtime) Define(name string) *NounBuilder
- func (r *Runtime) DefineGuard(name string, fn Guard)
- func (r *Runtime) DefineMode(name string, pending bool) error
- func (r *Runtime) DefinePassthrough(name string) error
- func (r *Runtime) Deliver(msg tea.Msg) (bool, error)
- func (r *Runtime) Detail(id string) *Detail
- func (r *Runtime) Dispatch(key MacroKey) (bool, error)
- func (r *Runtime) EnsureConfigSettings()
- func (r *Runtime) EnsureHistory()
- func (r *Runtime) EnsureTerminalLeader()
- func (r *Runtime) EnsureUserActions() []string
- func (r *Runtime) EnsureUserBindings() []string
- func (r *Runtime) Execute(q Request) (any, error)
- func (r *Runtime) ExecuteAt(c Context, q Request) (any, error)
- func (r *Runtime) ExportConfig(dir string, force bool) (ConfigExport, error)
- func (r *Runtime) HandleBinding(key string) (bool, error)
- func (r *Runtime) HandleBindingTimeout(msg BindingTimeoutMsg) (bool, error)
- func (r *Runtime) HandleCall(msg CallMsg)
- func (r *Runtime) History(n int) []HistoryEntry
- func (r *Runtime) HistoryOf(n int, kinds ...string) []HistoryEntry
- func (r *Runtime) Input(id string) *Input
- func (r *Runtime) Inputs() []*Input
- func (r *Runtime) Instance(id string, opts ...InstanceOption) *Instance
- func (r *Runtime) InstancePath(id string) []string
- func (r *Runtime) Issue(owner, verb, slot string, c Ctx) (Ticket, context.Context, error)
- func (r *Runtime) IssueAt(owner, scope, verb, slot string, c Ctx) (Ticket, context.Context, error)
- func (r *Runtime) Jobs() []JobInfo
- func (r *Runtime) JumpFocus(steps int, scope string) error
- func (r *Runtime) Launch(owner, verb string, res Result, c Ctx) (Ticket, error)
- func (r *Runtime) List(id string) *List
- func (r *Runtime) ListBindings(focus string) []Binding
- func (r *Runtime) Lists() []*List
- func (r *Runtime) LoadBindingSpec(noun string, data []byte) error
- func (r *Runtime) LoadBindings(data []byte) ([]Binding, error)
- func (r *Runtime) ModalFocus(id string) string
- func (r *Runtime) Modals() []*Instance
- func (r *Runtime) Noun(name string) *Noun
- func (r *Runtime) OpenChooser(spec ChooserSpec) (*Chooser, error)
- func (r *Runtime) OpenModal(kind string, payload Payload, opts ...ModalOption) (*Instance, error)
- func (r *Runtime) OpenPage(id string) error
- func (r *Runtime) OpenPagePicker() (*Chooser, error)
- func (r *Runtime) OpenRecordEditor(id string, spec RecordSpec) (*RecordEditor, error)
- func (r *Runtime) PageFocus(id string) string
- func (r *Runtime) PageList() []*Page
- func (r *Runtime) PageOf(id string) *Page
- func (r *Runtime) PaneLayout(id string, l Layout) Layout
- func (r *Runtime) PaneShift(page string) int
- func (r *Runtime) PendingCommands() tea.Cmd
- func (r *Runtime) Placed(id string)
- func (r *Runtime) PlacedAt(id, text string, focus, height int) string
- func (r *Runtime) Pop() error
- func (r *Runtime) Push(id, focus string) error
- func (r *Runtime) Query(preds ...Predicate) []*Instance
- func (r *Runtime) ReadYank(register string) (Yank, error)
- func (r *Runtime) RecordEditor(id string) *RecordEditor
- func (r *Runtime) Register(o Operation)
- func (r *Runtime) RegisterPage(page *Page, opts ...InstanceOption) error
- func (r *Runtime) RegisterPredicate(name string, fn PredicateFunc)
- func (r *Runtime) Registers() *Registers
- func (r *Runtime) ReloadThemes() []string
- func (r *Runtime) ReloadUserActions() []string
- func (r *Runtime) ReloadUserBindings() []string
- func (r *Runtime) RemoveInstance(id string) error
- func (r *Runtime) RetargetFocus(match func(id string) bool, to string)
- func (r *Runtime) SetConfirm(key, prompt string) error
- func (r *Runtime) SetFocus(id string) error
- func (r *Runtime) SetMode(mode string) error
- func (r *Runtime) SetPaneShift(page string, shift int) (int, error)
- func (r *Runtime) SetTerminalLeader(key string) error
- func (r *Runtime) Settings() *Settings
- func (r *Runtime) Settle(t Ticket, err error) bool
- func (r *Runtime) Snapshot() map[string]any
- func (r *Runtime) Sourced(source string) (restore func())
- func (r *Runtime) Start(owner string, work func(context.Context) (any, error), ...) (Ticket, error)
- func (r *Runtime) StopBindings() []StopBindings
- func (r *Runtime) StoreYank(y Yank, register string, deletion bool) error
- func (r *Runtime) TargetInstance(target string) (string, error)
- func (r *Runtime) Terminal(id string) *Terminal
- func (r *Runtime) TerminalLeader() string
- func (r *Runtime) TopModal() string
- func (r *Runtime) Tree(id string) *Tree
- func (r *Runtime) UI() *UI
- func (r *Runtime) UserActions() []Action
- func (r *Runtime) ValidateBindings() ([]string, error)
- func (r *Runtime) VerbGuard(key string) string
- func (r *Runtime) VerbShown(key, focus string, mode ModeState) bool
- type Scheme
- type SchemeColor
- type SchemeSet
- type Server
- type Setting
- type SettingValue
- type Settings
- func (s *Settings) Bool(name string) bool
- func (s *Settings) Declared() []Setting
- func (s *Settings) Duration(name string) time.Duration
- func (s *Settings) Float(name string) float64
- func (s *Settings) Get(name string) (SettingValue, error)
- func (s *Settings) Int(name string) int
- func (s *Settings) List() []SettingValue
- func (s *Settings) Observe(name string, fn func(name string, value any))
- func (s *Settings) Problems() []string
- func (s *Settings) Reload() []string
- func (s *Settings) ReloadIfChanged() bool
- func (s *Settings) Reset(name string) error
- func (s *Settings) Set(name string, value any) error
- func (s *Settings) String(name string) string
- func (s *Settings) Strings(name string) []string
- func (s *Settings) Value(name string) (any, bool)
- type SettingsPollMsg
- type SplitSide
- type StopBindings
- type Styles
- type Suggestion
- type Terminal
- func (t *Terminal) Close()
- func (t *Terminal) Err() string
- func (t *Terminal) Focused() bool
- func (t *Terminal) Frame() TerminalFrame
- func (t *Terminal) HandleMessage(msg tea.Msg) bool
- func (t *Terminal) ID() string
- func (t *Terminal) PendingCommand() tea.Cmd
- func (t *Terminal) Size() (cols, rows int)
- func (t *Terminal) View(width, height int) string
- func (t *Terminal) ViewBlock(width, height int) Block
- type TerminalFrame
- type TerminalReleaser
- type TerminalStream
- type Ticket
- type Tree
- func (t *Tree) Block(width, height int) Block
- func (t *Tree) Close()
- func (t *Tree) CollapseAll() error
- func (t *Tree) Collapsed(id string) bool
- func (t *Tree) DebounceCurrent(tick TreeDebounceMsg) bool
- func (t *Tree) Editable() bool
- func (t *Tree) Editing() string
- func (t *Tree) Failure() error
- func (t *Tree) Flush() error
- func (t *Tree) Focus() error
- func (t *Tree) FocusTarget() string
- func (t *Tree) HandleMessage(msg tea.Msg) bool
- func (t *Tree) ID() string
- func (t *Tree) List() *List
- func (t *Tree) Nodes() []TreeNode
- func (t *Tree) PendingCommand() tea.Cmd
- func (t *Tree) Record(a TreeAction) error
- func (t *Tree) Select(id string) error
- func (t *Tree) Selected() (TreeNode, bool)
- func (t *Tree) SetCollapsed(id string, collapsed bool) error
- func (t *Tree) SetNodes(nodes []TreeNode) error
- func (t *Tree) View(width, height int) string
- type TreeAction
- type TreeChange
- type TreeDebounceMsg
- type TreeNode
- type UI
- type UIMessage
- type UISink
- type Yank
Examples ¶
Constants ¶
const ( SettingsReferenceFile = "settings.reference.json" BindingsReferenceFile = "bindings.reference.json" ActionsExampleFile = "actions.example.json" ThemesExampleFile = "themes.example.json" ReferenceReadme = "README.md" )
The files config.export writes.
const ( BindingsFile = "bindings.json" SettingsFile = "settings.json" )
BindingsFile and SettingsFile are the file names in the config directory.
const ( JobRunning = "running" JobDone = "done" JobFailed = "failed" JobCancelled = "cancelled" )
Job states as jobs.list and the snapshot report them.
const ( KindInteraction = "interaction" // runs synchronously on the loop (default) KindApplication = "application" // an AppHandler; pending work runs off the loop )
Operation kinds.
const ( HistoryAction = "action" HistoryChange = "change" HistoryFetch = "fetch" HistorySystem = "system" )
The kinds of history entry (HistoryEntry.Kind, Operation.HistoryKind). An action is the user's interaction (a motion, a focus, page or modal move, a mode, the palette's line), a change is an edit or a mutating verb (what dot-repeat reads), a fetch asks for data (a state, list or show verb, a reload, a host calling an extension). HistorySystem is reserved for what the runtime does on its own (a resize, a job that finished); no entry has it yet.
const ( PaneStep = 5 PaneShiftLimit = 30 PaneMinWidth = 16 PaneMinHeight = 3 )
The pane limits: PaneStep is the percent points one pane.grow or pane.shrink moves a divider; PaneShiftLimit bounds Layout.Shift either way; Divide keeps PaneMinWidth cells on each side of a side-by-side split and PaneMinHeight rows on each side of a stacked one, so neither panel collapses.
const ( SourceKey = "key" SourceDigit = "digit" SourceText = "text" SourceCount = "count" SourceLine = "line" SourceSteps = "steps" SourceOp = "op" SourceOpCount = "opcount" SourcePrefix = "prefix" SourceRow = "row" )
Sources a From entry may name: "key" (the key name), "digit" (the key as an integer), "text" (pasted or typed text), "count" (payload count, at least 1), "line" (payload count, 0 when absent, else the operator count), "steps" (count times operator count), "op" (payload operator), "opcount", "prefix" (the key sequence the pending mode holds), "row" (the row's Data, see FromRow) and "row:<field>" (one field of it). A From value may name several sources separated by spaces ("prefix key"): their texts are joined with a space, the way terminal.send reads a key list.
const ( Digit = "digit" Alpha = "alpha" Printable = "printable" Paste = "paste" Any = "any" )
Pattern names.
const ( FormNoun = "form" FormFieldNoun = "form-field" FormTextNoun = "form-text" FormChoiceNoun = "form-choice" FormOptionNoun = "form-option" // FormSuggestNoun is a free text field with suggestions: an input // whose enter (normal) and ctrl+space open the suggestions chooser. FormSuggestNoun = "form-suggest" // FormSuggestionsKind is the suggestions chooser's modal kind // (Runtime.Chooser(FormSuggestionsKind) while it is open). FormSuggestionsKind = "form-suggestions" )
Form nouns: the editor, its text fields (single- and multi-line), its choice fields, and the chooser's rows. ("form", not "record", so the palette's words do not collide with the macro verb record.)
const ( SettingString = "string" // string; Enum limits it SettingInteger = "integer" // int SettingNumber = "number" // float64 SettingBoolean = "boolean" // bool SettingDuration = "duration" // time.Duration, written as "400ms" SettingList = "list" // []string, written as a JSON array )
Setting types: the value a setting holds, as its getter returns it.
const ( // SettingsPageID is the Settings page's instance id. SettingsPageID = "__settings" // SettingsGeneral titles the section of the settings without one. SettingsGeneral = "General" )
The Settings page: settings.edit opens (or switches to) a framework page of the declared settings. Its sections are tabs across the top (the settings without a section first, under SettingsGeneral, then each section in the order its first setting was declared; tab, shift+tab, ] and [ step through them, wrapping). Below the tabs the shown section is one list of rows, a setting a row: its name on the left (a • after a name whose value is not the default), its value on the right (‹ value › for one h/l steps). A list setting's row reads its item count, and each item is a row beneath it with the name column blank. Under the list the selected setting's description says what its default is, where its value comes from (the default, settings.json, or the default because settings.json holds an invalid value) and what it takes; J/K scroll it.
Every change is saved as it is made; there is no save key. On a setting row enter edits (a boolean flips, an enum takes its next value, a list takes a new item, any other type opens a one-line prompt prefilled with the value), l/h and space step a boolean, an enum or a number, n adds an item to a list, r (or backspace, delete) resets to the default. On an item row enter or i edits the item, n adds one after it, d d deletes it, r resets the whole list. u (or ctrl+z) takes back the last change made on the page. q or esc (settings.close) goes back to the page the Settings page was opened from, with its remembered focus and mode; the page reopens on the section and row it was left on. A value another process sets (the poll) redraws the open lists.
settings.edit registers the page on first use and settings.close removes it again, so it is a tab only while it is open; an application that wants it as a permanent tab calls AddSettingsPage.
const ( TerminalLeaderSetting = "terminal-leader" DefaultTerminalLeader = "ctrl+a" )
The terminal leader setting: the key that enters leader_pending.
const ( TreeAdd = "add" TreeRename = "rename" TreeMove = "move" TreeDelete = "delete" )
Tree change operations.
const ( UINotice = "notice" UIClearNotice = "clear" UIStatus = "status" )
UI message kinds.
const ActionsFile = "actions.json"
ActionsFile is the user actions file in the config directory, beside bindings.json.
const CancelKey = "esc"
CancelKey is the key every key-sequence prefix answers with mode.leave: a default row "<prefix> esc" is kept in each table that binds a sequence, so Escape cancels a pending prefix without running anything and the resolver never names a key.
const ChooserPreviewMin = 60
ChooserPreviewMin is the width from which a chooser with a Preview draws it beside the rows.
const CompletionNoun = "completion"
CompletionNoun is the noun whose rows answer while suggestions are open.
const DefaultBindingTimeout = 1000 * time.Millisecond
DefaultBindingTimeout is how long a pending multi-key binding waits for its next key.
const DefaultCompletionDebounce = 150 * time.Millisecond
DefaultCompletionDebounce is the pause after the last edit before an input's search is asked.
const DefaultRecordDebounce = DefaultTreeDebounce
DefaultRecordDebounce is how long typing in a field pauses before the record is written.
const DefaultTreeDebounce = 400 * time.Millisecond
DefaultTreeDebounce is how long typing in an outline line pauses before the line is written.
const HistoryFetchLimit = 100
HistoryFetchLimit bounds the fetches the ring keeps apart from the user's actions and changes, so a host polling a state verb never pushes those out.
const HistoryFetchesSetting = "history-fetches"
HistoryFetchesSetting is the declared boolean setting that lets the history file keep fetches (entries of kind fetch the user did not type into the palette). Off by default: a host polling a state verb would fill the file and push the user's own entries out of it, and nothing reads a fetch back after a restart.
const HistoryFile = "history.jsonl"
HistoryFile is the action history file in the state directory.
const HistoryLimit = 500
HistoryLimit bounds the action history ring.
const HistorySetting = "history-limit"
HistorySetting is the declared setting that bounds the history file (and the ring while it is persisted): the last N entries are kept; 0 writes and reads no file.
const ImplicitGuard = "input"
ImplicitGuard is the guard the framework puts on every editor noun row that runs an input operation (input.cancel aside): such a row answers only while the focus is an input itself, not a non-input instance an application parented under one. It is the framework's, not the user's: it is not part of a row's identity, so a row without when replaces or unbinds the default it shadows, and a user row that runs an input operation on the editor noun gets it too, as the default it replaces had.
const JobLinger = 4 * time.Second
JobLinger is how long a finished job stays on the ticker after the frame that first saw it finished. The Model schedules one JobLingerMsg for the earliest remembered finish (Model.lingerCommand), so the row goes on an idle screen; any earlier frame past the deadline drops it too, and a newer job can push it off sooner.
const JobTickerRows = 2
JobTickerRows is the most entries the jobs ticker shows; they ride the rule line above the footer (Layout.TickerRule), so the ticker takes no row of its own.
const ListFilterMode = "list_filter"
ListFilterMode is the mode the filter line is typed in.
const MovementSection = "movement"
MovementSection is the help section that holds every motion, after the app's rows.
const PanesFile = "panes.json"
PanesFile is the remembered pane dividers in the state directory: an object of page id to Layout.Shift.
const ReferenceDir = "reference"
ReferenceDir is the directory config.export writes to by default, inside the config directory.
const SettingsPoll = time.Second
SettingsPoll is how often a Model checks settings.json for a change another process made (the CLI's settings set).
const ThemeSetting = "theme"
ThemeSetting is the declared setting that selects the colour scheme.
const ThemesFile = "themes.json"
ThemesFile is the user colour schemes file in the config directory.
const TreeRowNoun = "outline-row"
TreeRowNoun is the noun of a node that names none: enter toggles it.
Variables ¶
var BuiltinThemes = []string{"adaptive", "dark", "light", "mono"}
BuiltinThemes are the schemes every application has: adaptive follows the terminal's background, dark and light fix it, mono draws no colour.
Functions ¶
func BindingHints ¶
BindingHints renders the rows a focus answers to in its current mode as a hint line, from the innermost level outward (the focused instance's rows, its noun's, then its parents' up to the page and app): "enter demo.open · : palette.open · ? bindings.help". Motions (Operation.Motion) and hidden rows (counts, registers, macros, ctrl+c) are left to ? help, except a motion row with its own Hint (J reads "J/K detail"; a hint that starts with the row's key and a slash is shown alone), and of rows that run the same request only the first (innermost) key is shown. It is the data bindings.list prints, so a hint never names a key that is not bound; the descriptions are in BindingHelp (the ? modal).
func Call ¶
Call runs q in the application listening on the socket at path and returns its result (CallResponse keeps the messages too).
func ComposeModal ¶
ComposeModal centers a content-sized panel over the existing page, not a blank screen. Body and backdrop may contain trusted ANSI; title and footer are raw labels.
func InputView ¶
InputView renders an input's visible text without a cursor, for inputs that are not focused. See InputBlock.
func JobsTicker ¶
JobsTicker renders the ticker's entries: one message per job, "noun.verb state" ("noun.verb label state" when the job has a Label), with ": error" on a failure, each truncated to width (Layout.TickerRule joins them into the rule line).
func ModalSize ¶
ModalSize returns safe body bounds, reserving the same chrome as ComposeModal. Modal chrome uses one horizontal padding cell regardless of page density.
func PanelContentSize ¶
PanelContentSize returns the body cells available inside a Panel, excluding its border and horizontal padding. Tiny panels omit their chrome.
func ParseSchemes ¶ added in v0.2.0
ParseSchemes reads colour schemes in the themes.json shape, an object of schemes by name:
{"kombu": {"background": "dark", "accent": "#C9A227",
"error": {"light": "#B3261E", "dark": "#FF8A80"}}}
A role left out takes the built-in palette's. A scheme that does not validate (an unknown role, a bad colour or background, a built-in's name, an error colour equal to the accent or muted one) is skipped and reported; a file that is not a JSON object yields no schemes.
func RegisterInputOperations ¶
func RegisterInputOperations(r *Runtime)
func TableText ¶ added in v0.2.0
TableText lays a table out as plain text lines, the header line first, with the layout a list with columns draws (List.View) and no styling, gutter or highlight: a printer outside the TUI (the command line's --format table) reads the same column declarations. At width > 0 the columns that do not fit drop by Priority and cells cut with "…" at their width; at width <= 0 nothing drops or cuts, every column is as wide as its widest cell or title (Width and Min are ignored). A row with fewer cells than columns has empty ones; control characters in a cell become spaces; trailing spaces are trimmed. No columns is no lines.
Types ¶
type Action ¶ added in v0.2.0
type Action struct {
Noun string `json:"noun"`
Verb string `json:"verb"`
Description string `json:"description,omitempty"`
Command Argv `json:"command,omitempty"`
Base Argv `json:"base,omitempty"`
Call string `json:"call,omitempty"`
Target string `json:"target,omitempty"`
JSON bool `json:"json,omitempty"`
Label string `json:"label,omitempty"`
Confirm string `json:"confirm,omitempty"`
Parameters map[string]Parameter `json:"parameters,omitempty"`
Positional []string `json:"positional,omitempty"`
Dir string `json:"dir,omitempty"`
Timeout string `json:"timeout,omitempty"`
Quiet bool `json:"quiet,omitempty"`
History string `json:"history,omitempty"`
}
Action is one entry of actions.json: a verb on an existing noun that runs an external command. It becomes an application operation (noun.verb) like any other, so binding rows, the palette, the CLI, ? help and the catalog see it; its work runs off the loop as a job labelled Label, and the command's standard output is the job's result (JSON when it parses, a JSON value per line when every line does, else the text).
The command is either Command, an argv template run directly (never through a shell), or Base, the convention for a CLI with a JSON form: BASE NOUN VERB --json ARGS [--target TARGET], where NOUN VERB is Call ("noun verb", default this action's noun and verb), ARGS the action's arguments as one JSON object and TARGET the Target template when it is not empty. JSON appends --json ARGS to a Command too.
Templates ({{name}}) in Command, Base, Label, Dir and Target expand to: target or id (the instance the verb runs on), label (its label, else its id), noun and verb (the action's), data (the instance's Data: a string as is, else JSON), data.KEY (one field of Data as a JSON object), args (the arguments as JSON) or a declared parameter's value. An argv element that is exactly one placeholder and expands to nothing is left out, so an optional parameter disappears instead of passing "". Confirm is a confirm prompt template, as NounBuilder.Confirm takes. History is the kind of history entry it records (Operation.HistoryKind): "fetch" for a command that only reads; empty is a change, as for any application verb.
Actions are read only from the user's own actions.json (Config.Path): never from a catalog, a binding row, a socket call or an application's data, so nothing but the user's file decides what runs.
type Align ¶
type Align string
Align is a column's alignment: AlignLeft (the zero value) or AlignRight.
type AppHandler ¶
AppHandler is the signature of an application verb: it reads the Ctx and returns Done, Failed or Pending work. Pending work runs off the loop; its completion is delivered to the owning instance through the contract, so a handler never blocks key handling.
type Appearance ¶
type Appearance struct {
Theme string `json:"theme"`
Density string `json:"density"`
Dark bool `json:"dark"`
Accent color.Color `json:"-"`
// Schemes are the colour schemes beyond the built-in themes, by name:
// the user's themes.json (Model.Init and themes.reload set it) or an
// application's own (NewSchemeSet). A pointer keeps Appearance
// comparable.
Schemes *SchemeSet `json:"-"`
}
Appearance is event-loop-owned configuration. Operation results are value snapshots. Dark is the terminal background reported by tea.BackgroundColorMsg; the adaptive theme assumes a dark background until that message arrives.
Accent replaces the theme's accent colour when it is not nil: the title, panel and modal borders, the active tab, the badge and every highlight drawn in the accent take it, so an application can say "you are looking at everything" by colour alone (a pin state). Semantic colours (errors) and the muted text keep their meaning. The mono theme and NO_COLOR stay colourless. Applications set it in code; the appearance verbs leave it.
func NewAppearance ¶
func NewAppearance(r *Runtime) *Appearance
NewAppearance registers appearance operations once per runtime.
func (Appearance) Background ¶ added in v0.4.0
func (a Appearance) Background() (background string, plain bool)
Background is the background the appearance draws on, "light" or "dark" (an adaptive scheme follows Dark), and whether it draws no colour at all (the mono theme or NO_COLOR). A renderer with its own palette, such as the markdown package's Glamour styles, picks from it.
func (Appearance) ThemeNames ¶ added in v0.2.0
func (a Appearance) ThemeNames() []string
ThemeNames are the schemes Theme can name: the built-in themes, then the application's or user's (Schemes) by name.
type ArgumentError ¶ added in v0.1.1
type ArgumentError struct{ Err error }
ArgumentError is a request refused for its arguments (a missing required one, a wrong type, a value outside the enum or the source's choices) before any instance was chosen, so a caller never blames the target for it (the CLI adds no "pass --target" hint).
func (*ArgumentError) Error ¶ added in v0.1.1
func (e *ArgumentError) Error() string
func (*ArgumentError) Unwrap ¶ added in v0.1.1
func (e *ArgumentError) Unwrap() error
type Arguments ¶
Arguments are a request's named arguments, keyed by parameter name.
func ParseArguments ¶
ParseArguments parses the same JSON object used by the wire API.
type Argv ¶ added in v0.2.0
type Argv []string
Argv is a command line: a JSON array of words, or a string split on spaces (use the array for a word holding a space).
func (*Argv) UnmarshalJSON ¶ added in v0.2.0
UnmarshalJSON reads an array of strings or one string split on spaces.
type Binding ¶
type Binding struct {
Noun string `json:"noun,omitempty"`
Instance string `json:"instance,omitempty"`
Mode string `json:"mode,omitempty"`
Keys string `json:"keys,omitempty"`
Pattern string `json:"pattern,omitempty"`
Request Request `json:"request"`
From map[string]string `json:"from,omitempty"`
When string `json:"when,omitempty"`
Unbind bool `json:"unbind,omitempty"`
Replay bool `json:"replay,omitempty"`
Capture bool `json:"capture,omitempty"`
// Hint replaces "noun.verb: description" in the footer and the help
// for a row whose operation says nothing useful on its own (the
// terminal leader's mode.enter); bindings list carries it too.
Hint string `json:"hint,omitempty"`
// Hidden keeps the row off the footer's hint line (counts, registers,
// macros, ctrl+c); ? help and bindings list still show it.
Hidden bool `json:"hidden,omitempty"`
// Help replaces the operation's description in ? help and bindings
// list for a row whose operation is generic (mode.enter into a
// register, macro or count mode).
Help string `json:"help,omitempty"`
}
Binding is one row of a mode table, identical in code and config: {noun | instance, mode, keys | pattern, request | null, from, when}. Keys is an exact key or a space-separated sequence ("g g"); Pattern is a key class: digit, alpha, printable, paste, any, a class minus keys ("alpha-q"), or a set ("one-of:h j k l"). From fills request arguments from the key or the mode payload (see Sources). When names a registered guard. A row's identity is its table (noun or instance), mode, keys or pattern and guard: a row replaces only the row with the same identity, so a row with When and the unguarded row on the same keys coexist, and Unbind removes only the row with the same identity (an unbind row without When removes the unguarded row, never a guarded one). The editor noun's implicit "input" guard is not part of the identity (see withImplicitGuard). Replay dispatches the key again, fresh, after the row ran (a pending mode that hands an unknown key back to the stack). Capture rows are consulted outer-first (app first) before the inner-first walk (see resolve.go).
A row is atomic: a Request (one registered operation, its arguments from the row, the key or the payload), a mode transition (Enter, Leave) or an unbind. There is no row that runs Go code with the key. Composite behaviour is an operation whose handler calls other operations through Execute (macro.record, terminal.paste under the leader); a condition is a named guard. TestBindingRowsAreAtomic pins this for every table.
func Enter ¶
Enter builds a row that enters a pending mode with a typed payload: the operator fields (Op, Count, OpCount) and, for a leader, Prefix (the key sequence the mode holds, which arms the sequence timer) and Request (what the timer runs when no second key arrives).
func Leave ¶
func Leave() Binding
Leave builds a row that returns from a pending mode to the mode it shadowed.
func (Binding) Captured ¶
Captured marks a row as a capture row: consulted outer-first before the inner-first walk (config field "capture").
func (Binding) FromPayload ¶
FromPayload fills an argument from the mode payload (a Source name).
func (Binding) FromRow ¶ added in v0.3.0
FromRow fills an argument from the Data of the row the key acted on: the innermost instance carrying Data from the focus out to the level the row answered at (a list row's ListItem.Data, also when the row is bound on the list). field names a key of that value (a map's key, a struct's JSON field name; dots walk nested values, "repo.path"); "" passes the whole value. A struct is read through its JSON encoding, so the value is what the CLI would send (numbers float64, the whole row an object). A row without Data, or without the field, leaves the argument out. The source is "row:<field>" (or "row") in a binding file.
func (Binding) Hide ¶
Hide keeps the row off the footer (config field "hidden"); ? help and bindings list still show it.
type BindingTimeoutMsg ¶
type BindingTimeoutMsg struct {
// contains filtered or unexported fields
}
BindingTimeoutMsg resolves a pending key sequence on the owning event loop. Messages from an older sequence or another runtime are ignored.
type Block ¶
Block is the result of rendering. Text is trusted ANSI. Cursor is where the focused input's cursor sits inside Text, or nil when the block holds no focused input. Only the innermost focused component supplies a cursor; composers move it by where they placed the child and never invent one.
func ComposeModalBlock ¶
func ComposeModalBlock(background, title string, body Block, footer string, width, height int, styles Styles) Block
ComposeModalBlock is ComposeModal for a body that may carry a cursor. The result's cursor is the body's, moved to where the panel placed it; the backdrop never contributes one because a modal covers whatever it held.
func InputBlock ¶
InputBlock renders width x height cells of an input around its cursor and reports where the cursor sits, without changing text or editing state. Visual selections are painted in reverse video; the cursor itself is left to the terminal, so compose this block only for the focused input.
func (Block) Clip ¶
Clip drops a cursor that fell outside a width x height cell area whose top-left corner is the block's origin, as when a composer clipped the child.
type Choice ¶
Choice is one value a parameter accepts: ID is the argument value, Label what a pick list shows.
func ParseChoices ¶
ParseChoices reads a source operation's result: []string, []Choice, []PaletteInstance, []map with "id" and optional "label", or []any of strings or such maps (the JSON-decoded form).
type Chooser ¶ added in v0.2.0
type Chooser struct {
// contains filtered or unexported fields
}
Chooser is one open chooser, the Component of its modal instance.
func (*Chooser) HandleMessage ¶ added in v0.2.0
The delivery contract: a chooser runs no jobs of its own (Choose and Create return their own results). Pending work they return belongs to the focus the chooser opened over (runApplication), since the chooser and its input are closed before the callback runs.
func (*Chooser) Highlighted ¶ added in v0.2.0
func (c *Chooser) Highlighted() (ChooserRow, bool)
Highlighted is the row Enter takes: the moved-to row, else the top match; none means Enter creates.
func (*Chooser) Matches ¶ added in v0.2.0
func (c *Chooser) Matches() []ChooserRow
Matches are the rows the query keeps: matches first, then trailing rows, then the create row, then the fixed rows.
func (*Chooser) ModalBlock ¶ added in v0.2.0
func (*Chooser) ModalTitle ¶ added in v0.2.0
ModalTitle and ModalBlock make a chooser a self-drawing modal body (ModalBody), drawn like a record editor and its chooser.
func (*Chooser) Moved ¶ added in v0.2.0
Moved reports whether the user moved the highlight since the last edit.
func (*Chooser) PendingCommand ¶ added in v0.2.0
func (*Chooser) SetRows ¶ added in v0.2.0
func (c *Chooser) SetRows(rows []ChooserRow)
SetRows replaces the rows (a background load landing); the highlight stays on the same row id when the user had moved it.
func (*Chooser) View ¶ added in v0.2.0
View draws the search line, then the rows with the highlighted one in reverse video, with what Enter would create when nothing is highlighted after the matches (before the fixed rows); with a Preview and the width for it, the highlighted row's preview on the right. Its cursor is the search input's.
type ChooserRow ¶ added in v0.2.0
type ChooserRow struct {
ID string
Label string
Data any
Trailing bool
Fixed bool
// Cells, when set, draw the row as aligned columns (each column as
// wide as its widest cell among the rows); Label stays what the
// filter reads.
Cells []string
}
ChooserRow is one choice. Trailing rows (a "browse…" entry) follow the matches. Enter takes one without moving onto it only when the query is not empty and no ordinary row matches, so their filter should be strict (a substring of the label); an empty query with no ordinary rows creates. Fixed rows (a "no pin" entry) sit at the bottom whatever the query: the filter never sees them and Enter takes one only once the highlight is moved onto it, or when the query spells it.
type ChooserSpec ¶ added in v0.2.0
type ChooserSpec struct {
Kind string
Title string
Rows []ChooserRow
Filter func(query string, row ChooserRow) bool
Choose func(ChooserRow) Result
Create func(query string) Result
CreateLabel func(query string) string
CreateRow bool
Empty string
// Keep names the columns (indexes into ChooserRow.Cells) cut last when
// the cells do not fit (a directory chooser's path): the others narrow
// to their minimum first, then the kept ones, widest first.
Keep []int
// Preview, when set, draws the highlighted row's text beside the rows
// (wrapped, cut at the bottom) once the chooser is ChooserPreviewMin
// cells wide; narrower, the rows take the whole width.
Preview func(ChooserRow) string
}
ChooserSpec opens a chooser. Kind is the modal's kind (one open chooser per kind). Title is the modal's title. Filter defaults to a fuzzy match on Label; matches whose label holds the query whole come first, otherwise in Rows order. Create is optional; without it Enter on no match fails. CreateLabel names what Enter would create from the query. CreateRow shows that as a "+ <label>" row while the query is not empty, after the matches and trailing rows and before the fixed rows; typing never matches or ranks it, it is the default only when nothing else matches, and Enter on it creates. Empty is the line shown while there are no rows at all ("loading…"). Keep names the cell columns cut last. Preview draws a preview of the highlighted row beside the rows when there is room.
type Column ¶
type Column struct {
Title string `json:"title"`
Width int `json:"width,omitempty"`
Min int `json:"min,omitempty"`
Max int `json:"max,omitempty"`
Align Align `json:"align,omitempty"`
Priority int `json:"priority,omitempty"`
Wrap bool `json:"wrap,omitempty"`
}
Column is one column of a table. Width fixes the column's cells (0: a flexible column, as wide as its widest cell or title when there is room); Min is a flexible column's least width before columns drop (default: 10 cells or its title's width when wider, at most its widest cell or title). Priority orders dropping when the width is short: the column with the largest Priority drops first, ties the rightmost first; 0, the default, is the most important, and the last column left never drops (it is cut instead). Max caps a flexible column's growth (0: up to its widest cell). Wrap makes List.View wrap a cell longer than its column onto further lines of the row instead of cutting it: the row is as tall as its tallest wrapped cell, the other cells sit on its first line (TableText still cuts).
type Completer ¶ added in v0.5.0
type Completer struct {
// Debounce is the pause before a search is asked
// (DefaultCompletionDebounce when 0).
Debounce time.Duration
// contains filtered or unexported fields
}
Completer is the inline completion component: which input it follows, the token whose suggestions are wanted and the answer on screen.
func (*Completer) Close ¶ added in v0.5.0
func (c *Completer) Close()
Close hides the list and cancels its searches.
func (*Completer) DebounceCurrent ¶ added in v0.5.0
func (c *Completer) DebounceCurrent(msg CompletionDebounceMsg) bool
DebounceCurrent reports whether a pause timer is for the latest request, whose search has not started yet.
func (*Completer) DebounceTick ¶ added in v0.5.0
func (c *Completer) DebounceTick() (CompletionDebounceMsg, bool)
DebounceTick is the pause timer in flight, for a host that delivers it at once (tests, o-story): false when no search is waiting on one.
func (*Completer) HandleMessage ¶ added in v0.5.0
HandleMessage starts a search when its pause ends and takes a search's answer.
func (*Completer) Highlighted ¶ added in v0.5.0
Highlighted is the highlighted suggestion's index, -1 for none.
func (*Completer) Input ¶ added in v0.5.0
Input is the input the list belongs to, "" when none is followed.
func (*Completer) Open ¶ added in v0.5.0
Open reports whether the suggestion list is shown (its rows answer).
func (*Completer) PendingCommand ¶ added in v0.5.0
PendingCommand looks at the focused input and schedules the pause timer of a new request.
func (*Completer) Searching ¶ added in v0.5.0
Searching reports whether a search newer than the answer on screen runs.
func (*Completer) Suggestions ¶ added in v0.5.0
func (c *Completer) Suggestions() []Suggestion
Suggestions are the answer on screen.
func (*Completer) Token ¶ added in v0.5.0
func (c *Completer) Token() (CompletionToken, bool)
Token is the token whose suggestions are wanted, and whether there is one.
type Completion ¶
Completion is the message off-loop work sends back. It is delivered to the owning instance only while its ticket is current.
type CompletionDebounceMsg ¶ added in v0.5.0
type CompletionDebounceMsg struct {
Seq uint64
}
CompletionDebounceMsg is the pause timer of one request: when it is the latest (Completer.DebounceCurrent) the search is started.
type CompletionSearch ¶ added in v0.5.0
type CompletionSearch func(ctx context.Context, query string) ([]Suggestion, error)
CompletionSearch answers a query, the token after its trigger, with suggestions. It runs off the loop, as a job; its context is cancelled when the answer can no longer be shown (the suggestions were dismissed, or a newer answer is already on screen). An error is shown in the list.
func SearchStrings ¶ added in v0.5.0
func SearchStrings(search func(ctx context.Context, query string) ([]string, error)) CompletionSearch
SearchStrings adapts a search that answers plain strings, for the usual case where what the list shows is what is inserted.
type CompletionToken ¶ added in v0.5.0
type CompletionToken struct {
Start int `json:"start"`
End int `json:"end"`
Trigger string `json:"trigger"`
Query string `json:"query"`
}
CompletionToken is the trigger token under an input's cursor: the rune range [Start, End) it covers, its trigger and its query (the token after the trigger).
func FindCompletionToken ¶ added in v0.5.0
FindCompletionToken finds the token holding the cursor in text and the index of the trigger it starts with. A token is a run of non-whitespace; it counts only when it starts with a trigger (the longest one, when triggers overlap) and the cursor is past that trigger, at the token's end or anywhere inside it.
type CompletionTrigger ¶ added in v0.5.0
type CompletionTrigger struct {
Trigger string
Search CompletionSearch
}
CompletionTrigger is one trigger of an input: the characters that start a completion token and the search that answers its query.
type Component ¶
Component is the delivery contract every instance that works off the loop implements through Instance.Component. HandleMessage applies a result on the loop and reports whether the message was for this component; PendingCommand hands the Bubble Tea adapter the work scheduled since the last drain; Close cancels outstanding work and releases anything held. The picker and the registers component are the framework's own; an application adds its own by setting Instance.Component.
type Config ¶ added in v0.2.0
type Config struct {
App string
Dir string
// Report, when set, receives every problem as it is found: a bindings
// row that was skipped, a file that does not parse, an unknown or
// invalid setting. NewModel sets it to Model.Notify, so problems are
// persistent footer notices.
Report func(problem string)
// Withdraw, when set, takes back a problem Report sent once it no
// longer holds (bindings.reload of a fixed file); NewModel sets it to
// drop the notice.
Withdraw func(problem string)
// StateDir, when set, is the state directory (the history file);
// else $XDG_STATE_HOME/<App>, else ~/.local/state/<App>.
StateDir string
// NoHistoryFile keeps the action history in memory only: an
// application opts out of history.jsonl.
NoHistoryFile bool
// contains filtered or unexported fields
}
Config is the application's per-user configuration directory and what the framework loaded from it: the user bindings file (bindings.json, rows in the bindings.load shape that replace or unbind the defaults by noun, mode and keys) and the declared settings (settings.json). It is one instance under app, reached through Runtime.Config(), never a Runtime field.
The directory is Dir when set, else $XDG_CONFIG_HOME/<App>, else ~/.config/<App>. App defaults to the binary's name (a test binary, NAME.test, has none), so every application gets the files without code; an application whose directory is named otherwise sets App before the Model starts (mtm sets "matomeru"). With App and Dir both empty there is no directory: nothing is read or written.
func (*Config) ActionProblems ¶ added in v0.2.0
ActionProblems are the problems the last read of actions.json found.
func (*Config) BindingProblems ¶ added in v0.2.0
BindingProblems are the problems the last load of the user bindings found (rows skipped, a file that does not parse).
func (*Config) Close ¶ added in v0.2.0
func (c *Config) Close()
Close keeps everything: the config lives as long as the runtime.
func (*Config) Directory ¶ added in v0.2.0
Directory is the config directory, "" when there is none.
func (*Config) Disable ¶ added in v0.2.0
func (c *Config) Disable()
Disable gives the runtime no config directory (App and Dir empty): a sandbox such as an o-story session reads and writes no user files, and keeps no history file.
func (*Config) Flush ¶ added in v0.2.0
Flush stops the history writer once every line sent to it is written. The Model calls it on quit; later requests are not persisted.
func (*Config) FrameworkTheme ¶ added in v0.2.0
FrameworkTheme reports whether the theme setting is the framework's (the Model applies it to Appearance.Theme) rather than the application's own.
func (*Config) HandleMessage ¶ added in v0.2.0
HandleMessage: the config does no off-loop work.
func (*Config) HistoryPath ¶ added in v0.2.0
HistoryPath is the history file, "" when the history is not persisted (no state directory, or the application set NoHistoryFile).
func (*Config) PanesPath ¶ added in v0.4.0
PanesPath is the panes file, "" when dividers are not persisted (no state directory: Config.Disable, a test binary).
func (*Config) Path ¶ added in v0.2.0
Path is a file in the config directory, "" when there is none.
func (*Config) Paths ¶ added in v0.6.0
func (c *Config) Paths() ConfigPaths
Paths are the config, state and default reference directories.
func (*Config) PendingCommand ¶ added in v0.2.0
PendingCommand: nothing is ever scheduled.
func (*Config) Schemes ¶ added in v0.2.0
Schemes are the user's colour schemes from themes.json, by name, as the last read found them (EnsureConfigSettings, themes.reload).
func (*Config) StateDirectory ¶ added in v0.2.0
StateDirectory is the application's state directory, "" when there is none: StateDir when set, else $XDG_STATE_HOME/<App>, else ~/.local/state/<App>. Disable leaves none.
type ConfigExport ¶ added in v0.6.0
type ConfigExport struct {
Dir string `json:"dir"`
Files []string `json:"files"`
Config string `json:"config"`
State string `json:"state"`
}
ConfigExport is what config.export wrote: the directory, the files in it (absolute paths, in the order written) and where the live files are.
type ConfigPaths ¶ added in v0.6.0
type ConfigPaths struct {
Config string `json:"config"`
State string `json:"state"`
Reference string `json:"reference"`
}
ConfigPaths are where the application's user files live: Config is the config directory (bindings.json, settings.json, actions.json, themes.json), State the state directory (history.jsonl, panes.json) and Reference the directory config.export writes to by default. A directory the application has none of is "".
type Context ¶
Context is the derived view of a focus: the instance ids from app down to the focused instance (Path), and the focused input when there is one.
type Ctx ¶
Ctx is what an application handler receives: the runtime, the context the request runs in, its arguments and the instance it addresses (id, noun, payload).
func (Ctx) ClearNotice ¶ added in v0.4.0
ClearNotice takes back a notice Notify posted.
type Detail ¶ added in v0.2.0
type Detail struct {
// contains filtered or unexported fields
}
Detail is the component a detail instance fronts: a page's read-only detail region (the text beside or below a list about its selected row) that scrolls while the focus stays in the list. The application names the item the detail is about with the func it gives AddDetail (the selected row's id) and draws the text through Window; the framework keeps the offset. A new item starts at the top, checked on every Window and every scroll, so a scroll typed before the next frame lands on the new item; the same item keeps its offset while its text refreshes (clamped to the new length). J and K on the app noun (detail.scroll, counts work: 10J) scroll the current page's detail while it overflows and the focus is on the page outside it; a focused noun that binds J or K (the outline) keeps them, as inner rows answer first. A detail is not a focus stop.
func (*Detail) Marker ¶ added in v0.2.0
Marker is the position marker of the last Window: first and last visible lines and the total, "12–40 / 300", or "" when the text fits.
func (*Detail) Overflows ¶ added in v0.2.0
Overflows reports whether the last Window had more lines than it showed.
func (*Detail) Scroll ¶ added in v0.2.0
Scroll moves the window by lines (down when positive), clamped to the text the last Window measured, and returns the new offset. A new item starts at the top first.
type EditNode ¶
type EditNode struct {
Text string `json:"text"`
Cursor int `json:"cursor"`
Parent int `json:"parent"`
Children []int `json:"children"`
}
EditNode is one state in an input's undo tree: its text, cursor, parent and children.
type FocusTargeter ¶
type FocusTargeter interface {
FocusTarget() string
}
FocusTargeter is a component that knows where focus lands inside it: a list on its selected row, a grid on its cursor cell.
type Footer ¶
type Footer struct {
}
Footer is the bottom row of the page chrome: a raw label, styled as an error when Error is set. Jobs are the jobs ticker's entries (Model.JobsTicker), drawn in the rule line above the footer (TickerRule); the body keeps its size, and no jobs means the plain rule.
type Guard ¶
Guard is a named condition a row requires. The built-in guards are "input" and "no-input" (the focus is or is not an input), "multiline", "count" and "no-count" (the pending count is present or absent), "self" (the focus is the instance whose level the row sits on, not a descendant), "shadow-idle" (the mode a shadow mode such as macro_recording re-dispatches in is normal with an empty payload) and "op:<key>" (the pending operator). Applications add their own with DefineGuard.
type Header ¶
Header is the top of the page chrome: the title row with an optional right-aligned badge (the shell shows the mode there) and the subtitle row, which is a label or, when Tabs is set, the page tabs with Active marked. Every field is a raw label.
type HelpRow ¶
type HelpRow struct {
Key string `json:"key"`
Operation string `json:"operation"`
Args Arguments `json:"args,omitempty"`
Description string `json:"description,omitempty"`
Noun string `json:"noun"`
Section string `json:"section,omitempty"`
}
HelpRow is one binding as the help shows it: the key, the operation it runs (noun.verb, or the row's Hint when it has one), arguments resolved when help opens, its description, the answering noun, and the help's section: that noun, or "movement" for a motion (Operation.Motion).
func BindingHelp ¶
BindingHelp lists the rows a focus answers to in its current mode with their descriptions, grouped by the noun of the level that answers, from the innermost instance outward (the focused instance's rows, its noun's, its parents' up to the page, then app; a capture row sits with its own level, so app's ctrl+c comes after the focused row's verbs), and the motions of every level last, under "movement".
type HistoryContext ¶
type HistoryContext struct {
Focus string `json:"focus"`
Page string `json:"page,omitempty"`
Mode string `json:"mode"`
Source string `json:"source"`
}
HistoryContext is the interaction state a request ran in. Source is "key:<keys>", "macro:<register>", "palette", "cli" or "api".
type HistoryEntry ¶
type HistoryEntry struct {
Seq uint64 `json:"seq"`
At time.Time `json:"at"`
Kind string `json:"kind,omitempty"`
Request Request `json:"request"`
Context HistoryContext `json:"context"`
Result HistoryResult `json:"result"`
Moved *HistoryMove `json:"moved,omitempty"`
Job uint64 `json:"job,omitempty"`
// Depth is how many requests enclose this one: a request an operation
// runs while it runs (a choices source, a macro's keys) is one deeper.
Depth int `json:"depth,omitempty"`
// Restored marks an entry read from the history file at start
// (EnsureHistory): an earlier session ran it. Dot-repeat skips it.
Restored bool `json:"restored,omitempty"`
}
HistoryEntry is one user action: what ran, where, from which source, how it ended and, when it moved the interaction, from where to where (Moved). It holds ids and the request, never the data the operation returned, so an entry costs the same over a list of ten rows or ten thousand. Kind is the operation's HistoryKind. Job is the job id an application verb launched.
type HistoryMove ¶ added in v0.7.0
type HistoryMove struct {
From HistoryPlace `json:"from"`
To HistoryPlace `json:"to"`
}
HistoryMove is how a request moved the interaction: j on a list moves the focus from row A to row B, page.next from one page to the next, a modal's open into the modal and its close back out.
type HistoryPlace ¶ added in v0.7.0
type HistoryPlace struct {
Focus string `json:"focus"`
Page string `json:"page,omitempty"`
Mode string `json:"mode"`
}
HistoryPlace is where the interaction stands: the focused instance (a list's focus is its selected row), the page and the mode.
type HistoryResult ¶
HistoryResult is the outcome: ok, or the error. The value the operation returned is the caller's (the CLI prints it), not the history's; a reference to it (a hash into a content-addressed store) would go here, beside ok.
type Input ¶
type Input struct {
ID string
Text []rune
Cursor int
Mode string // the editing mode: normal, insert or a visual mode; pending modes live on the instance
Multiline bool
Kind string
PathFilter string
// Completions are the input's completion triggers (Completions, the
// AddInput option); none falls back to its noun's.
Completions []CompletionTrigger
Anchor int
History []EditNode
Head int
// contains filtered or unexported fields
}
Input is a single- or multi-line modal text field with an undo tree.
func (*Input) Count ¶
Count is the pending Vim count, read from the global mode payload while the input is focused.
func (*Input) Pending ¶
Pending describes the pending editor mode the way the old grammar did: "d" for an operator, "g" for a g prefix, "dg" for both, "register" while a register name is awaited, "" otherwise.
type Instance ¶
type Instance struct {
ID string `json:"id"`
Noun string `json:"noun"`
Parent string `json:"parent,omitempty"`
Payload Payload `json:"payload"`
Bindings []Binding `json:"bindings,omitempty"`
Unfocusable bool `json:"unfocusable,omitempty"`
Label string `json:"label,omitempty"` // a display name (a list row's label, a header name); {{label}} in a confirm prompt
Data any `json:"data,omitempty"` // an opaque application value (a list row's ListItem.Data)
Component any `json:"-"`
// contains filtered or unexported fields
}
Instance is one addressable thing on screen: a page, a list, a list row, a modal body, or an input. Parent links form the focus stack; walking them from the focused instance outward is the path Context.Path spells out. An instance holds no mode: the mode is global (Runtime.Mode). Payload is the data a modal body carries (a confirm's prompt and request). Bindings are this instance's own rows, resolved above its noun's table at the same stack level. Component holds the typed component the instance fronts. Unfocusable opts the instance out of being a focus stop although its noun is Focusable (a disabled panel). Label is an optional display name a confirm prompt reads as {{label}}. Data is an opaque application value (a list row's ListItem.Data); the framework never reads it.
type InstanceOption ¶
type InstanceOption func(*instanceSpec)
InstanceOption configures the instance constructors: Instance, AddPage, AddList, AddInput, AddTerminal and RegisterPage.
func CloseOnDetach ¶
func CloseOnDetach() InstanceOption
CloseOnDetach makes terminal.detach remove the terminal instance after returning focus, so the stream is released (see TerminalReleaser) instead of kept for a later attach. Only AddTerminal reads it.
func Columns ¶
func Columns(cols ...Column) InstanceOption
Columns makes AddList's list a table with these columns (List.SetColumns changes them later). A list without columns draws its labels.
func Completions ¶ added in v0.5.0
func Completions(triggers ...CompletionTrigger) InstanceOption
Completions gives an input its completion triggers (AddInput reads it). They replace the triggers its noun declares (NounBuilder.Completions).
func Focus ¶
func Focus(id string) InstanceOption
Focus names the instance a page starts focused on (default: the page itself). Other constructors ignore it.
func FocusOnClose ¶
func FocusOnClose(id string) InstanceOption
FocusOnClose names the instance the focus moves to when this instance is removed while the focus is on it or inside it: a CloseOnDetach detach, Pop of a modal body, a list row dropped by SetItems, RemoveInstance. A target that is gone (or removed with it) falls back to the default (the parent, or the return Pop restores). Every constructor reads it.
func Kind ¶
func Kind(noun string) InstanceOption
Kind names the noun the instance answers to (default: the instance id for plain instances, "editor" for inputs, "list" for lists, "page" for pages, "terminal" for terminals).
func NoMarks ¶ added in v0.2.0
func NoMarks() InstanceOption
NoMarks makes a list (or a tree's list) a read-only view: its rows take no marks, so space does not answer with list.mark there (the verb's guard, list-marks, is false; the footer and ? help leave it out) and list.mark refuses. list.apply still runs on the selected row.
func NoSpill ¶
func NoSpill() InstanceOption
NoSpill makes a list trap its motions: list.move past its last (first) row stays on that row instead of moving the focus to the next (previous) stop on the page. For a list that must keep the focus, such as a picker.
func Parent ¶
func Parent(id string) InstanceOption
Parent places the instance under another instance (default app).
type JobInfo ¶
type JobInfo struct {
Job uint64 `json:"job"`
Owner string `json:"owner"`
Verb string `json:"verb"`
Label string `json:"label,omitempty"`
Slot string `json:"slot,omitempty"`
Scope string `json:"scope,omitempty"`
Started time.Time `json:"started"`
State string `json:"state"`
Error string `json:"error,omitempty"`
}
JobInfo is one row of the jobs list: what jobs.list returns and what the snapshot's /jobs holds for running jobs.
type JobLingerMsg ¶
JobLingerMsg is the ticker's one-shot timer: it fires when the oldest remembered finished job passes JobLinger, so the frame it causes drops the row with no key pressed. At is the deadline it was scheduled for; only the message for the timer in flight clears it.
type KeyEvent ¶
type KeyEvent struct {
Key MacroKey
Mode ModeState
Focus string
Level string // the instance whose level is answering, "" for a noun-only level
}
KeyEvent is what a row receives: the key, the mode it was resolved in and the focused instance.
type Layout ¶
type Layout struct {
Width, Height int
Styles Styles
// Shift moves the divider of every split this layout draws, in percent
// points of the split's length: positive grows the first (left or top)
// panel, negative the second, 0 is the split's default. It is the
// page's remembered divider (Runtime.PaneLayout sets it; pane.grow,
// pane.shrink and pane.reset change it). Divide applies it.
Shift int
}
Layout renders page chrome, bounded panels and panel pairs for a viewport. It is a plain value: every method only renders and keeps no state.
Example ¶
layout := Layout{
Width: 80, Height: 24,
Styles: NewStyles(Appearance{Theme: "adaptive"}),
}
body := layout.Split("Files", "main.go\nlayout.go", "Preview", "Selected file contents")
page := layout.Page("Workspace", "Browse files", body, "Enter open · Esc back")
fmt.Print(page)
func (Layout) BodySize ¶
BodySize returns the exact cells available to Page's body. Viewports that cannot hold any body report 0, 0. Small viewports drop the header and keep only a footer row.
func (Layout) BodySizeWith ¶
BodySizeWith is the body's size with the footer f: BodySize, since the jobs ticker rides the rule line above the footer and takes no body row, so a job starting or lingering out never moves or hides the body (UX review 2 F13).
func (Layout) Divide ¶ added in v0.4.0
Divide is where a split of total cells puts its divider: first is the split's default size of its first (left or top) panel, moved by Shift percent points of total and clamped so each panel keeps least cells. A split with no shift, or too small for two panels of least cells, keeps first. A layout of its own (a page body split by hand) calls it with its default; Split and its kin call it for theirs.
func (Layout) Page ¶
Page renders title, subtitle, body and footer into exactly Width x Height cells. Body is trusted ANSI; title, subtitle and footer are raw labels. Overlong bodies are clipped; use Panel for a visible overflow marker.
func (Layout) PageBlock ¶
PageBlock is Page for a body that may carry a cursor; the cursor is moved by the page chrome around the body.
func (Layout) Panel ¶
Panel renders a rounded, titled box of exactly width x height outer cells. Focused panels use the heavy accent border. Body is trusted ANSI; title is a raw label. Content that does not fit is clipped and marked with "…" (columns) or a "… N more" last row (lines). Below 3x3 cells the border is dropped.
func (Layout) PanelBlock ¶
PanelBlock is Panel for a body that may carry a cursor; the cursor is moved inside the border and padding.
func (Layout) Shell ¶
Shell is the one page chrome: title row, subtitle row, a rule, the body, a rule, the footer and a bottom margin, inside a gutter, into exactly Width x Height cells. Viewports too small for the chrome keep the body and, from three rows up, the footer. The shell and PageBlock both render through it, so a page and the application around it reserve the same rows. The body's cursor is moved by the chrome around it.
func (Layout) Sidebar ¶
func (l Layout) Sidebar(title string, items []string, selected int, mainTitle, mainBody string) string
Sidebar renders a 28-cell navigation rail beside the main panel. Below 72 columns it stacks above the main panel. Items are raw labels; mainBody is trusted ANSI. Selection is zero-based and clamped for rendering. The caller owns selection and key handling; this method keeps the selected item visible.
Example ¶
layout := Layout{Width: 80, Height: 24, Styles: NewStyles(Appearance{Theme: "adaptive"})}
body := layout.Sidebar("Workspace", []string{"Files", "Search", "Settings"}, 1, "Search", "Search results")
fmt.Print(layout.Page("Project", "Workspace navigation", body, "↑↓ select · Enter open"))
func (Layout) SidebarBlock ¶
func (l Layout) SidebarBlock(title string, items []string, selected int, mainTitle string, mainBody Block) Block
SidebarBlock is Sidebar for a main body that may carry a cursor.
func (Layout) Split ¶
Split renders two panels filling BodySize: side by side (left ~40%) when the viewport is at least 72 cells wide, otherwise stacked (top ~40%), the divider moved by Shift (Divide). The left or top panel is the focused one; SplitFocusBlock takes which.
func (Layout) SplitBlock ¶
func (l Layout) SplitBlock(leftTitle string, leftBody Block, rightTitle string, rightBody Block) Block
SplitBlock is Split for bodies that may carry a cursor. One body should carry it; when both do, the left or top panel wins.
func (Layout) SplitFocusBlock ¶ added in v0.2.0
func (l Layout) SplitFocusBlock(focused SplitSide, leftTitle string, leftBody Block, rightTitle string, rightBody Block) Block
SplitFocusBlock is SplitBlock with the focused panel named: the one holding the focus draws in the focused style (accent title and border), the other plain, so a view whose focus moves between its panes (o-json's tree and detail) shows where it is. When both bodies carry a cursor, the focused panel's wins.
func (Layout) TickerRule ¶ added in v0.2.0
TickerRule is the rule line above the footer, width cells: the plain rule with no jobs; with jobs, "── " then the ticker entries (Footer.Jobs, at most JobTickerRows) joined by " · ", cut with "…" so at least " ─" of rule is left, and the rest of the row filled with rule characters, all muted, so the chrome still reads as a rule.
type Lines ¶
type Lines []any
Lines is a result printed as JSON Lines (one compact value per line, no outer array) by a CLI, so a reader can decode it as it arrives; over JSON it is an array. HandleCall keeps the type through its copy.
type List ¶
type List struct {
// contains filtered or unexported fields
}
List owns flat selection, marks and scrolling on the runtime's event loop. Focus sits on the selected row when there is one, else on the list.
func (*List) ColumnOffset ¶ added in v0.9.0
ColumnOffset is the table's column offset: 0 unscrolled, else the first column shown after the frozen first one.
func (*List) Filter ¶ added in v0.8.0
Filter is the list's filter query ("" when every row is shown).
func (*List) Filtering ¶ added in v0.8.0
Filtering reports whether the filter line shows: a filter is set, or its query is being typed on this list.
func (*List) FocusTarget ¶
FocusTarget is where a focus jump to the list lands: its selected row.
func (*List) Focused ¶
Focused derives focus from the active frame instead of retaining a stale flag.
func (*List) Height ¶ added in v0.8.0
Height is the lines the list needs to draw every row without windowing (a table's header aside): Len, plus the filter line while it shows. A host that sizes a list to its rows sizes it with Height, so opening the filter line neither windows the rows nor moves what is drawn below the list as the filter narrows it.
func (*List) Items ¶
Items returns a copy of every row in display order, the ones a filter hides included.
func (*List) Len ¶
Len is the number of rows, the ones a filter hides included (Shown counts the rest).
func (*List) Marked ¶
Marked lists the marked rows in list order, the ones a filter hides included (a mark survives the filter).
func (*List) Patch ¶ added in v0.8.0
Patch applies a record-level change (ListPatch) without the caller rebuilding the rows: it is SetItems over the patched rows, so a row that stays keeps its instance (and the bindings and pending jobs on it), the selection and the marks follow their ids, and only a removed row's instance is closed. An empty patch does nothing; an invalid one (an index out of order or out of range, a repeated id) leaves the list unchanged. The patch applies to every row, the ones a filter hides included, and SetItems filters the result again.
func (*List) Select ¶
Select changes the selected row by stable ID without taking focus. A row the filter hides is shown by clearing the filter.
func (*List) SetColumns ¶
SetColumns replaces the list's columns; none makes it a plain list again.
func (*List) SetFilter ¶ added in v0.8.0
SetFilter sets the filter query and shows the rows that match it; "" shows every row. The selection stays on its row when that row still shows, else it moves to the first match (none when nothing matches); the focus follows it.
func (*List) SetItems ¶
SetItems copies rows, preserves selection by ID, and falls back to the nearest remaining index if that ID disappears. Invalid updates leave the list unchanged. A filter (SetFilter) stays and applies to the new rows. It creates one instance per new row under the list and removes the instances of rows that disappear; a retained row keeps its instance and any bindings the application put on it. Rows whose cells are unchanged keep a table's measured widths. A record-level change is Patch.
func (*List) Shown ¶ added in v0.8.0
Shown is the number of rows the filter lets through (Len without one).
func (*List) Snapshot ¶
Snapshot is the list's state with a copy of its rows (the snapshot's /lists entry); changing it never reaches the list.
func (*List) ToggleMark ¶
ToggleMark marks or unmarks a row for fan-out verbs; a list added with NoMarks refuses.
func (*List) View ¶
View fits the viewport and updates its scroll offset to keep selection visible; a list with columns draws as a table (tableView). Calling it places the list in its page's drawing order (Placed), even at zero height, and reports its selected row's line (PlacedAt) so the page scrolls to keep that row on screen.
type ListItem ¶
type ListItem struct {
ID string `json:"id"`
Label string `json:"label"`
Noun string `json:"noun"`
Data any `json:"data,omitempty"`
Cells []string `json:"cells,omitempty"`
Section string `json:"section,omitempty"`
}
ListItem is application-owned identity, display text, and the registered noun the row answers to. Each row is an Instance whose ID is the item ID and whose Parent is the list; its bindings and actions come from its noun. Data is an opaque value the application keeps on the row (a host's record of the row, an extension's own id); SetItems copies it to the row instance's Data, where a verb reads it as Ctx.Instance.Data. The framework never reads it. Cells are the row's text per column when the list has columns (a table, Columns); Label stays the row's name for the palette, search and {{label}}, and is the first cell of a row without cells. Section groups a table's rows: List.View draws the section as a label line above the first row of each run of rows with the same Section (a list without columns ignores it).
type ListPatch ¶ added in v0.8.0
ListPatch is a record-level change to a list's rows: the rows that changed or were added, whole (Upsert), and the ids of the rows that went away (Remove). Every other row stays as it is, in its order.
At, when given, is each upserted row's index in the patched list, one per Upsert and ascending: the rows neither upserted nor removed keep their relative order and fill the indexes the upserts leave free. Without At a row whose id the list has replaces it in place and a new row is appended, in Upsert order.
type MacroState ¶
type MacroState struct {
Recording string `json:"recording,omitempty"`
Last string `json:"last,omitempty"`
Keys []MacroKey `json:"keys,omitempty"`
Depth int `json:"depth"`
Steps int `json:"steps"`
}
MacroState is the application-wide recording and replay state. Awaiting a register name is the macro_pending or replay_pending mode of the focused instance, not a field here.
type ModalBody ¶ added in v0.2.0
ModalBody is a modal body component that draws itself: a modal whose instance's Component implements it needs no ModalView (a record editor opened as a modal, its chooser, a Chooser). A ModalView for the id still wins.
type ModalOption ¶
type ModalOption func(*modalSpec)
ModalOption configures OpenModal.
func WithInput ¶
func WithInput(in *Input, opts ...InstanceOption) ModalOption
WithInput places an input inside the modal body and focuses it, so a one-field prompt is one call. The input is registered under the body (a Kind option names its noun; Parent is ignored) and is removed with the body on Pop; the *Input keeps its text and undo history and may be passed again to the next OpenModal.
type ModalView ¶
ModalView renders one modal without replacing or inspecting its parent page. Render receives the modal instance (its Payload carries what OpenModal gave it) and returns the body as a Block; its cursor, when the modal holds the focused input, is relative to the body's top-left cell.
type ModeBuilder ¶
type ModeBuilder struct {
*NounBuilder
// contains filtered or unexported fields
}
ModeBuilder binds rows into one mode table of a noun.
func (*ModeBuilder) Bind ¶
func (m *ModeBuilder) Bind(keys string, row Binding) *ModeBuilder
Bind adds an exact-key (or key-sequence) row, replacing the row with the same keys and guard (Binding.Guard, or When after Bind).
func (*ModeBuilder) Extends ¶
func (m *ModeBuilder) Extends(parent string) *ModeBuilder
Extends makes the selected mode's table read parent's rows after its own, as the editor spec's "extends" does: three motion tables become one table and two that extend it. A mode extends one parent; Extends("") removes the link.
func (*ModeBuilder) Pattern ¶
func (m *ModeBuilder) Pattern(pattern string, row Binding) *ModeBuilder
Pattern adds a key-class row.
func (*ModeBuilder) Unbind ¶
func (m *ModeBuilder) Unbind(keysOrPattern string) *ModeBuilder
Unbind removes the unguarded row with these keys or this pattern; a guarded row on them stays (UnbindGuarded removes that one).
func (*ModeBuilder) UnbindGuarded ¶ added in v0.6.0
func (m *ModeBuilder) UnbindGuarded(keysOrPattern, guard string) *ModeBuilder
UnbindGuarded removes the row with these keys or this pattern and this guard ("" is the unguarded row).
func (*ModeBuilder) When ¶
func (m *ModeBuilder) When(guard string) *ModeBuilder
When guards the last bound row with a registered guard name. The guard is part of the row's identity, so the row is placed again under it: a row it replaced as an unguarded row comes back, and it replaces the row with the same keys and this guard instead.
type ModeObserver ¶
type ModeObserver interface {
ModeChanged(from, to string)
}
ModeObserver is implemented by a component that follows the base mode while the focus sits on it or beneath it: the grid starts and ends its selection when a visual shape is entered or left.
type Model ¶
type Model struct {
Runtime *Runtime
Palette *Palette
Appearance *Appearance
ModalViews map[string]ModalView
Title string
Width int
Height int
Status string
// Notices are persistent lines (a host's mount warnings), kept across
// keys and errors until notice.clear (or the application) clears them.
// The footer shows the newest before the hints, cut to half the width,
// with "(+N more)" for the rest (notice.list has them all), so notices
// never hide the hints. Status is the last key's error (or what a
// handler set with ctx.Status) and goes with the next key; a notice
// does not. The Model is the runtime's UI sink (Runtime.UI), so
// ctx.Notify and ctx.Status land here.
Notices []string
// Sidebar replaces page tabs with a navigation rail. Existing page operations
// remain the only navigation state; input focus and modal routing are unchanged.
Sidebar bool
// Now is the Model's clock: the ticker's memory of finished jobs and
// the linger timer read it (time.Now by default, time.Now when nil). A
// headless host fakes it, advances it to JobLingerTick's deadline and
// delivers that message instead of waiting JobLinger.
Now func() time.Time
// contains filtered or unexported fields
}
Model is the Bubble Tea adapter. Pages and modal instances retain their state in Runtime; components (picker, registers, application components) are instances the runtime drives through the delivery contract, so the adapter holds no component list of its own.
func (*Model) Init ¶
Init installs the user actions file (Runtime.EnsureUserActions) and applies the user bindings file (Runtime.EnsureUserBindings), after the application defined its own nouns and rows, declares the framework's settings (EnsureConfigSettings), reads settings.json (its problems are notices), draws themes.json's schemes and the theme setting's (applyThemeSetting), restores and persists the action history (EnsureHistory), starts the settings.json poll (SettingsPoll) when the application declared settings, and asks for the background colour.
func (*Model) JobLingerTick ¶
func (m *Model) JobLingerTick() (JobLingerMsg, bool)
JobLingerTick is the linger timer in flight, the message its tea.Tick will deliver at its deadline (At), and false when none is scheduled. A host with a fake Now advances the clock to At and delivers the message itself rather than waiting JobLinger.
func (*Model) JobsTicker ¶
JobsTicker is the ticker the shell draws in the rule line above the footer for the current frame, as plain entries at most width cells each: none when no job shows.
func (*Model) Notify ¶
Notify adds a persistent notice to the footer (Notices) through the runtime's UI, as ctx.Notify does, and returns its id; notice.clear removes them.
func (*Model) View ¶
View renders the shell as a full-screen tea.View; View().Content is the string. The terminal cursor follows the focused input through the page or modal that holds it: a bar in insert mode, a block in normal mode and an underline in visual modes. It is hidden when no input is focused.
type NoticeID ¶ added in v0.4.0
type NoticeID uint64
NoticeID names one notice so the code that posted it can clear it. The UI assigns it, whatever sink shows the notice (or none), so a handler can always clear what it posted.
type Noun ¶
type Noun struct {
Name string `json:"name"`
Verbs []string `json:"verbs,omitempty"`
Pin string `json:"pin,omitempty"`
Focusable bool `json:"focusable,omitempty"`
Region bool `json:"region,omitempty"`
Bindings map[string][]Binding `json:"bindings"`
Extends map[string]string `json:"extends,omitempty"`
Guards map[string]string `json:"guards,omitempty"`
Actions map[string]Handler `json:"-"`
// Columns are the table columns a list of the noun's rows draws
// (NounBuilder.Columns, the catalog's columns): declared data a host
// passes to Columns when it builds the list, never applied on its own.
Columns []Column `json:"columns,omitempty"`
// Completions are the completion triggers of the noun's inputs that
// declare none of their own (NounBuilder.Completions).
Completions []CompletionTrigger `json:"-"`
}
Noun is the behaviour shared by every instance of one kind: the verbs it answers to, its key bindings per mode, the action handlers that override an operation's default while the noun is on the focus stack, and an optional pinned mode (the prompt noun pins insert). Focusable marks every instance of the noun as a focus stop (focus.next and the mode rule read it); Region marks a grouping that focus.next {scope: "region"} jumps between.
Bindings is keyed by mode name. "" holds rows that apply in every base mode; a pending mode (operator_pending, a key-sequence prefix, ...) is exclusive and reads only its own table.
type NounBuilder ¶
type NounBuilder struct {
// contains filtered or unexported fields
}
NounBuilder is the declaration surface of one noun.
func (*NounBuilder) Action ¶
func (b *NounBuilder) Action(key string, h Handler) *NounBuilder
Action overrides any operation ("noun.verb") while this noun is on the stack.
func (*NounBuilder) Columns ¶
func (b *NounBuilder) Columns(cols ...Column) *NounBuilder
Columns declares the table columns a list of the noun's rows draws, in order, each row's ListItem.Cells the same order (Noun.Columns). The catalog carries them, so a host mounting the noun's rows draws a table; an application passes r.Noun(noun).Columns to the Columns list option.
func (*NounBuilder) Completions ¶ added in v0.5.0
func (b *NounBuilder) Completions(triggers ...CompletionTrigger) *NounBuilder
Completions declares the completion triggers of every input of the noun that has none of its own (Input.Completions).
func (*NounBuilder) Confirm ¶
func (b *NounBuilder) Confirm(prompt string) *NounBuilder
Confirm asks before the last declared verb runs: the prompt template ({{id}}, {{noun}}, {{<arg>}}) opens a confirm modal whose y runs the stored request and n or esc pops it. An empty prompt removes the confirm.
func (*NounBuilder) Fetch ¶ added in v0.7.0
func (b *NounBuilder) Fetch() *NounBuilder
Fetch marks the last declared verb as a data request (Operation.HistoryKind HistoryFetch): a state, list or show verb. Its calls are history entries of kind fetch, which history.list leaves out by default and the ring bounds apart from the user's actions and changes.
func (*NounBuilder) Focusable ¶
func (b *NounBuilder) Focusable() *NounBuilder
Focusable makes every instance of the noun a focus stop.
func (*NounBuilder) Mode ¶
func (b *NounBuilder) Mode(mode string) *ModeBuilder
Mode selects the table rows are bound into; "" is the any-mode table.
func (*NounBuilder) Motion ¶
func (b *NounBuilder) Motion() *NounBuilder
Motion marks the last declared verb as a motion (Operation.Motion): the footer leaves its rows to ? help, as it does for list.move.
func (*NounBuilder) Noun ¶
func (b *NounBuilder) Noun() *Noun
func (*NounBuilder) PersistArgs ¶ added in v0.2.0
func (b *NounBuilder) PersistArgs() *NounBuilder
PersistArgs marks the last declared verb's text-like arguments as safe to keep in the history file (Operation.PersistArgs).
func (*NounBuilder) Pin ¶
func (b *NounBuilder) Pin(mode string) *NounBuilder
Pin keeps every instance of the noun in one base mode.
func (*NounBuilder) Positional ¶
func (b *NounBuilder) Positional(names ...string) *NounBuilder
Positional names the parameters of the last declared verb that bare words fill first, in order (Operation.Positional): Positional("name") makes BIN project link foo set name even though the boolean all sorts first. The CLI gives a boolean a bare word only when it is named here.
func (*NounBuilder) Quiet ¶
func (b *NounBuilder) Quiet() *NounBuilder
Quiet marks the last declared verb as bookkeeping (Operation.Quiet): its jobs stay off the jobs ticker. The framework names no quiet verb.
func (*NounBuilder) Region ¶
func (b *NounBuilder) Region() *NounBuilder
Region makes every instance of the noun a focus region: a grouping (a panel) that focus.next {scope: "region"} jumps between, never a stop.
func (*NounBuilder) Rows ¶
func (b *NounBuilder) Rows(noun string) *NounBuilder
Rows declares that the last declared verb's result lists rows of noun (Operation.Rows): a host reading the catalog knows which noun a list verb's rows answer to. An empty noun removes the declaration.
func (*NounBuilder) State ¶
func (b *NounBuilder) State() *NounBuilder
State marks the last declared verb as the runtime's state source (Operation.State): one call answers every list's rows as JSON Lines, each line tagged with the list noun (see cli.CatalogDoc). A host reading the catalog's state runs it once instead of one row source per list. The framework names no state verb.
func (*NounBuilder) Verb ¶
func (b *NounBuilder) Verb(verb string, h any, description ...string) *NounBuilder
Verb registers noun.verb as an operation when it is new, else installs the handler as this noun's override of the existing operation. The handler is a Handler (an interaction verb, run on the loop) or an AppHandler (func(Ctx) Result: an application verb whose pending work runs off the loop). An override of an existing operation must be a Handler.
func (*NounBuilder) Verbs ¶
func (b *NounBuilder) Verbs(verbs ...string) *NounBuilder
Verbs records the verbs the noun answers to, for help and the palette.
func (*NounBuilder) When ¶
func (b *NounBuilder) When(guard string) *NounBuilder
When guards the last declared verb with a registered guard name: while the guard is false at the focus and mode the verb would run in, the palette does not offer it. The guard reads a KeyEvent whose Focus and Level are that focus and whose Mode is that mode. A palette noun's default verb is never guarded (RegisterNoun refuses one). An empty name removes the guard.
type Operation ¶
type Operation struct {
Verb string `json:"verb"`
Noun string `json:"noun"`
Description string `json:"description"`
Parameters map[string]Parameter `json:"parameters"`
Result string `json:"result"`
Kind string `json:"kind"`
Confirm string `json:"confirm,omitempty"`
Repeatable bool `json:"repeatable,omitempty"`
// Rows names the noun whose rows the verb's result lists (a list
// verb's JSON array of rows of that noun); "" when the result is not
// rows. It is data for hosts (the catalog's rows); the runtime does
// not read it.
Rows string `json:"rows,omitempty"`
// State marks the verb whose answer is the rows of every one of a
// host's lists in one call (NounBuilder.State), as JSON Lines of
// cli.Row tagged by list noun ({"noun":"agent","id":..,"label":..}).
// Data for hosts (the catalog's state); the runtime does not read it.
State bool `json:"state,omitempty"`
// Quiet marks bookkeeping (a list reload) the jobs ticker does not
// show; set by NounBuilder.Quiet. The catalog's quiet.
Quiet bool `json:"quiet,omitempty"`
// Builtin marks an operation the framework registered itself: every
// one NewRuntime and NewModel register, and those a framework
// constructor registers later (NewPicker, NewPalette, grid.Register,
// markdown.Register, cli.AddCommands), each inside Runtime.Builtin. An
// application's verb is never builtin, even on a framework noun
// (history.capture-hook). Data for hosts (the catalog's builtin): a
// host mounting another tool's verbs skips these, which every
// ochazuke tool has; the runtime does not read it.
Builtin bool `json:"builtin,omitempty"`
// PersistArgs lets the history file keep this operation's arguments
// named like text (text, value, keys, args, password, secret, token), which
// it otherwise leaves out; set by NounBuilder.PersistArgs. Only for an
// operation whose arguments are never typed secrets (settings.set).
PersistArgs bool `json:"persistArgs,omitempty"`
// Motion marks movement (list.move, focus.next, surface.scroll,
// page.next): the footer's hint line leaves its rows out, since motions
// are standard and the footer is for the verbs the focus offers; ?
// help and bindings list keep them. Set by NounBuilder.Motion; the
// framework's own motions are marked as they register (motionOps).
Motion bool `json:"motion,omitempty"`
// HistoryKind is the kind of entry the operation records
// (HistoryAction, HistoryChange, HistoryFetch); empty derives it
// (HistoryKindOf). Set it to HistoryFetch on a verb that only asks for
// data (NounBuilder.Fetch, the catalog's history), so history.list's
// default view and the bounded ring leave its calls to the fetches.
HistoryKind string `json:"historyKind,omitempty"`
// Positional names the parameters bare words fill first, in this
// order (NounBuilder.Positional), ahead of ParameterOrder's
// required-then-by-name rest. The CLI gives a boolean a bare word only
// when it is named here. The catalog's positional.
Positional []string `json:"positional,omitempty"`
Run Handler `json:"-"`
App AppHandler `json:"-"`
}
Operation is one registered noun.verb. Kind is "interaction" (the default: Run executes synchronously on the loop) or "application" (App is an AppHandler whose pending work runs off the loop and reports through the delivery contract). Confirm, when set, is a prompt template ({{id}}, {{noun}}, {{label}}, {{<arg>}}) shown in a confirm modal before the operation runs. Repeatable marks a change (not a motion or navigation) that dot-repeat (history.repeat, bound to . on app in normal mode) may run again; set it on the Operation passed to Register.
func (Operation) HistoryKindOf ¶ added in v0.7.0
HistoryKindOf is the kind of history entry the operation records: its HistoryKind when set; else a fetch for a verb that answers rows (Rows, State), a change for a Repeatable one, an action for a Motion, a change for any other application verb (work that may change something outside the runtime: the safe reading of an extension verb that declares nothing), and an action for any other interaction verb.
func (Operation) ParameterOrder ¶
ParameterOrder lists the operation's parameters in positional order: the Positional names first, in their order, then the rest required first, then by name. Parameters is a map, so this is the declared order the palette's words and the CLI's bare arguments fill.
type Page ¶
type Page struct {
ID string `json:"id"`
Title string `json:"title"`
Focus string `json:"focus"`
Remembered string `json:"remembered"`
Render func(*Runtime, int, int) Block `json:"-"`
// OnOpen, when set, runs on the loop each time OpenPage makes this page
// current from another page (or from none: the first page opened), after
// the focus and mode are restored; from is the page left, "" for none.
// Reopening the current page does not run it. An application refreshes
// what the page shows here (SetItems, or Launch a reload job owned by
// one of its instances) instead of polling. Every way a page opens goes
// through OpenPage: page.open, page.next/previous, ctrl+j/k, the page
// picker.
OnOpen func(r *Runtime, from string) `json:"-"`
// Scrolloff is how many lines the page keeps visible above and below
// the focused element when it scrolls to follow the focus: 0 means the
// default, 2; a negative value keeps no margin.
Scrolloff int `json:"scrolloff,omitempty"`
// contains filtered or unexported fields
}
Page is the component a page instance fronts: a title, the instance it starts focused on (Focus), the focus it remembers while another page is open (Remembered, restored with its mode by OpenPage), and a renderer. Render returns the page body for the given cell bounds as a Block; its cursor, when the page holds the focused input, is relative to the body's top-left cell. Pages without inputs return Text(body).
type Palette ¶
type Palette struct {
// contains filtered or unexported fields
}
Palette is the ex-mode command line: one prompt input whose text is the source of truth, parsed by the grammar in palette_parse.go, with a completion list for the next word beneath it. It never edits the originating input. Create one palette per runtime: operation keys are globally unique.
func NewPalette ¶
NewPalette returns the command palette for r.
func (*Palette) RegisterNoun ¶
func (p *Palette) RegisterNoun(noun string, config PaletteNoun) error
RegisterNoun adds or replaces a live instance source without changing operation forms.
type PaletteEntry ¶
type PaletteEntry struct {
Value string `json:"value"`
Kind string `json:"kind"`
Label string `json:"label"`
ID string `json:"id,omitempty"`
Verb string `json:"verb,omitempty"`
}
PaletteEntry is one completion: Value is the word it appends, Kind is verb, noun or choice, Label what the list shows.
type PaletteInstance ¶
PaletteInstance is a labeled object whose ID becomes the default action argument.
func PagesPaletteSource ¶
func PagesPaletteSource(r *Runtime, _ Context) []PaletteInstance
PagesPaletteSource reads the runtime registry on every listing, not at startup.
type PaletteNoun ¶
type PaletteNoun struct {
Source PaletteSource
DefaultVerb string
Argument string
}
PaletteNoun explicitly chooses the action and string argument used for an instance.
type PaletteSource ¶
type PaletteSource func(*Runtime, Context) []PaletteInstance
PaletteSource reads current instances in the context captured when the palette opened.
type PaletteWord ¶
type PaletteWord struct {
Text string `json:"text"`
Kind string `json:"kind,omitempty"`
Value string `json:"value,omitempty"`
Param string `json:"param,omitempty"`
Candidates []string `json:"candidates,omitempty"`
}
PaletteWord is one word of the line and what it resolved to: Kind is verb, noun, instance or argument; Value is the full word ("" while it is unresolved); Candidates are the words an ambiguous prefix could be.
type Parameter ¶
type Parameter struct {
Type string `json:"type"`
Required bool `json:"required,omitempty"`
Description string `json:"description,omitempty"`
// Enum lists the static choices of a string parameter; Source names an
// operation (noun.verb) whose result lists more. Free also accepts a
// value outside them.
Enum []string `json:"enum,omitempty"`
Source string `json:"source,omitempty"`
Free bool `json:"free,omitempty"`
}
Parameter describes one argument of an operation: its type, whether it is required, and its choices.
type Payload ¶
type Payload struct {
Return string `json:"return,omitempty"`
Count int `json:"count,omitempty"`
OpCount int `json:"opCount,omitempty"`
Op string `json:"op,omitempty"`
Prefix string `json:"prefix,omitempty"`
Prompt string `json:"prompt,omitempty"`
Request *Request `json:"request,omitempty"`
Shadow *ModeState `json:"shadow,omitempty"`
}
Payload is the small typed state a mode carries (Runtime.Mode.Payload). For a pending mode Return is the mode it returns to on leave. Count and OpCount are the Vim counts before and after an operator; Op is the pending operator; Prefix is the key sequence typed so far; Request is a stored request (the completed match a sequence prefix falls back to, or a confirm's deferred action); Prompt is the text a confirm modal shows; Shadow is the mode the macro_recording shadow mode re-dispatches in.
type Picker ¶
type Picker struct {
Runtime *Runtime
Origin Context
Directory string
Filter string
Entries []PickerEntry
Selected int
Error string
Loading bool
// contains filtered or unexported fields
}
Picker owns one modal and one ordinary editor. Background commands only read immutable snapshots; HandleMessage is the sole result-application boundary. Its work runs as four replacing jobs on the picker instance (the "index", "search", "preview" and "stat" slots), so the runtime's jobs list decides which result is current: a newer job in a slot drops the older, and Close cancels them all.
func (*Picker) Close ¶
func (p *Picker) Close()
Close cancels indexing, searching and previews; the picker instance stays registered for the next open.
func (*Picker) HandleMessage ¶
HandleMessage applies only the current job of each slot (index, search, preview) on the UI loop; the runtime's jobs list says which that is.
func (*Picker) PendingCommand ¶
PendingCommand is drained by Runtime.PendingCommands after every event, including CallMsg. It schedules work, never waits on filesystem or search.
type PickerEntry ¶
PickerEntry is relative to the indexed root. Symlinks are selectable files, never traversal edges.
type Placement ¶
type Placement struct {
ID string `json:"id"`
// Line is the body line the view's first line landed on, -1 when the
// view reported no text or the page did not draw it; Height is its line
// count.
Line int `json:"line"`
Height int `json:"height"`
// Focus and FocusHeight are the focused lines, relative to Line.
Focus int `json:"focus"`
FocusHeight int `json:"focusHeight"`
}
Placement is one Placed call of a frame: the instance drawn and, when its view reported them (PlacedAt), the lines it covers in the page body and the lines inside it that hold the focus (a list's selected row, a grid's cursor row, an input's whole box, a terminal's top line).
type Pos ¶
type Pos struct {
X, Y int
}
Pos is a cell position inside a rendered block: zero-based, counted from the block's top-left corner.
type Predicate ¶
type Predicate struct {
Name string `json:"name"`
Arg string `json:"arg,omitempty"`
Of []Predicate `json:"of,omitempty"`
}
Predicate is one named test over an instance: a value, never a string selector. A query is a list of predicates, ANDed. Name is a registered predicate (noun, id, kind, within, child-of, focusable, region, state or one an application adds) and Arg its argument; the combinators any, all and not take nested predicate lists in Of instead. The wire form is a JSON array: ["noun","row"], ["any",[["noun","a"],["noun","b"]]].
func IsFocusable ¶
func IsFocusable() Predicate
func ParsePredicates ¶
ParsePredicates reads the wire form: a list of [name, arg] pairs, or [combinator, [nested pairs]] for any, all and not. A []Predicate from Go passes through.
type PredicateFunc ¶
PredicateFunc tests one instance; arg is the predicate's argument.
type QueryMatch ¶
type QueryMatch struct {
ID string `json:"id"`
Noun string `json:"noun"`
Parent string `json:"parent,omitempty"`
}
QueryMatch is one instances.query result row.
type Record ¶ added in v0.2.0
Record is one record's values by field name, as an editor loads and writes them.
type RecordDebounceMsg ¶ added in v0.2.0
RecordDebounceMsg is the timer a pause in typing sets off: when Seq is still the editor's latest change, the record is written.
type RecordEditor ¶ added in v0.2.0
type RecordEditor struct {
// Styles colour the labels (the zero value draws them plain); a modal
// editor uses the Model's.
Styles Styles
// contains filtered or unexported fields
}
RecordEditor is a form over one record: a field per schema entry, each a focus stop, and every change written as it is made. Typing in a text field is written after a pause (Debounce) and at once when the field is left or insert mode ends; a choice, an edit in normal mode, an undo or a redo is written at once. A value that is not valid (Required, the type, the choices, Validate) is not written, and its label says why. u and ctrl+r undo and redo the record's written changes, each written like any other; q and esc leave, and nothing is ever discarded. There is no save key.
The editor is an instance of the form noun (id) with a child per field (id/name): text fields are inputs of form-field (form-text when multiline), choice fields instances of form-choice, whose enter opens the chooser (a modal list of form-option rows).
func (*RecordEditor) Block ¶ added in v0.2.0
func (e *RecordEditor) Block(width, height int) Block
Block draws the form: per field its label (with why a value is not written) and its value, a text field as its input, a choice field as its value with the one highlight while focused; a failed write is the last line. Each field is placed in drawing order, so motions follow it.
func (*RecordEditor) Close ¶ added in v0.2.0
func (e *RecordEditor) Close()
Close writes what is pending (the editor is being removed).
func (*RecordEditor) Closed ¶ added in v0.2.0
func (e *RecordEditor) Closed() bool
Closed reports whether the editor was left (form.leave) or removed.
func (*RecordEditor) DebounceCurrent ¶ added in v0.2.0
func (e *RecordEditor) DebounceCurrent(tick RecordDebounceMsg) bool
DebounceCurrent reports whether a pause timer is for the latest change.
func (*RecordEditor) Failure ¶ added in v0.2.0
func (e *RecordEditor) Failure() error
Failure is the last background failure, cleared when read.
func (*RecordEditor) Flush ¶ added in v0.2.0
func (e *RecordEditor) Flush() error
Flush writes what is pending now (on quit).
func (*RecordEditor) Focus ¶ added in v0.2.0
func (e *RecordEditor) Focus() error
Focus focuses the first field (in insert mode when the spec says so).
func (*RecordEditor) FocusTarget ¶ added in v0.2.0
func (e *RecordEditor) FocusTarget() string
FocusTarget is where a jump to the editor lands: its first field.
func (*RecordEditor) HandleMessage ¶ added in v0.2.0
func (e *RecordEditor) HandleMessage(msg tea.Msg) bool
HandleMessage writes the record when its pause timer is the latest.
func (*RecordEditor) ID ¶ added in v0.2.0
func (e *RecordEditor) ID() string
ID is the editor's instance id.
func (*RecordEditor) ModalBlock ¶ added in v0.2.0
func (e *RecordEditor) ModalBlock(s Styles, width, height int) Block
func (*RecordEditor) ModalTitle ¶ added in v0.2.0
func (e *RecordEditor) ModalTitle() string
ModalTitle and ModalBlock draw a modal editor (ModalBody).
func (*RecordEditor) PendingCommand ¶ added in v0.2.0
func (e *RecordEditor) PendingCommand() tea.Cmd
PendingCommand notices changes: typing in a text field sets the pause timer; leaving a field, ending insert mode or any other change writes at once and closes the field's undo step.
func (*RecordEditor) Problem ¶ added in v0.2.0
func (e *RecordEditor) Problem(name string) string
Problem says why a field's value is not written, "" when it is.
func (*RecordEditor) Values ¶ added in v0.2.0
func (e *RecordEditor) Values() Record
Values is every field's value as shown, valid or not.
func (*RecordEditor) WriteError ¶ added in v0.2.0
func (e *RecordEditor) WriteError() string
WriteError is the last write's failure, "" once a write succeeds.
func (*RecordEditor) Written ¶ added in v0.2.0
func (e *RecordEditor) Written() Record
Written is the record as written (or queued to be): the last valid value of every field.
type RecordField ¶ added in v0.2.0
type RecordField struct {
Name string `json:"name"`
Label string `json:"label,omitempty"` // shown above the value (default Name)
Parameter
Multiline bool `json:"multiline,omitempty"`
// Validate checks a value the type, Required and the choices allow;
// its error is why the value is not written.
Validate func(value string) error `json:"-"`
}
RecordField is one editable field of a record schema. Its Parameter is the same description a verb's parameter carries (Type, Required, Enum, Source, Free, Description), so a form can come from a verb's catalog parameters (RecordFields). A field with Enum or Source (and not Free), or of Type boolean, is edited through a chooser, never as free text. A Free field with Enum or Source is a text field with suggestions (form-suggest): typing stays free text, enter in normal mode or ctrl+space opens the framework chooser over the suggestions (the Enum, then the Source's result, loaded off the loop when the Source verb is Pending), a pick fills the field and is written at once, and a value outside the suggestions is written as typed; it is one line high (Multiline is ignored). The rest are text inputs, Multiline ones several lines high.
func RecordFields ¶ added in v0.2.0
func RecordFields(op Operation) []RecordField
RecordFields is a form's schema from a verb's parameters, in the order bare CLI words fill them (Operation.ParameterOrder): a mounted tool's edit verb gets a form from its catalog alone.
type RecordSpec ¶ added in v0.2.0
type RecordSpec struct {
Title string // the modal's title; a placed editor's heading is the application's
Fields []RecordField
// Load reads the record when the editor opens (nil: every field empty).
Load func() (Record, error)
// Save writes one change: Done, Failed, or Pending work that runs off
// the loop. At most one write is in flight; changes made meanwhile go
// in the next write. A failed write keeps the values on screen, says
// so, and is retried with the next change.
Save func(RecordWrite) Result
// Debounce is the pause in typing before a text field is written
// (DefaultRecordDebounce when zero).
Debounce time.Duration
// Insert opens the editor with the first field in insert mode when it
// is a text field.
Insert bool
// OnLeave runs after the editor closed (form.leave): every change is
// written or queued by then; a placed editor stops being drawn.
OnLeave func()
}
RecordSpec is what an application gives a record editor: the schema, how to load the record and how to write it.
type RecordWrite ¶ added in v0.2.0
RecordWrite is one write an editor hands Save: the record as it is to be stored (every field's last valid value) and the fields this write changes, in schema order.
func (RecordWrite) String ¶ added in v0.2.0
func (w RecordWrite) String() string
String reads a write in one line: "write title=milk status=doing", the changed fields in order (a value with spaces or empty is quoted).
type RecordingSink ¶ added in v0.4.0
type RecordingSink struct {
// contains filtered or unexported fields
}
RecordingSink is a UISink that keeps every message, for tests. Attach it with r.UI().Attach(&ochazuke.RecordingSink{}).
func (*RecordingSink) ClearNotice ¶ added in v0.4.0
func (s *RecordingSink) ClearNotice(id NoticeID)
ClearNotice records a clear.
func (*RecordingSink) LastStatus ¶ added in v0.4.0
func (s *RecordingSink) LastStatus() string
LastStatus is the last status recorded, "" for none.
func (*RecordingSink) Messages ¶ added in v0.4.0
func (s *RecordingSink) Messages() []UIMessage
Messages is a copy of what the sink recorded, in order.
func (*RecordingSink) Notices ¶ added in v0.4.0
func (s *RecordingSink) Notices() []string
Notices is the text of the notices still standing (posted and not cleared), oldest first.
func (*RecordingSink) Notify ¶ added in v0.4.0
func (s *RecordingSink) Notify(id NoticeID, text string)
Notify records a notice.
func (*RecordingSink) Status ¶ added in v0.4.0
func (s *RecordingSink) Status(text string)
Status records a status.
type Registers ¶
type Registers struct {
Named map[string]Register
History []Yank
Active string
Macro MacroState
// contains filtered or unexported fields
}
Registers is the component that owns the shared yanks, named registers, yank history, the register selected for the next operation and the macro state. It is one instance under app, reached through the register, macro and yank-history operations and Runtime.Registers(), never through Runtime fields. Its key rows (q, @, " and the pending modes they enter) sit on the app noun so a page or list focus can record and replay too.
func (*Registers) Close ¶
func (g *Registers) Close()
Close abandons a recording in progress; the registers themselves stay.
func (*Registers) HandleMessage ¶
HandleMessage: the registers do no off-loop work.
func (*Registers) PendingCommand ¶
PendingCommand: nothing is ever scheduled.
type Request ¶
type Request struct {
Verb string `json:"verb"`
Noun string `json:"noun"`
Target string `json:"target,omitempty"`
Args Arguments `json:"args,omitempty"`
Confirmed bool `json:"confirmed,omitempty"`
}
Request names an operation and, optionally, the instance it addresses. Confirmed skips the operation's Confirm prompt: the confirm modal's y sets it on the stored request, and a script may set it to run unattended.
type Response ¶
type Response struct {
// Result is the operation's result. From HandleCall it is detached
// from application state: Lines stays Lines (each line encoded), any
// other value is its JSON encoding as a json.RawMessage, so object
// keys keep the order the handler's value marshals in (a struct's
// field order); a nil or null result is nil.
Result any `json:"result,omitempty"`
Error string `json:"error,omitempty"`
// Argument is true when Error is an ArgumentError: the request was
// refused for its arguments, before any instance was chosen.
Argument bool `json:"argument,omitempty"`
// Messages are what the call told the user while it ran (ctx.Notify,
// ctx.ClearNotice, ctx.Status), in order; the runtime's sink got them
// too. Messages posted later, by a job's Then, reach only the sink.
Messages []UIMessage `json:"messages,omitempty"`
}
Response is the reply to a socket call: a result or an error message.
type Result ¶
type Result struct {
// contains filtered or unexported fields
}
Result is what an application handler returns.
func Pending ¶
Pending schedules work off the loop as a job that accumulates: it runs beside the owner's other jobs and its completion is delivered whenever it finishes. The context is cancelled when the owning instance closes.
func (Result) Label ¶ added in v0.2.0
Label names this job for people reading the jobs list: the ticker shows it after the verb ("agent.launch claude running") and jobs.list carries it. It says which of a verb's jobs this is (the program a launch starts, the file a build writes); "" leaves the verb alone.
func (Result) Replacing ¶
Replacing puts the pending work in a slot on its owner: starting it cancels the owner's running job in the same slot, and a newer job in the slot cancels this one. Use it for replaceable work such as a preview or a search, never for independent work.
func (Result) ReplacingAt ¶
ReplacingAt is Replacing with the slot scoped to scope, the owner or one of its ancestors: the newest job in (scope, slot) cancels the older one whichever descendant of scope asked, so previews launched from the rows of one list replace each other while another list keeps its own. The job still belongs to the row that asked (its completion and Then land there and closing it cancels the job); Replacing(slot) is ReplacingAt(owner, slot). A scope off the owner's ancestry fails the launch.
type Runtime ¶
type Runtime struct {
Nouns map[string]*Noun
Instances map[string]*Instance
Focus string // the focused instance; Context() is derived from it
Mode ModeState // the one interaction mode; mode.set writes it, a focus change to another stop resets it
Page string // the current page instance; always an ancestor of BaseFocus()
Modes map[string]bool
Operations map[string]Operation
Quit bool
Pending string
BindingTimeout time.Duration
// ResolveTarget, when set, maps a request target that is not an
// instance (a foreign id: an extension's row id, a database key) to
// the instance that stands for it; ExecuteAt consults it (TargetInstance)
// before refusing an unknown target, so keys, the palette, the CLI and
// the API all accept the foreign id. An error refuses the request with
// it; "" and no error leaves the target unknown.
ResolveTarget func(target string) (string, error)
// contains filtered or unexported fields
}
Runtime is owned by one event loop. Transport callers submit messages to that loop. It holds the operation registry (Operations, Modes and their guards), the instance registry (Nouns, Instances and their parent links, including list rows), the three plain interaction fields Focus, Mode and Page with the chain of open modals, the pending key-sequence state (Pending, prefix, BindingTimeout) and the hook that hands off-loop work to the adapter (commands). Components such as inputs, lists, the picker and the registers are instances, never fields; TestRuntimeHoldsNoComponentFields pins this list.
func NewRuntime ¶
func NewRuntime() *Runtime
NewRuntime returns a runtime with the framework nouns registered and focus on the app instance.
func (*Runtime) ActionFor ¶
ActionFor returns the innermost noun handler for an operation key on the focus stack, or nil when the operation's own Run applies.
func (*Runtime) AddDetail ¶ added in v0.2.0
AddDetail registers a detail instance under its parent (Parent(page) or an instance beneath the page) and returns its component. item names what the detail shows now (the selected row's id); a different answer than the last one starts the detail at the top. A nil item never resets.
func (*Runtime) AddInput ¶
func (r *Runtime) AddInput(in *Input, opts ...InstanceOption) error
AddInput registers an editor instance. Options: Parent(id) (default app), Kind(noun) (default "editor"; "prompt" pins insert mode) and Completions(triggers...).
func (*Runtime) AddList ¶
AddList registers a list instance of the list noun with its rows. Options: Parent(id) (default app), Kind(noun) for a list that answers to its own noun as well, NoSpill() for a list whose motions stay inside it, and Columns(...) for a table.
func (*Runtime) AddPage ¶
func (r *Runtime) AddPage(id, title string, render func(*Runtime, int, int) Block, opts ...InstanceOption) (*Page, error)
AddPage registers a page instance of kind page under app with a title and a renderer. Options: Focus(id) names where the page starts (the page itself or an instance beneath it, registered first) and Kind(noun) a noun of the application's own. Registration does not activate the page; see OpenPage. It is RegisterPage for callers that do not hold a *Page.
func (*Runtime) AddRecordEditor ¶ added in v0.2.0
func (r *Runtime) AddRecordEditor(id string, spec RecordSpec, opts ...InstanceOption) (*RecordEditor, error)
AddRecordEditor places a record editor under Parent (default app); the application draws it with Block in its page. FocusOnClose names where the focus goes when it leaves. Call Focus to start editing.
func (*Runtime) AddSettingsPage ¶ added in v0.7.0
AddSettingsPage registers the Settings page as a permanent page, a tab in registration order like the application's own; settings.edit then switches to it and settings.close goes back without removing it. Without it, settings.edit registers the page when it opens and settings.close removes it.
func (*Runtime) AddTerminal ¶
func (r *Runtime) AddTerminal(id string, stream TerminalStream, opts ...InstanceOption) (*Terminal, error)
AddTerminal registers a terminal instance of the terminal noun fed by stream, in terminal mode: every key forwards to the pane except the leader. Options: Parent(id) (default app), Kind(noun) for a noun that supplies its own tables and CloseOnDetach to remove the instance (and release the stream) on detach. The first frame read is scheduled at once.
func (*Runtime) AddTree ¶
AddTree registers a tree under Parent (default app) with its nodes. Columns(...) makes its rows a table; NoSpill keeps motions inside it; NoMarks makes it a read-only view whose rows take no marks.
func (*Runtime) Ancestry ¶
Ancestry walks the parent links from id outward: id first, app last. An unknown id yields nil.
func (*Runtime) BaseFocus ¶
BaseFocus is the focus beneath every open modal: the return of the outermost modal, else Focus. Runtime.Page is always an ancestor of it.
func (*Runtime) BaseMode ¶
BaseMode is the mode Runtime.Mode stands in: its name, or for a pending mode or a key-sequence prefix the base mode it returns to.
func (*Runtime) Bind ¶
Bind installs rows from config or code onto their noun or instance tables by identity (mode, keys or pattern, and When): the row with the same identity is replaced in place, a new row is added (a guarded one before the unguarded row on its keys, so it answers first while its guard holds), and an unbind row removes only the row with its identity. A key sequence in progress (d of d d) is kept unless a row added or removed is on it: in its mode, with the keys typed so far, a sequence extending them or one they extend. Such a row cancels the sequence, so the next key starts fresh against the new tables.
func (*Runtime) BindingTimeoutCommand ¶
BindingTimeoutCommand schedules the latest deadline once. Custom Tea models call it after dispatch and send BindingTimeoutMsg to HandleBindingTimeout.
func (*Runtime) Builtin ¶ added in v0.8.0
func (r *Runtime) Builtin(register func())
Builtin runs register and marks every operation it registered as the framework's own (Operation.Builtin). NewRuntime and NewModel wrap their registrations in it, and so does every framework constructor that registers operations after them (NewPicker, NewPalette, NewAppearance, grid.Register, markdown.Register, cli.AddCommands), so an operation registered lazily is marked too. Operations registered before it, or by the application at any other time, keep Builtin false. Calls nest. It is for framework packages; an application's own verbs are not builtin.
func (*Runtime) CancelPendingBinding ¶
func (r *Runtime) CancelPendingBinding()
CancelPendingBinding leaves a key-sequence prefix mode without running its completed match and invalidates its timer.
func (*Runtime) CheckUserBindings ¶ added in v0.2.0
CheckUserBindings reports what a load of the bindings file would skip, without installing anything, and any row of the merged tables that no longer validates.
func (*Runtime) Choices ¶
Choices lists a parameter's accepted values in context c: its Enum, then the result of its Source operation. A source that asks for confirmation is refused; it must be a read.
func (*Runtime) Chooser ¶ added in v0.2.0
Chooser is the open chooser of kind, nil when none is open.
func (*Runtime) CompletionTriggers ¶ added in v0.5.0
func (r *Runtime) CompletionTriggers(id string) []CompletionTrigger
CompletionTriggers are the triggers an input completes with: its own, else its noun's.
func (*Runtime) DeclareSetting ¶ added in v0.2.0
DeclareSetting declares settings; each must have a unique name, a known type and a default of that type (in the enum when there is one).
func (*Runtime) Define ¶
func (r *Runtime) Define(name string) *NounBuilder
Define declares a noun, or returns the builder of an existing one.
func (*Runtime) DefineGuard ¶
DefineGuard registers a named row guard.
func (*Runtime) DefineMode ¶
DefineMode registers a mode name. A pending mode is exclusive: only rows in its own table answer, and a row that leaves the mode unchanged returns the instance to the mode it shadowed.
func (*Runtime) DefinePassthrough ¶
DefinePassthrough marks a defined mode as a passthrough mode: while it is the base mode (a pending mode over it included) capture rows stand aside, so the focused level's rows answer every key. The terminal mode is one: ctrl+c reaches the pane instead of the app's captured quit.
func (*Runtime) Deliver ¶
Deliver routes a message on the loop: a Completion goes to its owner when its job is running and is dropped otherwise; any other message is offered to every component until one claims it. A Then callback that removes its own owner is safe: the job is already settled and the completion is not offered to the gone component. It reports whether a component consumed the message and the delivered completion's error, if any.
func (*Runtime) Dispatch ¶
Dispatch resolves one key through the stack walk and runs the first row that answers. It reports whether any row claimed the key. Live keys and macro playback both arrive here.
func (*Runtime) EnsureConfigSettings ¶ added in v0.2.0
func (r *Runtime) EnsureConfigSettings()
EnsureConfigSettings declares the settings the framework reads from the user's settings.json, unless the application declared one of the same name first: theme (the colour scheme; its choices are the built-in themes and themes.json's, read here and again when the config directory changed) and history-limit while the history is persisted. It applies terminal-leader when an application declared it (EnsureTerminalLeader). Model.Init and the CLI shell call it, so settings set works in both; an application may call it earlier (after setting Config.App) to have them before the Model starts.
func (*Runtime) EnsureHistory ¶ added in v0.2.0
func (r *Runtime) EnsureHistory()
EnsureHistory persists the action history, once: it reads the history file (the last history-limit entries, marked Restored, before what this session already recorded), compacts it when it holds more or has lines that do not parse (each such file is one notice), and starts the writer every later entry is appended through. Nothing happens without a state directory (Config.Disable, a test binary) or with Config.NoHistoryFile. Model.Init calls it; the CLI shell does not (a one-shot call is not history worth keeping).
func (*Runtime) EnsureTerminalLeader ¶ added in v0.2.0
func (r *Runtime) EnsureTerminalLeader()
EnsureTerminalLeader declares the terminal-leader setting unless the application declared one, and applies it: an application with terminal panes calls it at setup (cli.AddCommands does), so settings.json, the Settings page and the CLI's settings set know the setting before the first pane opens. An application without terminals does not, and its settings list stays free of it.
func (*Runtime) EnsureUserActions ¶ added in v0.2.0
EnsureUserActions installs the user's actions.json once; later calls do nothing. Model.Init, cli.Mount and the CLI shell call it before the user bindings, so a bindings.json row can name an action's verb.
func (*Runtime) EnsureUserBindings ¶ added in v0.2.0
EnsureUserBindings applies the user bindings file once; later calls do nothing. Model.Init and the CLI shell call it, after the application defined its own rows, so a file row replaces an application default.
func (*Runtime) ExecuteAt ¶
ExecuteAt runs an operation for a context. The innermost noun on the focus stack that overrides the operation handles it; otherwise its Run does. Every request is appended to the action history with its kind, the context it ran in, its outcome and where it moved the interaction.
func (*Runtime) ExportConfig ¶ added in v0.6.0
func (r *Runtime) ExportConfig(dir string, force bool) (ConfigExport, error)
ExportConfig writes a complete reference of the user configuration into dir ("" is <config dir>/reference): settings.json with every declared setting at its current value, settings.reference.json with each setting's type, default, choices, description and value, and bindings.reference.json with every stored binding row in the bindings.load shape (bindings.list --all). Each file is written atomically, a temp file renamed over it. A file that would land on one of the live config files (dir is the config directory) is refused unless force is set, and then nothing is written.
func (*Runtime) HandleBinding ¶
HandleBinding dispatches a named key; kept for callers that only know keys.
func (*Runtime) HandleBindingTimeout ¶
func (r *Runtime) HandleBindingTimeout(msg BindingTimeoutMsg) (bool, error)
HandleBindingTimeout executes the longest completed match, or clears an incomplete prefix. Its result is false for a stale or cancelled timer.
func (*Runtime) HandleCall ¶
func (*Runtime) History ¶
func (r *Runtime) History(n int) []HistoryEntry
History returns the last n entries of every kind, oldest first (all of them for n <= 0): the user's and the fetches, merged by Seq.
func (*Runtime) HistoryOf ¶ added in v0.7.0
func (r *Runtime) HistoryOf(n int, kinds ...string) []HistoryEntry
HistoryOf returns the last n entries of the given kinds (every kind when none is given), oldest first; n <= 0 returns all of them.
func (*Runtime) Instance ¶
func (r *Runtime) Instance(id string, opts ...InstanceOption) *Instance
Instance registers a plain instance: a page body, a panel, a modal body. Its noun is defined when it does not exist yet. Registering an existing id returns it unchanged.
func (*Runtime) InstancePath ¶
InstancePath is Ancestry reversed: app first, id last.
func (*Runtime) Issue ¶
Issue admits a job for owner and returns its ticket and the context its work runs under; the caller runs the work and reports back with a message carrying the ticket, checked with Accepts and closed with Settle. A slot name cancels the owner's running job in that slot; "" accumulates. Launch and Start build on it for work the runtime runs as a tea.Cmd.
func (*Runtime) IssueAt ¶
IssueAt is Issue with the slot scoped to scope, owner or one of its ancestors: the running job in (scope, slot) is cancelled whichever instance owns it. See Result.ReplacingAt.
func (*Runtime) Jobs ¶
Jobs lists every job the runtime knows in start order: the running ones and the finished ones retained since the last jobs.list read.
func (*Runtime) JumpFocus ¶
JumpFocus moves the focus steps stops (scope "stop") or regions (scope "region") forward, or backward for negative steps, through the focus root in drawing order (units), wrapping. The current unit is the nearest stop (or region) on the focus path; the next one is the first after that unit's whole subtree. A stop is never descended into (a grid is one stop, its cells are not); the focus lands on the unit's remembered child.
func (*Runtime) Launch ¶
Launch starts a pending result as a job of owner under verb and queues its work for the adapter. The completion reaches the owner's Component.HandleMessage and the result's Then callback when the job is still current.
func (*Runtime) ListBindings ¶
ListBindings prints the rows the focus answers to in its current mode, one per key or pattern, sorted by key with pattern rows last.
func (*Runtime) LoadBindingSpec ¶
LoadBindingSpec installs a spec onto one noun: modes, then rows.
func (*Runtime) LoadBindings ¶
LoadBindings installs rows from a JSON array in the binding row shape and returns the installed rows.
func (*Runtime) ModalFocus ¶
ModalFocus is the instance an open modal points at: Focus for the top modal, else the return focus stored in the modal opened over it.
func (*Runtime) OpenChooser ¶ added in v0.2.0
func (r *Runtime) OpenChooser(spec ChooserSpec) (*Chooser, error)
OpenChooser opens a chooser modal with its search input focused in insert mode. Like OpenModal, it opens only from the top level.
func (*Runtime) OpenModal ¶
OpenModal opens a modal whose body is a new instance of noun kind (its id is the kind), parented at the current focus and carrying payload, and focuses it (or the input WithInput places in it). The instance lives until Pop closes the modal. The kind's rows answer first, then the focus it opened over, then the modal noun.
func (*Runtime) OpenPage ¶
OpenPage makes a page current and restores the focus and mode it was left in; an open modal blocks navigation. Runtime.Page is always an ancestor of the focus.
func (*Runtime) OpenPagePicker ¶ added in v0.2.0
OpenPagePicker opens the page chooser (page.pick): the pages visited before, most recent first, then the pages never visited in registration order, then the current page, marked "current", so the highlighted first row is the page last left and enter goes back to it. Typing filters by title; enter opens the highlighted page, esc closes.
func (*Runtime) OpenRecordEditor ¶ added in v0.2.0
func (r *Runtime) OpenRecordEditor(id string, spec RecordSpec) (*RecordEditor, error)
OpenRecordEditor opens a record editor as a modal over the focus, its first field focused; leaving closes the modal and restores the focus and mode it opened over.
func (*Runtime) PageFocus ¶
PageFocus is the focus a page shows: the live base focus while it is the current page, else the focus it remembers.
func (*Runtime) PageList ¶
PageList lists pages in registration order: app's children of kind page. It reads the app instance's page order (appPages), so a frame that asks several times costs the number of pages, not of instances; without one (an application gave app a component of its own) it scans the instances.
func (*Runtime) PaneLayout ¶ added in v0.4.0
PaneLayout is l with the divider of the page id is on (or is): a page renderer that draws a list/detail split passes its Layout through it, so Split, SplitBlock, SplitFocusBlock and Divide follow the page's pane keys. Called while the page renders, it also records that the page draws a split, which is when pane.grow, pane.shrink and pane.reset answer their keys and show in the hints.
func (*Runtime) PaneShift ¶ added in v0.4.0
PaneShift is the remembered divider of page (Layout.Shift), 0 for the split's default.
func (*Runtime) PendingCommands ¶
PendingCommands drains the work scheduled since the last call: the runtime's own queue and every component's PendingCommand.
func (*Runtime) Placed ¶
Placed records that the instance id is being drawn now, during its page's render: the order of these calls in a frame is the page's drawing order, which focus jumps (focus.next, focus.previous) and list spills walk, so motions follow the screen as drawn and cannot drift from it. List, Input (InputBlock), Terminal and grid views call it; a component of the application's own calls it from its view. Outside a page render it does nothing. There is no other way to order stops: before the first frame the order is the tree's, and once a frame drew any stop, a stop the last frame did not draw is skipped (it is not on screen). A stop drawn by an application view that never calls Placed is therefore skipped too.
func (*Runtime) PlacedAt ¶
PlacedAt records where the view text of instance id holds the focus (lines focus to focus+height of text; a list's selected row, an input's whole box) and returns text marked so its page finds the body line it lands on, which is how the page scrolls to keep the focus visible. Call it with the view's final text after Placed; it amends that placement (or places id, if Placed was not called). Outside a page render it returns text unchanged. List, Input, Terminal and grid views call it.
func (*Runtime) Pop ¶
Pop closes the active modal and restores the focus and mode it opened over. A body the modal created is closed through the delivery contract and removed with what it holds.
func (*Runtime) Push ¶
Push opens a modal with id focused on focus (app when empty). An id that is not already an instance becomes one of the modal noun for as long as it is open. The modal remembers the focus and mode it opened over.
func (*Runtime) Query ¶
Query returns the instances matching every predicate, in tree order: app first, then depth-first with siblings in the order they were added. An unknown predicate matches nothing; instances.query reports it instead.
func (*Runtime) ReadYank ¶
ReadYank reads a register ("" is the active register, else the unnamed one).
func (*Runtime) RecordEditor ¶ added in v0.2.0
func (r *Runtime) RecordEditor(id string) *RecordEditor
RecordEditor is the record editor with this id, or nil.
func (*Runtime) Register ¶
Register adds an operation. An operation with App set is of kind application and its Run is the framework's dispatcher for it.
func (*Runtime) RegisterPage ¶
func (r *Runtime) RegisterPage(page *Page, opts ...InstanceOption) error
RegisterPage registers a page as an instance of kind page under app (the instance may already exist, registered through Instance with the inputs and lists it holds). Focus names where the page starts: the page itself or an instance beneath it. Registration does not activate the page.
func (*Runtime) RegisterPredicate ¶
func (r *Runtime) RegisterPredicate(name string, fn PredicateFunc)
RegisterPredicate adds a named predicate an application's queries (and the CLI's instances.query) can use, such as marked.
func (*Runtime) ReloadThemes ¶ added in v0.2.0
ReloadThemes reads themes.json again: the schemes that validate replace the user's, every problem is reported (and the last read's withdrawn), and the theme setting's choices follow when the framework declared it. A missing file is no schemes and no problem.
func (*Runtime) ReloadUserActions ¶ added in v0.2.0
ReloadUserActions removes the actions a previous load installed, then reads actions.json again and installs each valid entry as an application verb. An entry that does not validate (an unknown noun, a verb that exists, a bad template) is skipped and reported, never fatal; a file that does not parse installs nothing. A missing file is no actions and no problem. It returns the problems, each also sent to Config.Report.
func (*Runtime) ReloadUserBindings ¶ added in v0.2.0
ReloadUserBindings takes out the rows a previous load installed (the rows they replaced come back), then reads the bindings file again and installs its rows one by one: a row that does not validate is skipped and reported, never fatal, and a file that does not parse installs nothing. A missing file is no rows and no problem. It returns the problems, each also sent to Config.Report.
func (*Runtime) RemoveInstance ¶
RemoveInstance closes an instance and its descendants (components closed, jobs cancelled) and drops them. Every focus reference into the removed subtree (Focus, a page's remembered focus, an open modal's return) moves to the nearest surviving ancestor (the Focus itself to a removed instance's FocusOnClose target when that survives); an open modal inside the subtree is kept and reparented there. app cannot be removed.
func (*Runtime) RetargetFocus ¶
RetargetFocus points every focus reference that match accepts (the focus, a page's remembered focus, an open modal's return) at to. A component that recreates its focused child (the grid's cell, the list's row) calls it after the move; staying inside one focus stop, it keeps the mode.
func (*Runtime) SetConfirm ¶
SetConfirm sets or clears (empty prompt) the confirm prompt of noun.verb.
func (*Runtime) SetFocus ¶
SetFocus points the focus at one instance: an input, a list, a row, a page or a modal body. Without a modal, the focus must sit inside the current page; a hidden page's instances are addressed with an explicit target.
func (*Runtime) SetMode ¶
SetMode sets the global mode by name and clears its payload, as mode.set does: a focused input runs its own transition (insert sessions, visual anchor), and a pinned input stays in its pinned mode.
func (*Runtime) SetPaneShift ¶ added in v0.4.0
SetPaneShift remembers page's divider, clamped to PaneShiftLimit either way, and writes the panes file (the state directory's PanesFile) when there is one; a failed write is a notice and the divider still holds for the session. It returns the shift kept.
func (*Runtime) SetTerminalLeader ¶ added in v0.2.0
SetTerminalLeader moves every leader to key: on every noun, each row that enters leader_pending on one key (the framework's terminal row and an application's own, such as a richer hint) is rebound to key with key as its prefix and its timeout request, and the leader_pending row that sends the old leader to the pane now sends key on key. Hints that name the old leader name the new one. A row already bound to key in those tables gives way. The rows stay data: this rewrites them as a binding file would. The terminal-leader setting calls it; a key that is not one ctrl+ or alt+ combination is refused.
func (*Runtime) Settle ¶
Settle records the outcome of a running job and reports whether the ticket was current; a stale ticket leaves the list unchanged. Deliver settles the completions it routes; a component that runs its own commands settles the tickets it issued.
func (*Runtime) Sourced ¶
Sourced sets the source the requests executed until restore is called are recorded with, unless an outer caller already set one (a row run by a key inside a macro replay keeps "macro:q"). Callers: the resolver ("key:<keys>"), the transport ("cli"), the palette ("palette").
func (*Runtime) Start ¶
func (r *Runtime) Start(owner string, work func(context.Context) (any, error), then func(Ctx, any, error), c Ctx) (Ticket, error)
Start schedules accumulating work owned by an instance and returns its ticket; it is Launch with Pending(work).Then(then) under the verb "work".
func (*Runtime) StopBindings ¶ added in v0.2.0
func (r *Runtime) StopBindings() []StopBindings
StopBindings is the app-wide keyboard: the effective rows of every focus stop, as ListBindings gives them for the focus a jump to the stop lands on. The order is fixed: the pages in tab order (PageList), each page's stops in drawing order (the order focus.next walks, undrawn stops after in tree order), then the open modals bottom to top with theirs, then app in normal mode. The mode is the one the focus would have there: the current mode at the current focus, else the stop's pinned mode (a prompt is insert, a terminal terminal), else normal. Nothing moves: the focus and mode are back as they were on return.
It differs from bindings.list --all, which exports every stored row (each noun's and instance's tables, every mode, as configuration JSON), active or not: this answers "what does each key do where", after shadowing, guards and the modal boundary.
func (*Runtime) StoreYank ¶
StoreYank puts a yank into the shared registers with the bookkeeping the editor's yank operations use: the named or active register, the unnamed register, "0" for a yank or "1".."9" and "-" for a deletion, and the yank history. A component outside the package (a grid) yanks shapes the editor does not know ("column"), which register.set refuses, so it stores through this call and the editor still sees the text.
func (*Runtime) TargetInstance ¶ added in v0.2.0
TargetInstance is the instance a request target names: the target when it is an instance, else what ResolveTarget maps it to. An unknown target is an error naming it.
func (*Runtime) TerminalLeader ¶ added in v0.2.0
TerminalLeader is the key the terminal noun's leader row binds (the terminal-leader setting once applied), DefaultTerminalLeader when the noun has no leader row.
func (*Runtime) UI ¶ added in v0.4.0
UI returns the UI component: Notify, ClearNotice and Status for code without a Ctx (setup, daemon events), Attach for a host.
func (*Runtime) UserActions ¶ added in v0.2.0
UserActions are the actions installed from actions.json, in file order.
func (*Runtime) ValidateBindings ¶
ValidateBindings checks every row of every noun and instance table the way Bind checks a row it installs: keys or a pattern, a registered mode and guard, and a Request to a registered operation with known arguments and sources, or an unbind. Every row is therefore atomic. It is the check behind TestBindingRowsAreAtomic and is for an application to run after it loads its own rows.
type Scheme ¶ added in v0.2.0
type Scheme struct {
Background string `json:"background,omitempty"`
Text SchemeColor `json:"text"`
Muted SchemeColor `json:"muted"`
Accent SchemeColor `json:"accent"`
Border SchemeColor `json:"border"`
Surface SchemeColor `json:"surface"`
Error SchemeColor `json:"error"`
}
Scheme is a named colour scheme: the palette roles NewStyles draws pages, panels, inputs and modals with. Background is which side of each role it draws: "adaptive" (the terminal's, the default), "light" or "dark". Text is body text and the title; Muted hints and inactive tabs; Accent the active tab, badge, subtitle and focused borders; Border unfocused panel borders; Surface the active tab's and badge's background; Error errors, kept apart from Accent and Muted. Selection stays reverse video in every scheme, so the selected row reads without colour.
type SchemeColor ¶ added in v0.2.0
SchemeColor is one palette role: Light is drawn on a light background, Dark on a dark one. Each is "#RRGGBB", "#RGB" or an ANSI index "0" to "255". In themes.json a role is one colour for both, or {"light": "...", "dark": "..."}.
func (*SchemeColor) UnmarshalJSON ¶ added in v0.2.0
func (c *SchemeColor) UnmarshalJSON(data []byte) error
UnmarshalJSON reads "#hex" (both sides) or {"light", "dark"} (a missing side takes the other).
type SchemeSet ¶ added in v0.2.0
type SchemeSet struct {
// contains filtered or unexported fields
}
SchemeSet is a read-only set of named schemes; a nil set is empty.
func NewSchemeSet ¶ added in v0.2.0
NewSchemeSet holds a copy of schemes.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server serves runtime requests over a Unix socket; see Listen.
type Setting ¶ added in v0.2.0
type Setting struct {
Name string `json:"name"`
Type string `json:"type"`
Default any `json:"default"`
Description string `json:"description,omitempty"`
Enum []string `json:"enum,omitempty"`
// Section files the setting under a section of the Settings page; ""
// takes the name before its last dot ("ext.ai.poll-every" is in
// "ext.ai"), and a name without a dot is in SettingsGeneral
// (SectionName).
Section string `json:"section,omitempty"`
// Validate, when set, checks a value of the right type further: Set
// refuses a value it rejects and a file value it rejects reads the
// default, as a value of the wrong type does.
Validate func(value any) error `json:"-"`
}
Setting is one declared user preference: its name, type, default, the line the settings list shows and, for a string, the allowed values. Settings are not for secrets: the file is plain JSON in the config directory.
func (Setting) SectionName ¶ added in v0.7.0
SectionName is the section the Settings page files the setting under: Section when declared, else the name before its last dot ("ext.ai.poll-every" is in "ext.ai"), else "" (SettingsGeneral).
type SettingValue ¶ added in v0.2.0
SettingValue is a setting with its current value, as settings.list and settings.get answer: Value and Default in their file form (a duration as "400ms"), Set when settings.json holds a value for it.
type Settings ¶ added in v0.2.0
type Settings struct {
// contains filtered or unexported fields
}
Settings holds the declared settings and their values from settings.json in the config directory. It is part of the config component, reached through Runtime.Settings(). The file is read on first use (and again when the config directory changes), written atomically (a temp file renamed over it) on every Set and Reset, and keeps every key it holds: an unknown or invalid key is reported and written back unchanged, never dropped. Without a config directory the values last for the session. Model polls the file (SettingsPoll) so a value another process set (the CLI) reaches a running TUI.
func (*Settings) Declared ¶ added in v0.2.0
Declared lists the declared settings in declaration order.
func (*Settings) Get ¶ added in v0.2.0
func (s *Settings) Get(name string) (SettingValue, error)
Get is one setting with its value.
func (*Settings) List ¶ added in v0.2.0
func (s *Settings) List() []SettingValue
List is every declared setting with its value, in declaration order.
func (*Settings) Observe ¶ added in v0.2.0
Observe calls fn with a setting's new value whenever it changes (Set, Reset, or a reload that read another value); name "" observes every setting. Observers run on the caller's goroutine, the update loop.
func (*Settings) Problems ¶ added in v0.2.0
Problems are the problems the last read of settings.json found.
func (*Settings) Reload ¶ added in v0.2.0
Reload reads settings.json again and tells the observers of every value that changed. It returns the problems the file has.
func (*Settings) ReloadIfChanged ¶ added in v0.2.0
ReloadIfChanged reloads when the file changed on disk since it was last read or written (another process set a value); it reports whether it did.
func (*Settings) Reset ¶ added in v0.2.0
Reset removes a setting's value from settings.json, so it reads its default again.
func (*Settings) Set ¶ added in v0.2.0
Set validates value against the setting's type and enum (a string is parsed: "3", "true", "400ms"), writes settings.json and tells the observers. A value that does not validate changes nothing.
func (*Settings) String ¶ added in v0.2.0
String is a string setting's value ("" when undeclared or another type).
type SettingsPollMsg ¶ added in v0.2.0
type SettingsPollMsg struct{}
SettingsPollMsg is the Model's settings.json check.
type SplitSide ¶ added in v0.2.0
type SplitSide int
SplitSide names the panel of a split that draws focused.
type StopBindings ¶ added in v0.2.0
type StopBindings struct {
Page string `json:"page,omitempty"`
Stop string `json:"stop"`
Focus string `json:"focus"`
Mode string `json:"mode"`
Bindings []Binding `json:"bindings"`
}
StopBindings is one entry of bindings.stops: the rows a focus stop answers to (ListBindings at Focus in Mode), with the page it sits on. Stop is the stop instance, Focus where a jump to it lands (its remembered child, a list's selected row), Mode the mode the focus has there. The last entry is app itself (Stop and Focus "app").
type Styles ¶
type Styles struct {
Title lipgloss.Style
Subtitle lipgloss.Style
Muted lipgloss.Style
Accent lipgloss.Style
Error lipgloss.Style
Panel lipgloss.Style
FocusedPanel lipgloss.Style
Tab lipgloss.Style
ActiveTab lipgloss.Style
Badge lipgloss.Style
Padding int
}
Styles is a render-time value; it does not retain mutable appearance state.
func NewStyles ¶
func NewStyles(a Appearance) Styles
NewStyles keeps layout and focus cues usable without terminal color support. Theme names the scheme (a built-in theme or one of Schemes; an unknown name draws adaptive); mono and NO_COLOR draw no colour at all.
type Suggestion ¶ added in v0.5.0
type Suggestion struct {
Text string `json:"text"`
Label string `json:"label,omitempty"`
Detail string `json:"detail,omitempty"`
}
Suggestion is one completion a search offers. Text replaces the token after its trigger; Label is what the list shows ("" shows Text); Detail is drawn muted after the label.
type Terminal ¶
type Terminal struct {
// contains filtered or unexported fields
}
Terminal is the component of a terminal instance: it holds the last frame the stream delivered, renders it into the area a page gives it and reports the pane's cursor. Frames arrive through the delivery contract as Completions owned by the instance in the "read" slot, one read at a time, so a frame that arrives after Close, or after a newer read started, is stale and dropped before it reaches the component.
func (*Terminal) Close ¶
func (t *Terminal) Close()
Close stops reading and releases a TerminalReleaser stream, once; the runtime has already cancelled the read in flight.
func (*Terminal) Frame ¶
func (t *Terminal) Frame() TerminalFrame
Frame is the last frame the stream delivered.
func (*Terminal) HandleMessage ¶
HandleMessage stores a frame delivered to this terminal and schedules the next read. A stream error ends reading; a cancelled read is silent.
func (*Terminal) PendingCommand ¶
PendingCommand is nil: reads are scheduled through Runtime.Start.
func (*Terminal) ViewBlock ¶
ViewBlock renders the pane's cells into exactly width x height cells and reports the pane's cursor; compose the cursor only while the terminal is focused. The stream is told the area the first time it is seen and whenever it changes, so the pane is sized to the detail area it fills.
type TerminalFrame ¶
type TerminalFrame struct {
Lines []string `json:"lines"`
Cursor Pos `json:"cursor"`
Shape string `json:"shape,omitempty"`
Hidden bool `json:"hidden,omitempty"`
}
TerminalFrame is one rendering of a pane: its rows of trusted ANSI, the cursor cell, the cursor shape the pane reports ("block", "bar", "underline"; "" for the default block) and whether the cursor is hidden.
type TerminalReleaser ¶
type TerminalReleaser interface {
Release() error
}
TerminalReleaser is a TerminalStream that holds something to give back when its terminal closes: a daemon size lease, a connection. Terminal.Close calls Release once, so Pop, SetItems, RemoveInstance and a CloseOnDetach detach all release the stream; its error is kept as the terminal's Err.
type TerminalStream ¶
type TerminalStream interface {
Next(ctx context.Context) (TerminalFrame, error)
Send(keys ...string) error
Paste(text string) error
Resize(cols, rows int) error
}
TerminalStream is the application's connection to one pane: a daemon client, never a PTY the framework owns. The framework reads frames from it, forwards keys and pasted text to it and tells it the pane's size. Next blocks until the pane changes and returns its next frame; it returns ctx's error when the terminal instance closes or newer work supersedes the read. Keys are named as bindings spell them ("ctrl+a", "d", "esc").
type Ticket ¶
type Ticket struct {
Owner string `json:"owner"`
Job uint64 `json:"job"`
Slot string `json:"slot,omitempty"`
}
Ticket names one job: the instance that owns it, its runtime-wide id and the slot it was started in. Slot is "" for a job that accumulates (every completion is delivered, in finish order) and a name for a job that replaces: a newer job in the same slot on the same owner (or, with ReplacingAt, on the same scope) drops the older. A completion is stale, and dropped, only when its job was cancelled by a newer job in its slot or by its owner closing.
type Tree ¶
type Tree struct {
// OnChange makes the tree editable and receives each change as it is
// made; an error keeps the change on screen, marks the row and retries
// it before the next change.
OnChange func(TreeChange) error
// NewID names a new node (default "<tree>-n<seq>").
NewID func() string
// RowNoun is the noun of nodes the tree adds (default TreeRowNoun).
RowNoun string
// Debounce is the pause in typing before a line is written.
Debounce time.Duration
// contains filtered or unexported fields
}
Tree is a list whose rows are nested nodes: expand and collapse, the same motions as a list (it is one: rows spill to the neighbouring stops in drawing order), the one highlighted row, columns like a table. Given OnChange it is an outline editor: every structural edit is written at once, typing within a line is written after a pause (Debounce) and when the line is left, undo and redo are changes too, and esc never discards.
The tree is an instance of the outline noun with a list child (id+"/list") holding the visible rows; editing adds an input (id+"/line", noun outline-line) under the tree while a line is edited. (The nouns are "outline", not "tree", so palette prefixes such as "tr" stay unique in apps.)
func (*Tree) Block ¶
Block renders the rows as the list does; while a line is open its row is the input, with the terminal cursor in it.
func (*Tree) CollapseAll ¶
CollapseAll collapses every node that has children.
func (*Tree) DebounceCurrent ¶
func (t *Tree) DebounceCurrent(tick TreeDebounceMsg) bool
DebounceCurrent reports whether a pause timer is for the line's latest change (an older timer writes nothing).
func (*Tree) Failure ¶
Failure is the last background failure, cleared when read: Deliver returns it for the message the tree handled, so it reaches the status.
func (*Tree) FocusTarget ¶
FocusTarget is where a jump to the tree lands: its selected row.
func (*Tree) HandleMessage ¶
HandleMessage writes the open line when its pause timer is the latest.
func (*Tree) PendingCommand ¶
PendingCommand notices typing in the open line and sets the pause timer; a line whose input lost the focus is closed (and written).
func (*Tree) Record ¶ added in v0.1.1
func (t *Tree) Record(a TreeAction) error
Record puts an application change on the undo stack: an open line is sealed first (so its typing undoes after the action, not before), and the redo stack is cleared, as for any new change.
func (*Tree) SetCollapsed ¶
SetCollapsed collapses or expands one node.
type TreeAction ¶ added in v0.1.1
type TreeAction struct {
ID string
Label string // what the change is ("done n1"), for logs
Undo func() error
Redo func() error
}
TreeAction is an application change that goes on an outline's undo stack in order with the tree's own edits: a change the application keeps outside the tree's nodes, such as a task's status. u runs Undo and ctrl+r runs Redo; each is written by the application like any change. ID is the node selected after either runs ("" keeps the selection).
type TreeChange ¶
type TreeChange struct {
Op string `json:"op"`
ID string `json:"id"`
Parent string `json:"parent,omitempty"`
Index int `json:"index"`
Text string `json:"text,omitempty"`
}
TreeChange is one committed edit of an outline: add, rename, move or delete. Index is the node's position among its parent's children after the change. The application writes each one to its store as it comes (Tree.OnChange); undo is a further change, never a discard.
func (TreeChange) String ¶
func (c TreeChange) String() string
String reads a change in one line: "add n1 under root at 1: text", "rename n1: text", "move n1 under a at 0", "delete n1".
type TreeDebounceMsg ¶
TreeDebounceMsg is the timer a pause in typing sets off: when Seq is still the line's latest change, the line is written.
type TreeNode ¶
type TreeNode struct {
ID string `json:"id"`
Parent string `json:"parent,omitempty"`
Label string `json:"label"`
Noun string `json:"noun,omitempty"`
Data any `json:"data,omitempty"`
Cells []string `json:"cells,omitempty"`
}
TreeNode is one node of a tree. Nodes are flat and in display order: a node's children follow it, and Parent "" is a root. Noun is the row's noun (default TreeRowNoun); Data and Cells are as on ListItem.
type UI ¶ added in v0.4.0
type UI struct {
// contains filtered or unexported fields
}
UI is the component that routes handler messages to the host's sink. It is one instance under app (Runtime.UI), never a Runtime field. With no sink it discards, except that until the first sink attaches it keeps the last 32 messages (the startup ring) and replays them, in order, into that sink; after the first attach nothing is kept, so memory stays bounded whether or not a sink ever attaches.
Like the rest of Runtime it is called from the update loop; work off the loop posts from its Then (which gets a Ctx).
func (*UI) Attach ¶ added in v0.4.0
Attach makes s the sink every later message goes to and returns the one it replaces (nil for none). The first attach of the runtime's life replays the startup ring into s and drops it. Attach(nil) detaches: messages are discarded from then on.
func (*UI) ClearNotice ¶ added in v0.4.0
ClearNotice takes back the notice Notify returned id for.
func (*UI) Close ¶ added in v0.4.0
func (u *UI) Close()
Close keeps everything: the UI lives as long as the runtime.
func (*UI) HandleMessage ¶ added in v0.4.0
HandleMessage: the UI does no off-loop work.
func (*UI) Notify ¶ added in v0.4.0
Notify posts a persistent notice and returns its id for ClearNotice.
func (*UI) PendingCommand ¶ added in v0.4.0
PendingCommand: nothing is ever scheduled.
type UIMessage ¶ added in v0.4.0
type UIMessage struct {
Kind string `json:"kind"`
ID NoticeID `json:"id,omitempty"`
Text string `json:"text,omitempty"`
}
UIMessage is one thing a handler told the user: a notice (Kind notice, ID and Text), the clearing of one (Kind clear, ID) or the status line (Kind status, Text; "" clears it). The startup ring, a call's Response.Messages and RecordingSink hold these.
type UISink ¶ added in v0.4.0
type UISink interface {
// Notify shows a persistent notice until ClearNotice(id) or the host
// clears it.
Notify(id NoticeID, text string)
// ClearNotice takes back a notice; an unknown id is ignored.
ClearNotice(id NoticeID)
// Status replaces the one-line status; "" clears it.
Status(text string)
}
UISink is how a host shows what handlers tell the user: the Model puts notices in the footer and the status in the status line, the CLI shell prints them on stderr, a test records them. Handlers never reach the sink: they post through Ctx (ctx.Notify, ctx.ClearNotice, ctx.Status) or Runtime.UI, and the host decides how it looks.
Source Files
¶
- actions.go
- bindings.go
- block.go
- chooser.go
- cli.go
- completion.go
- completion_list.go
- config_export.go
- configuration.go
- confirm.go
- delivery.go
- detail.go
- editing.go
- editor.go
- editor_block.go
- editor_keys.go
- focus.go
- help.go
- history.go
- history_store.go
- input.go
- instance.go
- layout.go
- list.go
- list_delta.go
- list_filter.go
- list_motions.go
- macros.go
- model.go
- noun.go
- pages.go
- palette.go
- palette_choices.go
- palette_editing.go
- palette_nouns.go
- palette_parse.go
- palette_results.go
- panes.go
- params.go
- picker.go
- picker_preview.go
- picker_search.go
- picker_stats.go
- picker_view.go
- query.go
- record_editor.go
- registers.go
- resolve.go
- runtime.go
- scheme.go
- settings.go
- settings_view.go
- surface.go
- table.go
- table_columns.go
- terminal.go
- theme.go
- ticker.go
- transport.go
- tree.go
- ui.go
- yank_api.go
- yank_history.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package cli is the generic command line of an ochazuke application: the NOUN VERB shell over a runtime (Shell), the oden mount that makes every noun a command of the bin (Mount) and the catalog answer that describes the runtime as JSON (Catalog).
|
Package cli is the generic command line of an ochazuke application: the NOUN VERB shell over a runtime (Shell), the oden mount that makes every noun a command of the bin (Mount) and the catalog answer that describes the runtime as JSON (Catalog). |
|
cmd
|
|
|
charmrefs
command
Command charmrefs writes docs/CHARM-INVENTORY.md: for every project listed in docs/charm-refs.txt, the Charm (charm.land, charmbracelet) modules it depends on, how many files import each package, its entry points, and its agent docs.
|
Command charmrefs writes docs/CHARM-INVENTORY.md: for every project listed in docs/charm-refs.txt, the Charm (charm.land, charmbracelet) modules it depends on, how many files import each package, its entry points, and its agent docs. |
|
codemap
command
Command codemap writes docs/CODEMAP.md: one entry per Go file in the root package and in each importable subpackage (cli/, grid/), listing what each file declares and which sibling files it leans on.
|
Command codemap writes docs/CODEMAP.md: one entry per Go file in the root package and in each importable subpackage (cli/, grid/), listing what each file declares and which sibling files it leans on. |
|
docgen
command
Command docgen generates the offline reference linked from the architecture guide.
|
Command docgen generates the offline reference linked from the architecture guide. |
|
o-story
command
Command o-story is a storybook-style sandbox for ochazuke: a story is a JSON file describing a synthetic page, a script of events and what must hold afterwards.
|
Command o-story is a storybook-style sandbox for ochazuke: a story is a JSON file describing a synthetic page, a script of events and what must hold afterwards. |
|
ochazuke
command
|
|
|
renamekeys
command
Command renamekeys rewrites operation keys from one spelling to the other across the repository's .go, .json, .md and .html files.
|
Command renamekeys rewrites operation keys from one spelling to the other across the repository's .go, .json, .md and .html files. |
|
examples
|
|
|
core
command
|
|
|
csv
command
Package main is the CSV reader and editor from docs/CSV-APP-SKETCH.md: the framework's lightweight second consumer.
|
Package main is the CSV reader and editor from docs/CSV-APP-SKETCH.md: the framework's lightweight second consumer. |
|
demo
Package demo is the runnable example behind `ochazuke run`: seven pages, nested draft modals, the picker and the keyboard guide, built only from the public API.
|
Package demo is the runnable example behind `ochazuke run`: seven pages, nested draft modals, the picker and the keyboard guide, built only from the public API. |
|
full-project
command
|
|
|
hello
command
Command hello is an oden tool whose TUI is ochazuke's Commands page: with no word it opens the page (cli.TUI as oden's Default), listing its inline commands and every hello-<name> on PATH.
|
Command hello is an oden tool whose TUI is ochazuke's Commands page: with no word it opens the page (cli.TUI as oden's Default), listing its inline commands and every hello-<name> on PATH. |
|
Package grid is a two-dimensional cursor component for ochazuke: a header and rows the application owns, a cursor and viewport in two axes, a visual selection in three shapes plus marks, and one instance per focused cell, parented to a row instance, parented to a column instance, parented to the grid, so the cell, row and column nouns all sit on the focus stack.
|
Package grid is a two-dimensional cursor component for ochazuke: a header and rows the application owns, a cursor and viewport in two axes, a visual selection in three shapes plus marks, and one instance per focused cell, parented to a row instance, parented to a column instance, parented to the grid, so the cell, row and column nouns all sit on the focus stack. |
|
internal
|
|
|
keytest
Package keytest drives Bubble Tea models from tests using the key names that bindings use ("ctrl+c", "esc", "enter", "shift+tab", "alt+b", "space", "x").
|
Package keytest drives Bubble Tea models from tests using the key names that bindings use ("ctrl+c", "esc", "enter", "shift+tab", "alt+b", "space", "x"). |
|
Package markdown renders Markdown with Charm's Glamour and edits its task lists in place.
|
Package markdown renders Markdown with Charm's Glamour and edits its task lists in place. |
|
Package story is o-story's engine: a story is data (a synthetic page, a script of events, an expectation), Build turns it into a live runtime and model, a Driver plays events against it headless, and a Recorder turns the messages of a live session into the same events.
|
Package story is o-story's engine: a story is data (a synthetic page, a script of events, an expectation), Build turns it into a live runtime and model, a Driver plays events against it headless, and a Recorder turns the messages of a live session into the same events. |
