Documentation
¶
Overview ¶
Package ansi provides ANSI escape code generation for terminal output.
Package goli provides the reactive TUI application lifecycle.
Package goli provides buffer implementations for terminal rendering.
Package cell provides the fundamental Cell type representing a terminal "pixel". Each Cell holds a character and its styling attributes.
Package goli provides the diff engine for comparing cell buffers.
Package goli provides text input handling for terminal UI.
Package goli provides intrinsic element handlers for box and text.
Package goli provides focus management for terminal UI components.
Package goli provides the flexbox layout engine for terminal UI.
Package goli provides intrinsic element registration.
Package goli provides buffer rendering functions.
Package goli provides the main rendering orchestrator for terminal UI.
Package goli provides a select primitive for list selection.
Package term provides terminal handling utilities.
Package goli provides VNode helper functions.
Index ¶
- Constants
- Variables
- func ClearScreen() string
- func CollectTextContent(node gox.VNode) string
- func ColorToAnsi(color Color, rgb *RGB, isFg bool) string
- func CreateTextNode(text string) gox.VNode
- func Expand(v gox.VNode) gox.VNode
- func FilterAbsoluteChildren(node gox.VNode) []gox.VNode
- func FilterChildren(node gox.VNode, typeStr string) []gox.VNode
- func FilterRelativeChildren(node gox.VNode) []gox.VNode
- func FormatMessage(msg LogMessage) string
- func GetBoolProp(props gox.Props, key string, defaultVal bool) bool
- func GetIntProp(props gox.Props, key string, defaultVal int) int
- func GetSize(fd int) (width, height int, err error)
- func GetTextContent(v gox.VNode) (string, bool)
- func GroupChangesByRow(changes []CellChange) map[int][]CellChange
- func HandleKey(key string) bool
- func HasIntrinsicHandler(name string) bool
- func HideCursor() string
- func IsInClip(x, y int, clip *ClipRegion) bool
- func IsTerminal(fd int) bool
- func IsTextNode(v gox.VNode) bool
- func MeasureNode(node gox.VNode) (width, height int)
- func MoveCursor(x, y int) string
- func Register(f Focusable)
- func RegisterIntrinsic(name string, handler *IntrinsicHandler)
- func RenderInputToBuffer(box *LayoutBox, buf *CellBuffer, clip *ClipRegion)
- func RenderInputToLogicalBuffer(box *LayoutBox, buf *LogicalBuffer, clip *ClipRegion)
- func RenderSelectToBuffer(box *LayoutBox, buf *CellBuffer, clip *ClipRegion)
- func RenderSelectToLogicalBuffer(box *LayoutBox, buf *LogicalBuffer, clip *ClipRegion)
- func RenderToBuffer(box *LayoutBox, buf *CellBuffer, clip *ClipRegion)
- func RenderToLogicalBuffer(box *LayoutBox, buf *LogicalBuffer, clip *ClipRegion)
- func RequestBlur(f Focusable)
- func RequestFocus(f Focusable)
- func Restore(fd int, state *State) error
- func Run(appFn func() gox.VNode, opts RunOptions)
- func RunToAnsi(run CellRun, sb *strings.Builder)
- func RuneWidth(s string) int
- func RunsToAnsi(runs []CellRun) string
- func RunsToAnsiBuilder(runs []CellRun, sb *strings.Builder)
- func ShowCursor() string
- func Stdin() int
- func Stdout() int
- func StyleToAnsi(style Style, sb *strings.Builder)
- func TypeString(v gox.VNode) (string, bool)
- func Unregister(f Focusable)
- func WrapText(text string, maxWidth int) []string
- type Align
- type App
- type BorderChars
- type BorderStyle
- type Cell
- type CellBuffer
- func (b *CellBuffer) Clear()
- func (b *CellBuffer) Get(x, y int) Cell
- func (b *CellBuffer) Height() int
- func (b *CellBuffer) Set(x, y int, c Cell)
- func (b *CellBuffer) SetChar(x, y int, char rune, style Style)
- func (b *CellBuffer) SetCharMerge(x, y int, char rune, style Style)
- func (b *CellBuffer) ToDebugString() string
- func (b *CellBuffer) Width() int
- func (b *CellBuffer) WriteString(x, y int, text string, style Style) int
- type CellChange
- type CellRun
- type ChildMeasurement
- type ClipRegion
- type Color
- type Direction
- type FocusManager
- func (m *FocusManager) Clear()
- func (m *FocusManager) Current() Focusable
- func (m *FocusManager) GetAll() []Focusable
- func (m *FocusManager) HandleKey(key string) bool
- func (m *FocusManager) Next()
- func (m *FocusManager) Prev()
- func (m *FocusManager) Register(f Focusable)
- func (m *FocusManager) RequestBlur(f Focusable)
- func (m *FocusManager) RequestFocus(f Focusable)
- func (m *FocusManager) Set(f Focusable)
- func (m *FocusManager) SetGlobalKeyHandler(handler func(key string) bool) func()
- func (m *FocusManager) Unregister(f Focusable)
- type Focusable
- type Input
- func (i *Input) Blur()
- func (i *Input) Clear()
- func (i *Input) CursorPos() int
- func (i *Input) DisplayValue() string
- func (i *Input) Dispose()
- func (i *Input) Focus()
- func (i *Input) Focused() bool
- func (i *Input) GetState() InputState
- func (i *Input) HandleKey(key string) bool
- func (i *Input) SetCursorPos(pos int)
- func (i *Input) SetFocused(f bool)
- func (i *Input) SetValue(value string)
- func (i *Input) ShowingPlaceholder() bool
- func (i *Input) Value() string
- type InputKeyHandler
- type InputOptions
- type InputState
- func InputDeletionHandler(key string, state InputState) *InputState
- func InputNavigationHandler(key string, state InputState) *InputState
- func InputNewlineHandler(key string, state InputState) *InputState
- func InputPrintableHandler(key string, state InputState) *InputState
- func InputShiftEnterHandler(key string, state InputState) *InputState
- type IntrinsicHandler
- type IntrinsicLayoutFunc
- type IntrinsicMeasureFunc
- type IntrinsicRenderFunc
- type IntrinsicRenderLogicalFunc
- type Justify
- type LayoutBox
- type LayoutContext
- type LayoutResult
- type LogCapture
- func (lc *LogCapture) Clear()
- func (lc *LogCapture) Debug(format string, args ...any)
- func (lc *LogCapture) Error(format string, args ...any)
- func (lc *LogCapture) Info(format string, args ...any)
- func (lc *LogCapture) LastMessages(n int) []LogMessage
- func (lc *LogCapture) Log(level LogLevel, format string, args ...any)
- func (lc *LogCapture) Messages() []LogMessage
- func (lc *LogCapture) OriginalStdout() *os.File
- func (lc *LogCapture) Start() error
- func (lc *LogCapture) Stop()
- func (lc *LogCapture) Warn(format string, args ...any)
- func (lc *LogCapture) WriteToOriginal(p []byte) (n int, err error)
- type LogLevel
- type LogMessage
- type LogicalBuffer
- func (b *LogicalBuffer) Clear()
- func (b *LogicalBuffer) ClearRow(y int)
- func (b *LogicalBuffer) Get(x, y int) Cell
- func (b *LogicalBuffer) GetRow(y int) *LogicalRow
- func (b *LogicalBuffer) Height() int
- func (b *LogicalBuffer) RowLength(y int) int
- func (b *LogicalBuffer) Set(x, y int, c Cell)
- func (b *LogicalBuffer) SetMerge(x, y int, c Cell)
- func (b *LogicalBuffer) ToVisualRows(terminalWidth int) VisualRows
- func (b *LogicalBuffer) WriteString(x, y int, text string, style Style)
- type LogicalRow
- type Options
- type Overflow
- type PipelineRenderer
- type Position
- type Props
- type RGB
- type Renderer
- type RendererInterface
- type RunOptions
- type Select
- func (s *Select[T]) Blur()
- func (s *Select[T]) ClearOptions()
- func (s *Select[T]) Dispose()
- func (s *Select[T]) Focus()
- func (s *Select[T]) Focused() bool
- func (s *Select[T]) HandleKey(key string) bool
- func (s *Select[T]) IsSelectedIndex(index int) bool
- func (s *Select[T]) Next()
- func (s *Select[T]) Prev()
- func (s *Select[T]) RegisterOption(index int, value T)
- func (s *Select[T]) RegisterOptionAny(index int, value any)
- func (s *Select[T]) SelectedIndex() int
- func (s *Select[T]) SetFocused(f bool)
- func (s *Select[T]) SetIndex(index int)
- func (s *Select[T]) SetOptionCount(count int)
- func (s *Select[T]) Value() T
- type SelectOptions
- type Spacing
- type State
- type Style
- type VNode
- type VisualRows
Constants ¶
const ( ESC = "\x1b" CSI = ESC + "[" )
const ( // Basic keys Space = " " Enter = "\r" EnterLF = "\n" Tab = "\t" Escape = "\x1b" // Editing keys Backspace = "\x7f" BackspaceCtrl = "\b" Delete = "\x1b[3~" Insert = "\x1b[2~" // Navigation keys Left = "\x1b[D" Right = "\x1b[C" Up = "\x1b[A" Down = "\x1b[B" Home = "\x1b[H" HomeAlt = "\x1b[1~" End = "\x1b[F" EndAlt = "\x1b[4~" PageUp = "\x1b[5~" PageDown = "\x1b[6~" // Shift combinations ShiftTab = "\x1b[Z" ShiftEnter = "\x1b[13;2u" ShiftUp = "\x1b[1;2A" ShiftDown = "\x1b[1;2B" ShiftLeft = "\x1b[1;2D" ShiftRight = "\x1b[1;2C" // Alt combinations AltBackspace = "\x1b\x7f" AltLeft = "\x1bb" AltLeftCSI = "\x1b[1;3D" AltRight = "\x1bf" AltRightCSI = "\x1b[1;3C" AltUp = "\x1b[1;3A" AltDown = "\x1b[1;3B" // Ctrl combinations (alphabetical) CtrlA = "\x01" CtrlB = "\x02" CtrlC = "\x03" CtrlD = "\x04" CtrlE = "\x05" CtrlF = "\x06" CtrlG = "\x07" CtrlH = "\x08" // Same as BackspaceCtrl CtrlI = "\x09" // Same as Tab CtrlJ = "\x0a" // Same as EnterLF CtrlK = "\x0b" CtrlL = "\x0c" CtrlM = "\x0d" // Same as Enter CtrlN = "\x0e" CtrlO = "\x0f" CtrlP = "\x10" CtrlQ = "\x11" CtrlR = "\x12" CtrlS = "\x13" CtrlT = "\x14" CtrlU = "\x15" CtrlV = "\x16" CtrlW = "\x17" CtrlX = "\x18" CtrlY = "\x19" CtrlZ = "\x1a" // Ctrl+Arrow combinations CtrlUp = "\x1b[1;5A" CtrlDown = "\x1b[1;5B" CtrlLeft = "\x1b[1;5D" CtrlRight = "\x1b[1;5C" // Function keys F1 = "\x1bOP" F2 = "\x1bOQ" F3 = "\x1bOR" F4 = "\x1bOS" F5 = "\x1b[15~" F6 = "\x1b[17~" F7 = "\x1b[18~" F8 = "\x1b[19~" F9 = "\x1b[20~" F10 = "\x1b[21~" F11 = "\x1b[23~" F12 = "\x1b[24~" )
Common terminal key codes.
const ( // Input mode flags ICRNL = 0x00000100 IXON = 0x00000400 BRKINT = 0x00000002 INPCK = 0x00000010 ISTRIP = 0x00000020 // Local mode flags ECHO = 0x00000008 ICANON = 0x00000002 ISIG = 0x00000001 IEXTEN = 0x00008000 // Output mode flags OPOST = 0x00000001 // Control mode flags CS8 = 0x00000030 )
const PipelineThreshold = 3000 // ~80x40 or 60x50
PipelineThreshold is the minimum cell count where the pipeline renderer helps. Below this, goroutine/channel overhead outweighs the parallelization benefit.
Variables ¶
var BorderCharSets = map[BorderStyle]BorderChars{ BorderSingle: { TopLeft: '┌', TopRight: '┐', BottomLeft: '└', BottomRight: '┘', Horizontal: '─', Vertical: '│', }, BorderDouble: { TopLeft: '╔', TopRight: '╗', BottomLeft: '╚', BottomRight: '╝', Horizontal: '═', Vertical: '║', }, BorderRounded: { TopLeft: '╭', TopRight: '╮', BottomLeft: '╰', BottomRight: '╯', Horizontal: '─', Vertical: '│', }, BorderBold: { TopLeft: '┏', TopRight: '┓', BottomLeft: '┗', BottomRight: '┛', Horizontal: '━', Vertical: '┃', }, }
Border character sets for different styles.
var DefaultInputHandler = ComposeInputHandlers( InputNavigationHandler, InputDeletionHandler, InputShiftEnterHandler, InputPrintableHandler, )
DefaultInputHandler implements standard text editing behavior.
var EmptyCell = Cell{Char: ' ', Style: EmptyStyle}
EmptyCell is a Cell with a space character and no styling.
var EmptyStyle = Style{}
EmptyStyle is a Style with no attributes set.
var NameToColor = map[string]Color{ "default": ColorDefault, "black": ColorBlack, "red": ColorRed, "green": ColorGreen, "yellow": ColorYellow, "blue": ColorBlue, "magenta": ColorMagenta, "cyan": ColorCyan, "white": ColorWhite, }
NameToColor converts a string color name to Color
Functions ¶
func CollectTextContent ¶
CollectTextContent recursively collects all text content from a node.
func ColorToAnsi ¶
ColorToAnsi converts a Color to ANSI escape code.
func CreateTextNode ¶
CreateTextNode creates a text node.
func FilterAbsoluteChildren ¶
FilterAbsoluteChildren returns children with absolute positioning.
func FilterRelativeChildren ¶
FilterRelativeChildren returns children with relative positioning.
func FormatMessage ¶
func FormatMessage(msg LogMessage) string
FormatMessage formats a log message for display
func GetBoolProp ¶
GetBoolProp gets a boolean property with a default value.
func GetTextContent ¶
GetTextContent returns the text content if this is a text node.
func GroupChangesByRow ¶
func GroupChangesByRow(changes []CellChange) map[int][]CellChange
GroupChangesByRow groups changes by row for more efficient cursor movement.
func HasIntrinsicHandler ¶
HasIntrinsicHandler returns true if a handler is registered for the given type.
func IsInClip ¶
func IsInClip(x, y int, clip *ClipRegion) bool
IsInClip checks if a position is within the clip region.
func IsTerminal ¶
IsTerminal returns whether the file descriptor is a terminal.
func MeasureNode ¶
MeasureNode measures the natural size of a node (before flex distribution).
func MoveCursor ¶
MoveCursor returns the ANSI code to move the cursor to (x, y). ANSI uses 1-based coordinates.
func RegisterIntrinsic ¶
func RegisterIntrinsic(name string, handler *IntrinsicHandler)
RegisterIntrinsic registers a handler for an intrinsic element type. This should be called from init() functions in component packages. The name corresponds to the JSX element name (e.g., "input", "select").
func RenderInputToBuffer ¶
func RenderInputToBuffer(box *LayoutBox, buf *CellBuffer, clip *ClipRegion)
func RenderInputToLogicalBuffer ¶
func RenderInputToLogicalBuffer(box *LayoutBox, buf *LogicalBuffer, clip *ClipRegion)
func RenderSelectToBuffer ¶
func RenderSelectToBuffer(box *LayoutBox, buf *CellBuffer, clip *ClipRegion)
func RenderSelectToLogicalBuffer ¶
func RenderSelectToLogicalBuffer(box *LayoutBox, buf *LogicalBuffer, clip *ClipRegion)
func RenderToBuffer ¶
func RenderToBuffer(box *LayoutBox, buf *CellBuffer, clip *ClipRegion)
RenderToBuffer renders a LayoutBox tree to a CellBuffer.
func RenderToLogicalBuffer ¶
func RenderToLogicalBuffer(box *LayoutBox, buf *LogicalBuffer, clip *ClipRegion)
RenderToLogicalBuffer renders a LayoutBox tree to a LogicalBuffer.
func RequestBlur ¶
func RequestBlur(f Focusable)
RequestBlur blurs a specific focusable using the global manager.
func RequestFocus ¶
func RequestFocus(f Focusable)
RequestFocus focuses a specific focusable using the global manager.
func Run ¶
func Run(appFn func() gox.VNode, opts RunOptions)
Run runs a TUI app with full terminal handling.
func RunsToAnsi ¶
RunsToAnsi renders all runs to a single ANSI string.
func RunsToAnsiBuilder ¶
RunsToAnsiBuilder renders all runs to the provided strings.Builder. This avoids allocation when the caller manages the builder.
func StyleToAnsi ¶
StyleToAnsi generates ANSI codes for a style, writing directly to builder.
func TypeString ¶
TypeString returns the type as a string (for intrinsic elements).
func Unregister ¶
func Unregister(f Focusable)
Unregister removes a focusable from the global manager.
Types ¶
type App ¶
type App struct {
// contains filtered or unexported fields
}
App represents a reactive TUI application.
type BorderChars ¶
type BorderChars struct {
TopLeft rune
TopRight rune
BottomLeft rune
BottomRight rune
Horizontal rune
Vertical rune
}
BorderChars holds the characters for drawing a border.
type BorderStyle ¶
type BorderStyle string
BorderStyle specifies the border appearance.
const ( BorderNone BorderStyle = "none" BorderSingle BorderStyle = "single" BorderDouble BorderStyle = "double" BorderRounded BorderStyle = "rounded" BorderBold BorderStyle = "bold" )
func GetBorderStyle ¶
func GetBorderStyle(border any) BorderStyle
GetBorderStyle normalizes border prop to BorderStyle.
type Cell ¶
Cell represents a single "pixel" in the terminal. It holds a character and its styling attributes.
type CellBuffer ¶
type CellBuffer struct {
// contains filtered or unexported fields
}
CellBuffer is a fixed-size 2D grid of cells representing the terminal screen. This is the core data structure for diffing.
func NewCellBuffer ¶
func NewCellBuffer(width, height int) *CellBuffer
NewCellBuffer creates a new buffer filled with empty cells.
func (*CellBuffer) Clear ¶
func (b *CellBuffer) Clear()
Clear clears the entire buffer with empty cells.
func (*CellBuffer) Get ¶
func (b *CellBuffer) Get(x, y int) Cell
Get returns the cell at (x, y), or EmptyCell if out of bounds.
func (*CellBuffer) Set ¶
func (b *CellBuffer) Set(x, y int, c Cell)
Set sets the cell at (x, y). Does nothing if out of bounds.
func (*CellBuffer) SetChar ¶
func (b *CellBuffer) SetChar(x, y int, char rune, style Style)
SetChar sets a character with style at (x, y).
func (*CellBuffer) SetCharMerge ¶
func (b *CellBuffer) SetCharMerge(x, y int, char rune, style Style)
SetCharMerge sets a character, merging style with existing cell. Preserves background if the new style doesn't specify one.
func (*CellBuffer) ToDebugString ¶
func (b *CellBuffer) ToDebugString() string
ToDebugString returns a debug string representation (characters only).
func (*CellBuffer) WriteString ¶
func (b *CellBuffer) WriteString(x, y int, text string, style Style) int
WriteString writes a string starting at (x, y), going right. Text is clipped at buffer edge. Returns number of characters written.
type CellChange ¶
CellChange represents a change at a specific position.
func DiffBuffers ¶
func DiffBuffers(from, to *CellBuffer) []CellChange
DiffBuffers computes the diff between two buffers. Returns an array of cell changes needed to transform `from` into `to`.
func DiffBuffersInto ¶
func DiffBuffersInto(from, to *CellBuffer, result []CellChange) []CellChange
DiffBuffersInto computes the diff between two buffers, appending to the provided slice. This avoids allocation when the caller pre-allocates the result slice.
type CellRun ¶
CellRun represents a run of consecutive cells.
func FindRuns ¶
func FindRuns(changes []CellChange) []CellRun
FindRuns detects consecutive runs in changes for efficient output. A run is a sequence of consecutive x positions.
func FindRunsInto ¶
func FindRunsInto(changes []CellChange, result []CellRun) []CellRun
FindRunsInto detects consecutive runs in changes, appending to the provided slice. This avoids allocation when the caller pre-allocates the result slice.
type ChildMeasurement ¶
ChildMeasurement holds a measured child node.
type ClipRegion ¶
type ClipRegion struct {
MinX int // Inclusive
MinY int // Inclusive
MaxX int // Exclusive
MaxY int // Exclusive
}
ClipRegion defines the visible area for clipping content.
func IntersectClip ¶
func IntersectClip(a, b *ClipRegion) *ClipRegion
IntersectClip intersects two clip regions, returning the overlapping area.
type Color ¶
type Color uint8
Color represents terminal colors using a compact uint8 representation. Values 0-9 are named colors, 10+ reserved for future use. RGB colors use a separate type.
type Direction ¶
type Direction string
Direction specifies the main axis for flex layout.
func GetDirection ¶
GetDirection returns the flex direction from props.
type FocusManager ¶
type FocusManager struct {
// contains filtered or unexported fields
}
FocusManager manages focus state for terminal UI components.
func (*FocusManager) Clear ¶
func (m *FocusManager) Clear()
Clear removes all registered focusables and handlers.
func (*FocusManager) Current ¶
func (m *FocusManager) Current() Focusable
Current returns the currently focused element.
func (*FocusManager) GetAll ¶
func (m *FocusManager) GetAll() []Focusable
GetAll returns all registered focusable elements.
func (*FocusManager) HandleKey ¶
func (m *FocusManager) HandleKey(key string) bool
HandleKey routes a keypress to the focused element. Handles Tab/Shift+Tab for focus navigation. Returns true if the key was consumed.
func (*FocusManager) Next ¶
func (m *FocusManager) Next()
Next focuses the next element in registration order.
func (*FocusManager) Prev ¶
func (m *FocusManager) Prev()
Prev focuses the previous element in registration order.
func (*FocusManager) Register ¶
func (m *FocusManager) Register(f Focusable)
Register adds a focusable to the manager.
func (*FocusManager) RequestBlur ¶
func (m *FocusManager) RequestBlur(f Focusable)
RequestBlur blurs a specific focusable.
func (*FocusManager) RequestFocus ¶
func (m *FocusManager) RequestFocus(f Focusable)
RequestFocus focuses a specific focusable.
func (*FocusManager) Set ¶
func (m *FocusManager) Set(f Focusable)
Set manually sets the focused element. Pass nil to blur all.
func (*FocusManager) SetGlobalKeyHandler ¶
func (m *FocusManager) SetGlobalKeyHandler(handler func(key string) bool) func()
SetGlobalKeyHandler sets a handler for app-wide keyboard shortcuts. This handler is called for keys that no focused element consumes. Returns a cleanup function to remove the handler.
func (*FocusManager) Unregister ¶
func (m *FocusManager) Unregister(f Focusable)
Unregister removes a focusable from the manager.
type Focusable ¶
type Focusable interface {
Focused() bool
Focus()
Blur()
Dispose()
HandleKey(key string) bool
SetFocused(focused bool)
}
Focusable is the interface for any focusable element (input, button, etc).
type Input ¶
type Input struct {
// contains filtered or unexported fields
}
Input represents a text input field.
func (*Input) DisplayValue ¶
DisplayValue returns the display text (with masking/placeholder).
func (*Input) GetState ¶
func (i *Input) GetState() InputState
GetState returns the current state snapshot.
func (*Input) SetCursorPos ¶
SetCursorPos updates the cursor position.
func (*Input) SetFocused ¶
SetFocused sets the focused state (called by focus manager).
func (*Input) ShowingPlaceholder ¶
ShowingPlaceholder returns true if displaying placeholder text.
type InputKeyHandler ¶
type InputKeyHandler func(key string, state InputState) *InputState
InputKeyHandler is a keypress handler. Return new state to consume the key, or nil to let it bubble up.
func ComposeInputHandlers ¶
func ComposeInputHandlers(handlers ...InputKeyHandler) InputKeyHandler
ComposeInputHandlers combines multiple handlers into one. Handlers are tried in order until one returns non-nil.
type InputOptions ¶
type InputOptions struct {
// InitialValue is the starting text.
InitialValue string
// MaxLength limits the number of characters (0 = unlimited).
MaxLength int
// Mask character for passwords (e.g., "*").
Mask rune
// Placeholder text shown when input is empty.
Placeholder string
// OnKeypress is a custom keypress handler.
OnKeypress InputKeyHandler
}
InputOptions configures input creation.
type InputState ¶
InputState represents the state of an input field.
func InputDeletionHandler ¶
func InputDeletionHandler(key string, state InputState) *InputState
InputDeletionHandler handles backspace, delete, word delete.
func InputNavigationHandler ¶
func InputNavigationHandler(key string, state InputState) *InputState
InputNavigationHandler handles arrow keys, home/end, word navigation.
func InputNewlineHandler ¶
func InputNewlineHandler(key string, state InputState) *InputState
InputNewlineHandler inserts newline on Enter (for multiline editors).
func InputPrintableHandler ¶
func InputPrintableHandler(key string, state InputState) *InputState
InputPrintableHandler inserts printable characters at cursor.
func InputShiftEnterHandler ¶
func InputShiftEnterHandler(key string, state InputState) *InputState
InputShiftEnterHandler inserts newline only on Shift+Enter.
type IntrinsicHandler ¶
type IntrinsicHandler struct {
// Layout computes the layout for this element type.
// If nil, default box layout is used.
Layout IntrinsicLayoutFunc
// Measure returns the intrinsic size of this element.
// If nil, size is determined by props or children.
Measure IntrinsicMeasureFunc
// Render draws this element to a CellBuffer.
// If nil, children are rendered with default box behavior.
Render IntrinsicRenderFunc
// RenderLogical draws this element to a LogicalBuffer.
// If nil, children are rendered with default box behavior.
RenderLogical IntrinsicRenderLogicalFunc
}
IntrinsicHandler defines how to layout and render an intrinsic element type.
func GetIntrinsicHandler ¶
func GetIntrinsicHandler(name string) *IntrinsicHandler
GetIntrinsicHandler returns the handler for an intrinsic element type. Returns nil if no handler is registered.
type IntrinsicLayoutFunc ¶
type IntrinsicLayoutFunc func(node gox.VNode, availWidth, availHeight int, ctx *LayoutContext) *LayoutBox
IntrinsicLayoutFunc handles layout for an intrinsic element type. It receives the node, available width/height, and layout context. Returns the computed LayoutBox for this element.
type IntrinsicMeasureFunc ¶
type IntrinsicMeasureFunc func(node gox.VNode, ctx *LayoutContext) (int, int)
IntrinsicMeasureFunc measures the intrinsic size of an element. Returns (width, height).
type IntrinsicRenderFunc ¶
type IntrinsicRenderFunc func(box *LayoutBox, buf *CellBuffer, clip *ClipRegion)
IntrinsicRenderFunc renders an element to a CellBuffer.
type IntrinsicRenderLogicalFunc ¶
type IntrinsicRenderLogicalFunc func(box *LayoutBox, buf *LogicalBuffer, clip *ClipRegion)
IntrinsicRenderLogicalFunc renders an element to a LogicalBuffer.
type Justify ¶
type Justify string
Justify specifies alignment along the main axis.
func GetJustify ¶
GetJustify returns the justify-content from props.
type LayoutBox ¶
type LayoutBox struct {
// Position (absolute, after all calculations)
X int
Y int
Width int
Height int
// Content area (inside padding/border)
InnerX int
InnerY int
InnerWidth int
InnerHeight int
// The node this box represents
Node gox.VNode
// Child boxes
Children []*LayoutBox
// For z-index sorting
ZIndex int
}
LayoutBox represents a computed layout for a node.
func ComputeLayout ¶
func ComputeLayout(node gox.VNode, ctx LayoutContext) *LayoutBox
ComputeLayout computes layout for a VNode tree.
func LayoutFlexChildren ¶
func LayoutFlexChildren( children []ChildMeasurement, ctx LayoutContext, direction Direction, justify Justify, align Align, gap int, absoluteBoxes *[]*LayoutBox, ) []*LayoutBox
LayoutFlexChildren lays out children using flexbox rules.
type LayoutContext ¶
LayoutContext provides the available space for layout.
type LayoutResult ¶
LayoutResult holds the result of layout computation.
func LayoutNode ¶
func LayoutNode(node gox.VNode, ctx LayoutContext) LayoutResult
LayoutNode computes layout for a single node.
type LogCapture ¶
type LogCapture struct {
// contains filtered or unexported fields
}
LogCapture captures log output for display in the TUI
func NewLogCapture ¶
func NewLogCapture(maxMessages int) *LogCapture
NewLogCapture creates a new log capture with the specified max message count
func (*LogCapture) Debug ¶
func (lc *LogCapture) Debug(format string, args ...any)
Debug logs a debug message
func (*LogCapture) Error ¶
func (lc *LogCapture) Error(format string, args ...any)
Error logs an error message
func (*LogCapture) Info ¶
func (lc *LogCapture) Info(format string, args ...any)
Info logs an info message
func (*LogCapture) LastMessages ¶
func (lc *LogCapture) LastMessages(n int) []LogMessage
LastMessages returns the last n messages (reactive)
func (*LogCapture) Log ¶
func (lc *LogCapture) Log(level LogLevel, format string, args ...any)
Log logs a message at the specified level
func (*LogCapture) Messages ¶
func (lc *LogCapture) Messages() []LogMessage
Messages returns the current messages (reactive)
func (*LogCapture) OriginalStdout ¶
func (lc *LogCapture) OriginalStdout() *os.File
OriginalStdout returns the original stdout file
func (*LogCapture) Start ¶
func (lc *LogCapture) Start() error
Start begins capturing stdout and stderr
func (*LogCapture) Stop ¶
func (lc *LogCapture) Stop()
Stop stops capturing and restores original stdout/stderr
func (*LogCapture) Warn ¶
func (lc *LogCapture) Warn(format string, args ...any)
Warn logs a warning message
func (*LogCapture) WriteToOriginal ¶
func (lc *LogCapture) WriteToOriginal(p []byte) (n int, err error)
WriteToOriginal writes directly to the original stdout (bypassing capture) This is useful for TUI rendering
type LogMessage ¶
LogMessage represents a captured log message
type LogicalBuffer ¶
type LogicalBuffer struct {
// contains filtered or unexported fields
}
LogicalBuffer stores content as logical rows with arbitrary length. Terminal wrapping is handled at render time, not storage time.
func NewLogicalBuffer ¶
func NewLogicalBuffer(height int) *LogicalBuffer
NewLogicalBuffer creates a new logical buffer with the given height.
func (*LogicalBuffer) Get ¶
func (b *LogicalBuffer) Get(x, y int) Cell
Get returns the cell at logical position (x, y). Returns EmptyCell if out of bounds.
func (*LogicalBuffer) GetRow ¶
func (b *LogicalBuffer) GetRow(y int) *LogicalRow
GetRow returns a logical row.
func (*LogicalBuffer) Height ¶
func (b *LogicalBuffer) Height() int
Height returns the number of logical rows.
func (*LogicalBuffer) RowLength ¶
func (b *LogicalBuffer) RowLength(y int) int
RowLength returns the length of a logical row.
func (*LogicalBuffer) Set ¶
func (b *LogicalBuffer) Set(x, y int, c Cell)
Set sets the cell at logical position (x, y). Extends the row if needed.
func (*LogicalBuffer) SetMerge ¶
func (b *LogicalBuffer) SetMerge(x, y int, c Cell)
SetMerge sets a cell, merging style with existing cell. Preserves background color if the new style doesn't specify one.
func (*LogicalBuffer) ToVisualRows ¶
func (b *LogicalBuffer) ToVisualRows(terminalWidth int) VisualRows
ToVisualRows transforms logical rows to visual rows based on terminal width.
func (*LogicalBuffer) WriteString ¶
func (b *LogicalBuffer) WriteString(x, y int, text string, style Style)
WriteString writes a string starting at (x, y). The row extends as needed - no clipping.
type LogicalRow ¶
type LogicalRow struct {
Cells []Cell
}
LogicalRow is a variable-length array of cells.
type Options ¶
type Options struct {
Width int
Height int
Output io.Writer
Pipeline bool // Force pipeline renderer (auto-detected if not set)
DisableThrottle bool // Disable frame rate limiting (for tests)
OnRender func()
OnError func(error)
}
Options configures the renderer and app.
type Overflow ¶
type Overflow string
Overflow specifies overflow behavior.
func GetOverflow ¶
GetOverflow returns the overflow mode from props.
type PipelineRenderer ¶
type PipelineRenderer struct {
// contains filtered or unexported fields
}
PipelineRenderer uses a 4-stage concurrent pipeline for rendering. Each stage runs in its own goroutine:
- Layout: VNode → LayoutBox
- Buffer: LayoutBox → CellBuffer
- Diff: CellBuffer → []CellChange → []CellRun → ANSI string
- Output: ANSI string → io.Writer
func NewPipeline ¶
func NewPipeline(opts Options) *PipelineRenderer
NewPipeline creates a new pipelined renderer.
func (*PipelineRenderer) Render ¶
func (p *PipelineRenderer) Render(root gox.VNode)
Render submits a frame to the pipeline (non-blocking if pipeline has capacity).
func (*PipelineRenderer) RenderBlocking ¶
func (p *PipelineRenderer) RenderBlocking(root gox.VNode)
RenderBlocking submits a frame and waits until it enters the pipeline.
func (*PipelineRenderer) Stop ¶
func (p *PipelineRenderer) Stop()
Stop shuts down the pipeline gracefully.
type RGB ¶
type RGB struct {
R, G, B uint8
}
RGB represents a 24-bit true color. When used, the Color field should be set to a special marker.
type Renderer ¶
type Renderer struct {
// contains filtered or unexported fields
}
Renderer is the main orchestrator that ties everything together. Uses LogicalBuffer for content storage, transforms to visual rows for output.
func (*Renderer) CurrentBuffer ¶
func (r *Renderer) CurrentBuffer() *CellBuffer
CurrentBuffer returns the current visual buffer (for testing).
type RendererInterface ¶
RendererInterface defines the common interface for all renderers.
func NewAuto ¶
func NewAuto(opts Options) RendererInterface
NewAuto creates the optimal renderer based on grid size. Uses pipeline renderer for larger grids (>3000 cells) and sequential for smaller ones.
type RunOptions ¶
type RunOptions struct {
Width int
Height int
Output io.Writer
OnMount func(*App)
OnUnmount func()
OnRender func()
OnError func(error)
CaptureConsole bool // Capture console output (default: true). Press Ctrl+L to toggle log viewer.
MaxConsoleMessages int // Maximum number of console messages to keep (default: 1000)
}
RunOptions configures the Run function.
type Select ¶
type Select[T comparable] struct { // contains filtered or unexported fields }
Select represents a list selection component. The select tracks the selected index; option values come from <option> children.
func NewSelect ¶
func NewSelect[T comparable](opts SelectOptions[T]) *Select[T]
NewSelect creates a new select primitive.
func (*Select[T]) ClearOptions ¶
func (s *Select[T]) ClearOptions()
ClearOptions clears registered options (called during layout).
func (*Select[T]) Dispose ¶
func (s *Select[T]) Dispose()
Dispose unregisters from the focus manager.
func (*Select[T]) IsSelectedIndex ¶
IsSelectedIndex returns true if the given index is selected.
func (*Select[T]) RegisterOption ¶
RegisterOption registers an option value at an index (called during layout). This does NOT trigger re-renders.
func (*Select[T]) RegisterOptionAny ¶
RegisterOptionAny registers an option value at an index (type-unsafe version for intrinsic use).
func (*Select[T]) SelectedIndex ¶
SelectedIndex returns the currently selected index.
func (*Select[T]) SetFocused ¶
SetFocused sets the focused state (called by focus manager).
func (*Select[T]) SetOptionCount ¶
SetOptionCount sets the option count (called during layout). This does NOT trigger re-renders.
type SelectOptions ¶
type SelectOptions[T comparable] struct { // InitialValue is the starting selection (used to set initial index when option with this value is registered). InitialValue T // OnChange is called when selection changes. OnChange func(value T) // OnKeypress is a custom key handler (called before default handling). OnKeypress func(key string) bool // DisableFocus disables focus management registration (default: false, meaning focusable by default). DisableFocus bool }
SelectOptions configures select creation.
type Spacing ¶
Spacing represents padding or margin on all sides.
func NormalizeSpacing ¶
NormalizeSpacing converts various spacing inputs to a Spacing struct.
type State ¶
type State struct {
// contains filtered or unexported fields
}
State holds the terminal state for later restoration.
type Style ¶
type Style struct {
Color Color
Background Color
Bold bool
Dim bool
Italic bool
Underline bool
Inverse bool
Strikethrough bool
// RGB colors (only used when Color/Background need 24-bit)
ColorRGB *RGB
BackgroundRGB *RGB
}
Style holds text styling attributes. Uses compact representation: 2 bytes for colors, 1 byte for flags, plus optional RGB.
func (Style) HasBackground ¶
HasBackground returns true if the style has a background color set.
type VisualRows ¶
type VisualRows struct {
Rows [][]Cell // Visual rows
LogicalToVisual []int // LogicalToVisual[logicalY] = first visual row index
}
VisualRows holds the result of transforming logical rows to visual rows.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
benchmarks
|
|
|
comparison-ink/goli-bench
command
Goli version of the benchmark UI - a file tree with 100 items
|
Goli version of the benchmark UI - a file tree with 100 items |
|
cpu
command
Package main provides CPU usage benchmarking for goli applications.
|
Package main provides CPU usage benchmarking for goli applications. |
|
examples
|
|
|
perf-benchmark
command
Performance benchmark - measures actual render pipeline timing
|
Performance benchmark - measures actual render pipeline timing |
|
perf-pipeline
command
Pipeline benchmark - compare sequential vs pipelined rendering
|
Pipeline benchmark - compare sequential vs pipelined rendering |
|
perf-scaling
command
Scaling test - see how performance changes with grid size
|
Scaling test - see how performance changes with grid size |
|
perf-stress
command
Performance stress test Tests rendering performance with rapidly changing content and scrolling.
|
Performance stress test Tests rendering performance with rapidly changing content and scrolling. |
|
Package signals provides fine-grained reactive primitives.
|
Package signals provides fine-grained reactive primitives. |