Documentation
¶
Overview ¶
Package compositor bridge provides integration with Bubbletea's rendering model. Since Bubbletea expects View() to return a string and handles terminal updates internally, we provide adapters that: 1. Track what was previously rendered 2. Compute minimal updates for high-churn areas 3. Return optimized ANSI output that bubbletea can pass through
For backend.Backend integration, see pkg/ui/render which provides BackendWriter.
Package compositor provides a flicker-free terminal rendering system. It maintains a virtual screen buffer and outputs only changed cells, inspired by modern compositor architecture.
Index ¶
- Constants
- Variables
- func CursorBack(n int) string
- func CursorDown(n int) string
- func CursorForward(n int) string
- func CursorShapeSeq(ps int) string
- func CursorTo(x, y int) string
- func CursorUp(n int) string
- func Hyperlink(url, text string) string
- func ProgressBar(current, total, width int, filled, empty rune, filledStyle, emptyStyle Style) string
- func RenderToString(width, height int, draw func(*Screen)) string
- func SpinnerFrame(tick int) rune
- func StyleDelta(from, to Style) string
- func StyleToANSI(s Style) string
- func SyncBegin() string
- func SyncEnd() string
- func TextBox(text string, x, y, width, height int, style Style, borderStyle Style) string
- func WrapSync(content string, syncEnabled bool) string
- type ANSIWriter
- func (w *ANSIWriter) Grow(n int)
- func (w *ANSIWriter) HideCursor()
- func (w *ANSIWriter) Len() int
- func (w *ANSIWriter) MoveTo(x, y int)
- func (w *ANSIWriter) Reset()
- func (w *ANSIWriter) ResetStyle()
- func (w *ANSIWriter) SetStyle(s Style)
- func (w *ANSIWriter) ShowCursor()
- func (w *ANSIWriter) String() string
- func (w *ANSIWriter) WriteRune(r rune)
- func (w *ANSIWriter) WriteString(s string)
- type Cell
- type Color
- type ColorMode
- type Compositor
- func (c *Compositor) AddLayer() *Screen
- func (c *Compositor) Clear()
- func (c *Compositor) ClearLayers()
- func (c *Compositor) Compose()
- func (c *Compositor) RemoveLayer()
- func (c *Compositor) Render() string
- func (c *Compositor) RenderFull() string
- func (c *Compositor) Resize(width, height int)
- func (c *Compositor) Screen() *Screen
- func (c *Compositor) SetCursor(x, y int, visible bool)
- func (c *Compositor) SetSyncOutput(enabled bool)
- func (c *Compositor) Size() (width, height int)
- type DiffStats
- type DirectWriter
- type FrameBuilder
- func (fb *FrameBuilder) Box(x, y, w, h int, style Style) *FrameBuilder
- func (fb *FrameBuilder) Fill(x, y, w, h int, r rune, style Style) *FrameBuilder
- func (fb *FrameBuilder) HLine(x, y, length int, r rune, style Style) *FrameBuilder
- func (fb *FrameBuilder) Text(x, y int, text string, style Style) *FrameBuilder
- func (fb *FrameBuilder) VLine(x, y, length int, r rune, style Style) *FrameBuilder
- type Region
- type Renderer
- type Screen
- func (s *Screen) Blit(src *Screen, srcX, srcY, dstX, dstY, w, h int)
- func (s *Screen) Box(x, y, w, h int, style Style)
- func (s *Screen) Clear()
- func (s *Screen) ClearCurrentBuffer()
- func (s *Screen) CopyToPrevious()
- func (s *Screen) Cursor() (x, y int, visible bool)
- func (s *Screen) FillRect(x, y, w, h int, r rune, style Style)
- func (s *Screen) FillRectCell(x, y, w, h int, cell Cell)
- func (s *Screen) Get(x, y int) Cell
- func (s *Screen) GetPrevious(x, y int) Cell
- func (s *Screen) HLine(x, y, length int, r rune, style Style)
- func (s *Screen) Resize(width, height int)
- func (s *Screen) Set(x, y int, r rune, style Style)
- func (s *Screen) SetCursor(x, y int, visible bool)
- func (s *Screen) SetString(x, y int, str string, style Style) int
- func (s *Screen) Size() (width, height int)
- func (s *Screen) Sub(x, y, w, h int) *SubScreen
- func (s *Screen) SwapBuffers()
- func (s *Screen) VLine(x, y, length int, r rune, style Style)
- type StreamRenderer
- type Style
- func (s Style) Equal(other Style) bool
- func (s Style) WithBG(c Color) Style
- func (s Style) WithBold(b bool) Style
- func (s Style) WithDim(d bool) Style
- func (s Style) WithFG(c Color) Style
- func (s Style) WithItalic(i bool) Style
- func (s Style) WithReverse(r bool) Style
- func (s Style) WithUnderline(u bool) Style
- type SubScreen
- func (ss *SubScreen) Box(style Style)
- func (ss *SubScreen) Clear()
- func (ss *SubScreen) FillRect(x, y, w, h int, r rune, style Style)
- func (ss *SubScreen) Set(x, y int, r rune, style Style)
- func (ss *SubScreen) SetString(x, y int, str string, style Style) int
- func (ss *SubScreen) Size() (width, height int)
- type TableRenderer
Constants ¶
const ( ANSIEscape = "\x1b[" ANSIClearScreen = "\x1b[2J" ANSIClearLine = "\x1b[2K" ANSICursorHome = "\x1b[H" ANSICursorHide = "\x1b[?25l" ANSICursorShow = "\x1b[?25h" ANSIReset = "\x1b[0m" ANSISaveCursor = "\x1b[s" ANSIRestoreCursor = "\x1b[u" ANSIAltScreen = "\x1b[?1049h" ANSIMainScreen = "\x1b[?1049l" ANSISyncStart = "\x1b[?2026h" ANSISyncEnd = "\x1b[?2026l" )
ANSI escape sequences.
Variables ¶
var ( ColorNone = Color{Mode: ColorModeNone} ColorDefault = Color{Mode: ColorModeDefault} // Basic 16 colors ColorBlack = Color{Mode: ColorMode16, Value: 0} ColorRed = Color{Mode: ColorMode16, Value: 1} ColorGreen = Color{Mode: ColorMode16, Value: 2} ColorYellow = Color{Mode: ColorMode16, Value: 3} ColorBlue = Color{Mode: ColorMode16, Value: 4} ColorMagenta = Color{Mode: ColorMode16, Value: 5} ColorCyan = Color{Mode: ColorMode16, Value: 6} ColorWhite = Color{Mode: ColorMode16, Value: 7} // Bright variants ColorBrightBlack = Color{Mode: ColorMode16, Value: 8} ColorBrightRed = Color{Mode: ColorMode16, Value: 9} ColorBrightGreen = Color{Mode: ColorMode16, Value: 10} ColorBrightYellow = Color{Mode: ColorMode16, Value: 11} ColorBrightBlue = Color{Mode: ColorMode16, Value: 12} ColorBrightMagenta = Color{Mode: ColorMode16, Value: 13} ColorBrightCyan = Color{Mode: ColorMode16, Value: 14} ColorBrightWhite = Color{Mode: ColorMode16, Value: 15} )
Pre-defined colors for convenience.
Functions ¶
func CursorShapeSeq ¶
CursorShapeSeq returns the DECSCUSR sequence for the given cursor shape. Ps: 0=default, 2=block, 4=underline, 6=beam.
func CursorTo ¶
CursorTo returns ANSI sequence to move cursor to (x, y). Coordinates are 0-indexed, but ANSI uses 1-indexed.
func Hyperlink ¶
Hyperlink wraps text in an OSC-8 hyperlink sequence. Terminals that don't support OSC-8 will ignore the escape sequences and display the text normally.
func ProgressBar ¶
func ProgressBar(current, total, width int, filled, empty rune, filledStyle, emptyStyle Style) string
ProgressBar renders a progress bar.
func RenderToString ¶
RenderToString is a convenience function for quick rendering.
func SpinnerFrame ¶
SpinnerFrame returns the current spinner character.
func StyleDelta ¶
StyleDelta returns ANSI codes to change from 'from' style to 'to' style. This is more efficient than always resetting and setting new style.
func StyleToANSI ¶
StyleToANSI converts a Style to ANSI escape sequence.
func SyncBegin ¶
func SyncBegin() string
SyncBegin returns the escape sequence to begin a synchronized update. DEC mode 2026: \x1b[?2026h
func SyncEnd ¶
func SyncEnd() string
SyncEnd returns the escape sequence to end a synchronized update. DEC mode 2026: \x1b[?2026l
Types ¶
type ANSIWriter ¶
type ANSIWriter struct {
// contains filtered or unexported fields
}
ANSIWriter helps build ANSI output efficiently.
func (*ANSIWriter) HideCursor ¶
func (w *ANSIWriter) HideCursor()
HideCursor adds cursor hide sequence.
func (*ANSIWriter) MoveTo ¶
func (w *ANSIWriter) MoveTo(x, y int)
MoveTo positions cursor, optimizing for sequential writes.
func (*ANSIWriter) Reset ¶
func (w *ANSIWriter) Reset()
Reset resets the writer for reuse, clearing the buffer and state while keeping capacity.
func (*ANSIWriter) ResetStyle ¶
func (w *ANSIWriter) ResetStyle()
ResetStyle adds a style reset to the buffer.
func (*ANSIWriter) SetStyle ¶
func (w *ANSIWriter) SetStyle(s Style)
SetStyle changes the current style.
func (*ANSIWriter) ShowCursor ¶
func (w *ANSIWriter) ShowCursor()
ShowCursor adds cursor show sequence.
func (*ANSIWriter) String ¶
func (w *ANSIWriter) String() string
String returns the accumulated output.
func (*ANSIWriter) WriteRune ¶
func (w *ANSIWriter) WriteRune(r rune)
WriteRune writes a single rune.
func (*ANSIWriter) WriteString ¶
func (w *ANSIWriter) WriteString(s string)
WriteString writes a string.
type Cell ¶
type Cell struct {
Rune rune
Width uint8 // Display width (1 for most, 2 for CJK, 0 for continuation)
Style Style
}
Cell represents a single character cell on screen.
type ColorMode ¶
type ColorMode uint8
ColorMode defines how a color is represented.
const ( // ColorModeNone means no color (inherit default). ColorModeNone ColorMode = iota // ColorModeDefault uses terminal default color. ColorModeDefault // ColorMode16 uses basic 16 ANSI colors (0-15). ColorMode16 // ColorMode256 uses extended 256 color palette. ColorMode256 // ColorModeRGB uses 24-bit true color. ColorModeRGB )
type Compositor ¶
type Compositor struct {
// contains filtered or unexported fields
}
Compositor manages the full rendering pipeline.
func NewCompositor ¶
func NewCompositor(width, height int) *Compositor
NewCompositor creates a new compositor with the given dimensions.
func (*Compositor) AddLayer ¶
func (c *Compositor) AddLayer() *Screen
AddLayer adds an overlay layer.
func (*Compositor) ClearLayers ¶
func (c *Compositor) ClearLayers()
ClearLayers removes all overlay layers.
func (*Compositor) Compose ¶
func (c *Compositor) Compose()
Compose merges all layers onto the main screen. Non-empty cells from higher layers override lower layers.
func (*Compositor) RemoveLayer ¶
func (c *Compositor) RemoveLayer()
RemoveLayer removes the topmost layer.
func (*Compositor) Render ¶
func (c *Compositor) Render() string
Render computes diff and returns ANSI output.
func (*Compositor) RenderFull ¶
func (c *Compositor) RenderFull() string
RenderFull forces complete redraw.
func (*Compositor) Resize ¶
func (c *Compositor) Resize(width, height int)
Resize updates compositor dimensions.
func (*Compositor) Screen ¶
func (c *Compositor) Screen() *Screen
Screen returns the main screen buffer.
func (*Compositor) SetCursor ¶
func (c *Compositor) SetCursor(x, y int, visible bool)
SetCursor sets cursor position and visibility.
func (*Compositor) SetSyncOutput ¶
func (c *Compositor) SetSyncOutput(enabled bool)
SetSyncOutput enables or disables synchronized output on the compositor's underlying renderer. See Renderer.SetSyncOutput for details.
func (*Compositor) Size ¶
func (c *Compositor) Size() (width, height int)
Size returns current dimensions.
type DiffStats ¶
type DiffStats struct {
TotalCells int
ChangedCells int
SkippedCells int // Continuation cells
StyleChanges int
CursorJumps int
}
DiffStats returns statistics about what changed between frames. Useful for debugging and performance monitoring.
type DirectWriter ¶
type DirectWriter struct {
// contains filtered or unexported fields
}
DirectWriter provides direct terminal output for compositor rendering. Use this when you want to bypass bubbletea's renderer entirely.
func NewDirectWriter ¶
func NewDirectWriter(out io.Writer, width, height int) *DirectWriter
NewDirectWriter creates a writer that outputs directly to a terminal.
func (*DirectWriter) Flush ¶
func (dw *DirectWriter) Flush() error
Flush renders and writes to output.
func (*DirectWriter) FlushFull ¶
func (dw *DirectWriter) FlushFull() error
FlushFull forces a complete redraw.
func (*DirectWriter) Resize ¶
func (dw *DirectWriter) Resize(width, height int)
Resize updates dimensions.
func (*DirectWriter) Screen ¶
func (dw *DirectWriter) Screen() *Screen
Screen returns the main screen for drawing.
type FrameBuilder ¶
type FrameBuilder struct {
// contains filtered or unexported fields
}
FrameBuilder provides a fluent API for building frames.
func NewFrameBuilder ¶
func NewFrameBuilder(screen *Screen) *FrameBuilder
NewFrameBuilder creates a builder for the screen.
func (*FrameBuilder) Box ¶
func (fb *FrameBuilder) Box(x, y, w, h int, style Style) *FrameBuilder
Box draws a box border.
func (*FrameBuilder) Fill ¶
func (fb *FrameBuilder) Fill(x, y, w, h int, r rune, style Style) *FrameBuilder
Fill fills a rectangle.
func (*FrameBuilder) HLine ¶
func (fb *FrameBuilder) HLine(x, y, length int, r rune, style Style) *FrameBuilder
HLine draws a horizontal line.
func (*FrameBuilder) Text ¶
func (fb *FrameBuilder) Text(x, y int, text string, style Style) *FrameBuilder
Text writes text at position with style.
func (*FrameBuilder) VLine ¶
func (fb *FrameBuilder) VLine(x, y, length int, r rune, style Style) *FrameBuilder
VLine draws a vertical line.
type Region ¶
type Region struct {
X, Y, Width, Height int
}
Region represents a rectangular area of the screen.
type Renderer ¶
type Renderer struct {
// contains filtered or unexported fields
}
Renderer computes minimal ANSI output from screen buffer changes.
func NewRenderer ¶
NewRenderer creates a renderer for the given screen. Synchronized output is enabled by default.
func (*Renderer) ComputeDiffStats ¶
ComputeDiffStats analyzes the current vs previous buffer without rendering.
func (*Renderer) Render ¶
Render computes the diff between current and previous buffers, returns minimal ANSI escape sequences to update the terminal.
func (*Renderer) RenderFull ¶
RenderFull forces a complete redraw (e.g., after resize or initial paint).
func (*Renderer) RenderRegion ¶
RenderRegion renders only a specific region (useful for partial updates).
func (*Renderer) SetSyncOutput ¶
SetSyncOutput enables or disables DEC mode 2026 synchronized output wrapping around rendered frames. When enabled (the default), frames are wrapped in SyncBegin/SyncEnd markers so the terminal can apply changes atomically, eliminating screen tearing.
func (*Renderer) SyncOutput ¶
SyncOutput reports whether synchronized output is enabled.
type Screen ¶
type Screen struct {
// contains filtered or unexported fields
}
Screen manages a double-buffered virtual terminal. It maintains two buffers: current (being built) and previous (last rendered). The diff engine compares these to output minimal ANSI escape sequences.
func (*Screen) Blit ¶
Blit copies a region from another screen onto this one. Useful for compositing overlays.
func (*Screen) ClearCurrentBuffer ¶
func (s *Screen) ClearCurrentBuffer()
ClearCurrentBuffer resets current buffer to empty cells. Call after SwapBuffers to prepare for next frame.
func (*Screen) CopyToPrevious ¶
func (s *Screen) CopyToPrevious()
CopyToPrevious copies current buffer to previous. Use after RenderFull to sync buffers.
func (*Screen) FillRectCell ¶
FillRectCell fills a rectangle with a specific cell.
func (*Screen) Get ¶
Get returns the cell at the given position. Returns EmptyCell if out of bounds.
func (*Screen) GetPrevious ¶
GetPrevious returns the cell from the previous frame.
func (*Screen) Resize ¶
Resize changes screen dimensions, preserving content where possible. Forces a full redraw by resetting the previous buffer.
func (*Screen) Set ¶
Set places a rune at the given position with style. Handles wide characters (CJK) by placing a continuation cell.
func (*Screen) SetString ¶
SetString writes a string starting at position, returns number of columns written.
func (*Screen) SwapBuffers ¶
func (s *Screen) SwapBuffers()
SwapBuffers swaps current and previous buffers, preparing for next frame. Returns the previous current buffer for diff computation.
type StreamRenderer ¶
type StreamRenderer struct {
// contains filtered or unexported fields
}
StreamRenderer provides flicker-free rendering for a streaming text area. It tracks the previous content and outputs only the delta.
func NewStreamRenderer ¶
func NewStreamRenderer(width, height int) *StreamRenderer
NewStreamRenderer creates a renderer for streaming content.
func (*StreamRenderer) Resize ¶
func (sr *StreamRenderer) Resize(width, height int)
Resize updates the dimensions.
func (*StreamRenderer) Update ¶
func (sr *StreamRenderer) Update(content string, style Style) string
Update renders new content, returning optimized ANSI output. If the content hasn't changed, returns empty string.
func (*StreamRenderer) View ¶
func (sr *StreamRenderer) View() string
View returns the current content as a plain string (for fallback).
type Style ¶
type Style struct {
FG Color
BG Color
Bold bool
Dim bool
Italic bool
Underline bool
Blink bool
Reverse bool
Strikethrough bool
}
Style defines visual attributes for a cell.
func (Style) WithItalic ¶
WithItalic returns a copy with italic set.
func (Style) WithReverse ¶
WithReverse returns a copy with reverse set.
func (Style) WithUnderline ¶
WithUnderline returns a copy with underline set.
type SubScreen ¶
type SubScreen struct {
// contains filtered or unexported fields
}
SubScreen creates a view into a region of this screen. Writes to the SubScreen are translated to the parent's coordinate space.
type TableRenderer ¶
type TableRenderer struct {
// contains filtered or unexported fields
}
Table renders a simple table.
func NewTableRenderer ¶
func NewTableRenderer(width, height int, columns []int) *TableRenderer
NewTableRenderer creates a table renderer.
func (*TableRenderer) AddRow ¶
func (tr *TableRenderer) AddRow(cells []string, style Style)
AddRow adds a row of cells.
func (*TableRenderer) AddSeparator ¶
func (tr *TableRenderer) AddSeparator(style Style)
AddSeparator adds a horizontal line.
func (*TableRenderer) Render ¶
func (tr *TableRenderer) Render() string
Render returns the table as a string.
func (*TableRenderer) SetRowHeight ¶
func (tr *TableRenderer) SetRowHeight(h int)
SetRowHeight sets height per row.