Documentation
¶
Overview ¶
Package spin is the branded spinner engine of spec section 10.2.5: the gradient label that wipes in column by column while kb waits on a network round trip or a model inference.
It is the branded half of the two-tier split of spec section 10.2.4. The plain half is bubbles' spinner.Dot on theme.Styles.Work.Label and needs no code here: a branded frame announces that the machine is thinking on your behalf and may be a while, so spending it on a local disk write devalues it.
The engine obeys the determinism contract of spec section 10.2.2 without exception. It reads no clock - the elapsed suffix arrives through a closure the surface builds from its own injected now - every frame is rendered once at construction and indexed afterwards, and every tick chain carries a generation so a restart cannot leave two tickers running.
Index ¶
- Constants
- func Elapsed(age time.Duration) string
- type Engine
- func (e *Engine) Configure(styles *theme.Styles, settings Settings)
- func (e Engine) Frame(step int) string
- func (e Engine) Gen() uint32
- func (e Engine) Mounted() bool
- func (e Engine) Seed() uint64
- func (e *Engine) Start() tea.Cmd
- func (e *Engine) Step(msg StepMsg, busy bool) tea.Cmd
- func (e *Engine) Stop()
- func (e Engine) View() string
- func (e Engine) Width() int
- type Settings
- type StepMsg
Constants ¶
const ( EllipsisStates = 4 // "", ".", "..", "..." EllipsisField = 3 // columns the ellipsis always occupies, space padded SuffixField = 6 // columns reserved for " 1m02s" MaxLabelW = 48 // longest branded label; longer is truncated MaxEngines = 1 // branded engines that may tick at once (section 10.2.6) // BirthGlyph is the pre-birth cell, drawn in theme.Styles.Work.Birth. BirthGlyph = "." // ScrambleRunes is the 36-rune alphabet a cell flashes through between its // birth step and its own rune. ASCII only, one column each. ScrambleRunes = "abcdefghijklmnopqrstuvwxyz0123456789" )
The engine vocabulary of spec section 10.2.5. Every duration and tick count the engine reads is a theme.Timing token instead; nothing here is a clock.
const ( SeedEditorDraft uint64 = 1 // card editor, AI draft SeedDriftCheck uint64 = 2 // card detail, drift check SeedAdrPropose uint64 = 3 // ADR split, propose stories SeedImportFetch uint64 = 4 // issue import, source list and preview fetch SeedSettingsTest uint64 = 5 // settings, test connection )
The per-surface birth seeds of spec section 10.2.4. Each is a named constant rather than a runtime instance id, which is what makes a birth schedule a fixed golden instead of a seeded reproduction: two surfaces stagger differently, and the same surface staggers identically in every process.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
Engine is one branded spinner. The zero value renders the empty string and arms nothing, which is the settled state of a spinner: a surface that is not busy shows its ordinary static text with no engine output in it at all. That is why the existing goldens need no edits (spec section 10.2.2, point 2).
At most MaxEngines of these tick at once and it belongs to the front-most open surface in the spec section 4 z-order; see Stop and Start.
func (*Engine) Configure ¶
Configure resolves the styles and settings of one mount, rebuilding the frame cache when - and only when - the settings hash or the theme instance changed. A rebuild happens on a theme rebuild, on a resize that changes the label width, and on a new operation with a different label; nothing else.
The cache is per engine. Spec section 6.2 forbids package-level mutable style state and a shared frame map is close enough to it to refuse, which the MaxEngines ceiling makes free anyway.
func (Engine) Frame ¶
Frame is the assembled row at an absolute step count s, ticks since the chain started. It is the whole render path, so a test asserts a fixed string against it without running a clock.
func (Engine) Gen ¶
Gen is the current generation, for a caller that has to build a StepMsg by hand - a test stepping the chain synchronously.
func (Engine) Mounted ¶
Mounted reports whether this engine is ticking. The root counts these across the open z-order stack against MaxEngines.
func (*Engine) Start ¶
Start mounts the engine at step zero and opens a fresh tick chain. The generation bump is what kills any chain still in flight.
Below FidelityFull the wipe is never armed: it is a class-B effect (spec section 10.7.6), its information lives in the color difference between born and unborn cells, and a flattened wipe is a flash of punctuation. The engine mounts settled instead, where the ellipsis and the elapsed suffix - carried by glyph and text, not by hue - go on running unchanged.
func (*Engine) Step ¶
Step advances the chain by one tick. busy is the surface's own gate, read on every tick rather than mirrored into an animating flag a code path can forget to clear (spec section 10.2.3).
A nil command is returned - and the chain therefore terminates - for a stale generation, a foreign seed, an unmounted engine, or a settled gate.
func (*Engine) Stop ¶
func (e *Engine) Stop()
Stop clears the mount and bumps the generation, so a tick still in flight is dropped on arrival. The backgrounded surface of spec section 10.2.6 calls this: its operation keeps running, only the animation stops.
func (Engine) View ¶
View is the assembled row at the current step, or the empty string while the engine is unmounted or still inside the birth delay. A surface that gets "" renders its ordinary static busy label instead.
The run carries no background; the caller lays it onto its own shade tier with theme.Styles.SurfaceRun.
type Settings ¶
type Settings struct {
Label string // the branded label, already truncated by Fit
Width int // resolved label width in columns, set by Fit
Seed uint64 // the per-surface constant above
Scramble bool // false is crush's NoScramble: the wipe without the flash
Suffix func() string // elapsed text, built by the surface from its injected now
}
Settings is the hashed description of one mount. These are all of its fields.
Suffix is deliberately outside the hash: a func has no stable identity, and the suffix is appended live to a cached frame rather than baked into one.
func (Settings) Fit ¶
Fit truncates Label onto the row that avail columns can hold and resolves Width. The label takes min(MaxLabelW, avail - EllipsisField - SuffixField) columns, because the ellipsis and the elapsed fields are reserved for the life of the mount whether or not they are showing (spec section 10.4.4).
type StepMsg ¶
StepMsg advances one engine by one tick of the one clock.
Seed identifies the engine because a single Update tree routes ticks for more than one of them - the front overlay's, and during the background handoff of spec section 10.2.6 a backgrounded surface's last outstanding tick. Gen is the double-chain fix of spec section 10.2.5: Start and Stop both bump it, so a tick issued by a superseded chain is dropped on arrival instead of doubling the frame rate.