screen

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Oct 11, 2026 License: MIT Imports: 41 Imported by: 0

Documentation

Overview

Package screen wraps a built layout tree as a tuilib screen.Screen. One component holds keyboard focus at a time: tab / shift+tab cycle through the components in walk order. Only the focused component receives KeyMsgs; non-key messages fan out so spinner ticks reach every pane. IsCapturingKeys reflects only the focused component, so the surrounding app shell's q/ctrl+c suppression is scoped to "the thing the user is interacting with" rather than "anything in the layout."

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Model

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

Model is the config-driven screen. Construct with New (single-screen) or NewMulti (multi-screen, with push actions) and pass as the root to app.New.

func New

func New(s *cfg.Screen, components map[string]*cfg.Component, entries map[string]*cfg.Source, actions map[string]*cfg.Action, th theme.Theme) (*Model, error)

New builds a single-screen Model. Components are looked up by name in the layout tree. SubstituteScreen with an empty selection applies ${env.*} substitution to URLs / headers / argv / etc. — without this step, env tokens in single-screen configs would be passed through literally (multi-screen already substitutes via NewMulti).

params is nil here — there's no push site context in single-screen mode. Parameterized sources will be constructed with unresolved ${params.*} templates and will surface errors at fetch time. Use wrangl --param for now, or have your source declare defaults.

func NewMulti

func NewMulti(screenName string, multi *Multi, sel build.Selection, params map[string]string, th theme.Theme) (*Model, error)

NewMulti builds a Model from one screen in a multi-screen Config. The Multi context lets enter on a bound list/table push another screen via the screen.Stack. The selection captured at push time substitutes ${selection} tokens in the pushed screen's config — and in any data-source URL/headers/body referenced from that screen.

params carries the push-site `bind:` block's resolved values for the destination screen's parameterized sources. Pass nil on the initial multi-screen construction (no push has fired yet) and on screens whose binding has no Bind: map. Missing required params surface as a build error so pushAction can pop an alert instead of constructing a half-broken screen.

func (*Model) Actions added in v0.3.0

func (m *Model) Actions() taction.Set

Actions implements tuilib's action.Provider: the screen names its verbs and what they will act on, and the shell owns everything after the pick — the menu overlay, the confirm modal, the goroutine, cancellation, the console entry, the statusbar badge, the kill picker and the per-target exclusivity check.

Every binding appears, including ones that can't fire right now. Hiding an unavailable verb teaches the user it doesn't exist; showing it with a reason teaches them it doesn't apply yet, which is the true statement.

func (*Model) Help

func (m *Model) Help() []key.Binding

Help returns the bindings the focused component currently exposes, plus the `enter` verb if this screen has one.

Flat, because that is what the statusbar strip wants. The key overlay takes HelpSections instead.

func (*Model) HelpSections added in v0.2.2

func (m *Model) HelpSections() []help.Section

HelpSections is the grouped form, for tuilib's key overlay (`?`).

Without it the shell wraps Help() in one unnamed group and titles it with the owner — which puts the screen's name over every binding it has, so "Pods" ends up as the heading above a table's scroll keys. Headings are supposed to name what the keys DO. The focused component already describes itself that way (Navigate / Scroll / Filter / Sort / Select / …); this adds the screen's own activation verb on top.

Only the focused component contributes, matching Help() — which is also why nothing here calls help.Qualify: a qualifier earns its noise only when more than one owner is on screen at once.

func (*Model) Init

func (m *Model) Init() tea.Cmd

Init focuses the initial component so the first frame already shows the highlighted border on the focused pane.

func (*Model) IsCapturingKeys

func (m *Model) IsCapturingKeys() bool

IsCapturingKeys reflects whether the *focused* component is engaging keystrokes (filter typing). Also true while any modal is showing so q/t/esc-pop are routed to the modal, not the app shell.

func (*Model) Layout

func (m *Model) Layout() layout.Node

Layout returns the live layout.Node tree built from the YAML config. When a modal is active it overlays a centered dialog on top of the body via ZStack — base still renders behind so the user sees what they're acting on. Precedence (only one can be up at a time in practice): confirm > form.

There is deliberately no error modal. Failures — action dispatch and initial fetch alike — go to the app-wide output console instead, which keeps them re-readable rather than dismissed-and-gone, and never blocks the UI. The statusbar's persistent unread badge is what makes that discoverable; see cmd/tui-builder's OutputKey.

func (*Model) OnEnter

func (m *Model) OnEnter(any) tea.Cmd

OnEnter fires each time the screen becomes the active top of the stack. On the first activation it kicks off one fetch per bound data source — and for sources that implement ds.StreamingSource, opens the subscription and starts pumping events into the bound logview. Subsequent activations (pop-back) reuse cached data and let polling handle refreshes.

func (*Model) SetTheme

func (m *Model) SetTheme(t theme.Theme)

SetTheme rebuilds each component against the new palette; each one carries its data and view state across via State / Restore.

func (*Model) Title

func (m *Model) Title() string

Title satisfies screen.Screen.

func (*Model) Update

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

Update is the stack's entry point: it drops messages another screen asked for, unwraps this screen's own, and stamps whatever the screen asks for next.

type Multi

type Multi struct {
	Screens    map[string]*cfg.Screen
	Components map[string]*cfg.Component
	Sources    map[string]*cfg.Source
	// Actions is the config-wide action registry every screen's
	// bindings resolve against. Post-hoist it holds inline declarations
	// too.
	Actions map[string]*cfg.Action
}

Multi is the shared context for a multi-screen app: every named screen, the top-level components map, and the unified data sources map. Passed once to every Model so any screen can build + push its push-action targets, and so pushed screens get the same data layer.

Jump to

Keyboard shortcuts

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