present

package
v0.16.0 Latest Latest
Warning

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

Go to latest
Published: Aug 25, 2026 License: Apache-2.0 Imports: 1 Imported by: 0

Documentation

Overview

Package present decides when a frame is drawn.

A terminal UI has more reasons to redraw than it has frames worth drawing: a streamed token, a spinner tick, a scroll wheel and a resize can all land inside one refresh interval. The presenter turns that stream of reasons into a paced sequence of draws, and refuses to draw at all while the terminal is still swallowing the last frame.

It is state, not machinery: it owns no goroutine, opens nothing, and writes nothing. Its driver asks what to do and it answers. That is what makes the pacing rules testable without a terminal.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Presenter

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

Presenter tracks whether a frame is owed, whether one is still in flight, and when the next one may go.

Not safe for concurrent use. It belongs to the driver that draws, and the whole point of a single owner is that "is a frame in flight" has one answer.

func (*Presenter) DueAt

func (p *Presenter) DueAt() (time.Time, bool)

DueAt is when a turned-away throttled request becomes allowed, if one is pending.

A driver that parks until something happens has to know to wake then, or the last update of a burst is never drawn.

func (*Presenter) Present

func (p *Presenter) Present(now time.Time, draw func(full bool) (uint64, error)) (bool, error)

Present draws the owed frame, if one is owed and the terminal is not still busy with the last, and reports whether it drew.

draw is given whether this frame must be a repaint from scratch, and returns the writer sequence its bytes were queued under — zero when it queued nothing. A frame that reached the writer becomes the one being waited for, so the next request coalesces instead of piling a second frame behind the first.

A failed draw does not satisfy the request. Its full-repaint requirement and due time remain pending so a caller that can recover may try again; a caller for which frame construction is fatal can return the error without the presenter recording a frame that never existed.

func (*Presenter) Request

func (p *Presenter) Request()

Request asks for a frame, now. It never draws: it records that one is owed, and cancels any wait a throttled request had put in the way.

func (*Presenter) RequestBy

func (p *Presenter) RequestBy(now time.Time, minInterval time.Duration) bool

RequestBy asks for a frame no sooner than minInterval after the last one, and reports whether it may be drawn straight away.

It is for sources that fire faster than a terminal can usefully be redrawn — a token stream, a scroll wheel held down. A request too soon still owes a frame: the interval decides when it is drawn, not whether. It arms Presenter.DueAt so a driver that parks knows when to wake, and Presenter.Present holds the frame until then.

func (*Presenter) RequestFull

func (p *Presenter) RequestFull()

RequestFull asks for a frame drawn from scratch, for when what the terminal is showing can no longer be trusted.

func (*Presenter) Wrote

func (p *Presenter) Wrote(seq uint64)

Wrote reports that the writer has finished with everything up to seq. The frame being waited for is released once seq reaches it.

Jump to

Keyboard shortcuts

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