Documentation
¶
Overview ¶
Package tui is the terminal-I/O layer around github.com/go-widgets/painter's CellPainter. It renders a widget tree into an ANSI cell stream sized to the current terminal, so the same widget code that produces pixels for a WUI or GUI back-end also produces text for a terminal — no widget changes required.
The package is deliberately minimal: no raw mode, no keyboard event loop, no alt-screen management. It ships a "snapshot" model — render one frame to a writer and return — that composes cleanly with either a caller-managed event loop or a CLI that prints once and exits. Higher-level facilities (an [App] runner with input, resize, and cleanup handling) live in a follow-up cycle.
Sizing follows the caller's preference:
- RenderOnceSized takes explicit (cols, rows) — the reliable form used by tests, size-aware callers, and headless renderers.
- RenderOnce queries the size from environment variables (EnvSize) and falls back to [DefaultCols]x[DefaultRows] when the environment does not report a size. This keeps the package stdlib-only — no ioctl, no cgo, no dependency on golang.org/x/term.
Both variants write a self-contained ANSI stream to the caller's writer via painter.CellPainter.WriteANSI; the caller is responsible for the surrounding terminal state (raw mode, alt screen, cursor visibility) if any.
Index ¶
- Constants
- Variables
- func EnvSize() (cols, rows int, ok bool)
- func RenderOnce(w io.Writer, widgets []painter.Widget, theme *painter.Theme) error
- func RenderOnceSized(w io.Writer, cols, rows int, widgets []painter.Widget, theme *painter.Theme) error
- func RenderToolkit(w io.Writer, widgets []toolkit.Widget, theme *toolkit.Theme) error
- func RenderToolkitSized(w io.Writer, cols, rows int, widgets []toolkit.Widget, theme *toolkit.Theme) error
- func SizeOrDefault() (cols, rows int)
- type InputParser
- type TTY
Constants ¶
const ( DefaultCols = 80 DefaultRows = 24 )
DefaultCols and DefaultRows are the terminal dimensions used when neither the environment nor the caller supplies a size — the classic VT100 defaults every terminal emulator honours as a floor.
Variables ¶
var ErrNotSupported = errors.New("tui: interactive TTY setup is Unix-only in v0.3.0")
ErrNotSupported is returned by OpenTTY on platforms where the interactive TTY setup path is not implemented (Windows, Plan 9, WebAssembly). It is a package-level sentinel so callers can errors.Is against it to fall back to a non-interactive rendering path.
Functions ¶
func EnvSize ¶
EnvSize reads the terminal size from the COLUMNS and LINES environment variables. It returns (cols, rows, true) when both parse cleanly and hold positive integers; otherwise it returns (0, 0, false) and the caller should substitute defaults.
The env-vars-only strategy is a deliberate trade-off: it keeps the package stdlib-only (no TIOCGWINSZ ioctl per platform, no cgo, no golang.org/x/term dependency). Interactive shells that need dynamic sizes should export COLUMNS / LINES from their prompt hook, or pass an explicit size to RenderOnceSized.
func RenderOnce ¶
RenderOnce paints the widget tree into a fresh CellPainter sized to SizeOrDefault, fills the background with theme.Background, calls each widget's Draw, and writes the resulting ANSI stream to w. It is the snapshot form: no raw mode, no event loop; one frame then return.
The theme argument may be nil, in which case painter.LightTheme is used. This keeps CLI callers ergonomic (`tui.RenderOnce(os.Stdout, widgets, nil)`) without forcing them to import painter just to name the default theme.
func RenderOnceSized ¶
func RenderOnceSized(w io.Writer, cols, rows int, widgets []painter.Widget, theme *painter.Theme) error
RenderOnceSized is like RenderOnce but uses the explicit (cols, rows) dimensions instead of querying the environment. Cols and rows must both be positive; a non-positive value falls back to the corresponding default so callers cannot accidentally produce an empty render.
func RenderToolkit ¶ added in v0.2.0
RenderToolkit paints a toolkit.Widget tree into a fresh CellPainter sized to SizeOrDefault, fills the background with theme.Background, calls each widget's Draw, and writes the resulting ANSI stream to w.
It is the toolkit-widget counterpart of RenderOnce (which renders painter.Widget). The two exist side-by-side because toolkit.Theme carries fields (SurfaceAlt, OnBackground, Extra) that painter.Theme does not, so a toolkit widget cannot be rendered through RenderOnce without losing theme surface.
The theme argument may be nil, in which case toolkit.DefaultLight is used.
func RenderToolkitSized ¶ added in v0.2.0
func RenderToolkitSized(w io.Writer, cols, rows int, widgets []toolkit.Widget, theme *toolkit.Theme) error
RenderToolkitSized is like RenderToolkit but uses the explicit (cols, rows) dimensions instead of querying the environment. Cols and rows must both be positive; a non-positive value falls back to the corresponding default so callers cannot accidentally produce an empty render.
func SizeOrDefault ¶
func SizeOrDefault() (cols, rows int)
SizeOrDefault returns EnvSize when the environment reports a size, otherwise [DefaultCols]x[DefaultRows]. This is what RenderOnce consumes.
Types ¶
type InputParser ¶ added in v0.3.0
type InputParser struct {
// contains filtered or unexported fields
}
InputParser reads bytes from a terminal stdin stream and emits toolkit.Event values. A single call to InputParser.Feed may produce zero, one, or many events: typing "abc" yields three toolkit.EventChar events, pasting a control sequence like "\x1b[A" yields one arrow-up event but consumes three bytes.
The toolkit exposes toolkit.EventKeyDown for named-key presses (Enter, Tab, arrows, Escape, …) and toolkit.EventChar for printable characters — the parser routes accordingly.
The pending buffer holds the incomplete tail of the last Feed call: a lone ESC (0x1B) whose next byte has not arrived, an ESC [ … partial CSI sequence still waiting for its final byte (0x40..0x7E), or a partial UTF-8 rune (1–3 bytes of a multi-byte codepoint split across two Reads). It is consumed automatically on the next Feed call, or drained by InputParser.Flush on an input-idle deadline.
func NewInputParser ¶ added in v0.3.0
func NewInputParser() *InputParser
NewInputParser returns a fresh parser with an empty buffer.
func (*InputParser) Feed ¶ added in v0.3.0
func (p *InputParser) Feed(b []byte) []toolkit.Event
Feed hands b bytes to the parser and returns any events that completed as a result. Bytes belonging to an incomplete sequence (a lone ESC, a partial CSI, a partial UTF-8 rune) are buffered internally and consumed on the next Feed call.
The classic Escape-vs-CSI ambiguity is resolved as follows: a lone ESC at the end of the buffer is held pending; on the next Feed a leading '[' starts a CSI sequence, any other byte causes the held ESC to be emitted as "Escape" and the following byte is then processed as a fresh input. Callers waiting on an idle deadline flush the held ESC via InputParser.Flush.
func (*InputParser) Flush ¶ added in v0.3.0
func (p *InputParser) Flush() []toolkit.Event
Flush emits any pending ESC (or partial CSI) as an "Escape" event and clears the buffer. Callers invoke it on an input-idle deadline to resolve the Escape-vs-CSI ambiguity in favour of a plain Escape. A partial UTF-8 rune is discarded silently — its tail bytes would be indistinguishable from an unrelated new keystroke by the time an idle timeout fires.
type TTY ¶ added in v0.3.0
TTY is the abstraction the App runner uses to talk to a real terminal. On non-Unix platforms the concrete TTY implementation is not available and OpenTTY returns ErrNotSupported; the interface is exported so callers can still write portable code that consumes a TTY handed to them from a Unix host.
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
tui-catalogue
command
tui-catalogue renders the complete go-widgets/toolkit widget catalogue (every kind with a public constructor) into a scrollable cell-grid frame written to stdout as an ANSI stream.
|
tui-catalogue renders the complete go-widgets/toolkit widget catalogue (every kind with a public constructor) into a scrollable cell-grid frame written to stdout as an ANSI stream. |
|
tui-explorer
command
tui-explorer is the reference interactive demo for tui.App: a small k9s-style file-browser mockup composed from toolkit widgets.
|
tui-explorer is the reference interactive demo for tui.App: a small k9s-style file-browser mockup composed from toolkit widgets. |
|
tui-snapshot
command
tui-snapshot renders a sample widget tree to stdout as an ANSI stream.
|
tui-snapshot renders a sample widget tree to stdout as an ANSI stream. |