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 ¶
- type Model
- func (m *Model) Actions() taction.Set
- func (m *Model) Help() []key.Binding
- func (m *Model) HelpSections() []help.Section
- func (m *Model) Init() tea.Cmd
- func (m *Model) IsCapturingKeys() bool
- func (m *Model) Layout() layout.Node
- func (m *Model) OnEnter(any) tea.Cmd
- func (m *Model) SetTheme(t theme.Theme)
- func (m *Model) Title() string
- func (m *Model) Update(msg tea.Msg) (tscreen.Screen, tea.Cmd)
- type Multi
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
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 ¶
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
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 ¶
Init focuses the initial component so the first frame already shows the highlighted border on the focused pane.
func (*Model) IsCapturingKeys ¶
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 ¶
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 ¶
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.
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.