compositor

package
v0.6.3 Latest Latest
Warning

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

Go to latest
Published: Jul 22, 2026 License: MIT Imports: 7 Imported by: 0

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

View Source
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

View Source
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 CursorBack

func CursorBack(n int) string

CursorBack moves cursor left n columns.

func CursorDown

func CursorDown(n int) string

CursorDown moves cursor down n lines.

func CursorForward

func CursorForward(n int) string

CursorForward moves cursor right n columns.

func CursorShapeSeq

func CursorShapeSeq(ps int) string

CursorShapeSeq returns the DECSCUSR sequence for the given cursor shape. Ps: 0=default, 2=block, 4=underline, 6=beam.

func CursorTo

func CursorTo(x, y int) string

CursorTo returns ANSI sequence to move cursor to (x, y). Coordinates are 0-indexed, but ANSI uses 1-indexed.

func CursorUp

func CursorUp(n int) string

CursorUp moves cursor up n lines.

func Hyperlink(url, text string) string

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

func RenderToString(width, height int, draw func(*Screen)) string

RenderToString is a convenience function for quick rendering.

func SpinnerFrame

func SpinnerFrame(tick int) rune

SpinnerFrame returns the current spinner character.

func StyleDelta

func StyleDelta(from, to Style) string

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

func StyleToANSI(s Style) string

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

func TextBox

func TextBox(text string, x, y, width, height int, style Style, borderStyle Style) string

TextBox renders text in a box with word wrapping. Returns the rendered output as a string.

func WrapSync

func WrapSync(content string, syncEnabled bool) string

WrapSync wraps content in synchronized output markers. If syncEnabled is false, the content is returned unchanged.

Types

type ANSIWriter

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

ANSIWriter helps build ANSI output efficiently.

func NewANSIWriter

func NewANSIWriter() *ANSIWriter

NewANSIWriter creates a new ANSI writer.

func (*ANSIWriter) Grow

func (w *ANSIWriter) Grow(n int)

Grow pre-allocates buffer capacity.

func (*ANSIWriter) HideCursor

func (w *ANSIWriter) HideCursor()

HideCursor adds cursor hide sequence.

func (*ANSIWriter) Len

func (w *ANSIWriter) Len() int

Len returns current buffer length.

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.

func EmptyCell

func EmptyCell() Cell

EmptyCell returns a blank cell with default style.

func NewCell

func NewCell(r rune, style Style) Cell

NewCell creates a cell with a rune and style.

func (Cell) Empty

func (c Cell) Empty() bool

Empty returns true if the cell is a space with default style.

func (Cell) Equal

func (c Cell) Equal(other Cell) bool

Equal compares two cells for equality.

type Color

type Color struct {
	Mode  ColorMode
	Value uint32 // For 16/256: color index, For RGB: 0xRRGGBB
}

Color represents a terminal color.

func Color256

func Color256(index uint8) Color

Color256 creates a 256-palette color (0-255).

func Hex

func Hex(hex uint32) Color

Hex creates a color from hex value (0xRRGGBB).

func RGB

func RGB(r, g, b uint8) Color

ColorRGB creates a 24-bit true color.

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) Clear

func (c *Compositor) Clear()

Clear clears all buffers.

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) Clear

func (dw *DirectWriter) Clear()

Clear clears all buffers.

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.

func (Region) Contains

func (r Region) Contains(x, y int) bool

Contains checks if a point is within the region.

func (Region) Intersect

func (r Region) Intersect(other Region) Region

Intersect returns the intersection of two regions.

func (Region) IsEmpty

func (r Region) IsEmpty() bool

IsEmpty returns true if the region has zero area.

type Renderer

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

Renderer computes minimal ANSI output from screen buffer changes.

func NewRenderer

func NewRenderer(screen *Screen) *Renderer

NewRenderer creates a renderer for the given screen. Synchronized output is enabled by default.

func (*Renderer) ComputeDiffStats

func (r *Renderer) ComputeDiffStats() DiffStats

ComputeDiffStats analyzes the current vs previous buffer without rendering.

func (*Renderer) Render

func (r *Renderer) Render() string

Render computes the diff between current and previous buffers, returns minimal ANSI escape sequences to update the terminal.

func (*Renderer) RenderFull

func (r *Renderer) RenderFull() string

RenderFull forces a complete redraw (e.g., after resize or initial paint).

func (*Renderer) RenderRegion

func (r *Renderer) RenderRegion(region Region) string

RenderRegion renders only a specific region (useful for partial updates).

func (*Renderer) SetSyncOutput

func (r *Renderer) SetSyncOutput(enabled bool)

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

func (r *Renderer) SyncOutput() bool

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 NewScreen

func NewScreen(width, height int) *Screen

NewScreen creates a new screen buffer with the given dimensions.

func (*Screen) Blit

func (s *Screen) Blit(src *Screen, srcX, srcY, dstX, dstY, w, h int)

Blit copies a region from another screen onto this one. Useful for compositing overlays.

func (*Screen) Box

func (s *Screen) Box(x, y, w, h int, style Style)

Box draws a box border using Unicode box-drawing characters.

func (*Screen) Clear

func (s *Screen) Clear()

Clear resets the current buffer to empty cells.

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) Cursor

func (s *Screen) Cursor() (x, y int, visible bool)

Cursor returns current cursor position and visibility.

func (*Screen) FillRect

func (s *Screen) FillRect(x, y, w, h int, r rune, style Style)

FillRect fills a rectangle with a character and style.

func (*Screen) FillRectCell

func (s *Screen) FillRectCell(x, y, w, h int, cell Cell)

FillRectCell fills a rectangle with a specific cell.

func (*Screen) Get

func (s *Screen) Get(x, y int) Cell

Get returns the cell at the given position. Returns EmptyCell if out of bounds.

func (*Screen) GetPrevious

func (s *Screen) GetPrevious(x, y int) Cell

GetPrevious returns the cell from the previous frame.

func (*Screen) HLine

func (s *Screen) HLine(x, y, length int, r rune, style Style)

HLine draws a horizontal line with a character.

func (*Screen) Resize

func (s *Screen) Resize(width, height int)

Resize changes screen dimensions, preserving content where possible. Forces a full redraw by resetting the previous buffer.

func (*Screen) Set

func (s *Screen) Set(x, y int, r rune, style Style)

Set places a rune at the given position with style. Handles wide characters (CJK) by placing a continuation cell.

func (*Screen) SetCursor

func (s *Screen) SetCursor(x, y int, visible bool)

SetCursor sets the cursor position and visibility.

func (*Screen) SetString

func (s *Screen) SetString(x, y int, str string, style Style) int

SetString writes a string starting at position, returns number of columns written.

func (*Screen) Size

func (s *Screen) Size() (width, height int)

Size returns current dimensions.

func (*Screen) Sub

func (s *Screen) Sub(x, y, w, h int) *SubScreen

Sub creates a SubScreen for a region.

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.

func (*Screen) VLine

func (s *Screen) VLine(x, y, length int, r rune, style Style)

VLine draws a vertical line with a character.

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 DefaultStyle

func DefaultStyle() Style

DefaultStyle returns a style with no attributes.

func (Style) Equal

func (s Style) Equal(other Style) bool

Equal compares two styles for equality.

func (Style) WithBG

func (s Style) WithBG(c Color) Style

WithBG returns a copy with background color set.

func (Style) WithBold

func (s Style) WithBold(b bool) Style

WithBold returns a copy with bold set.

func (Style) WithDim

func (s Style) WithDim(d bool) Style

WithDim returns a copy with dim set.

func (Style) WithFG

func (s Style) WithFG(c Color) Style

WithFG returns a copy with foreground color set.

func (Style) WithItalic

func (s Style) WithItalic(i bool) Style

WithItalic returns a copy with italic set.

func (Style) WithReverse

func (s Style) WithReverse(r bool) Style

WithReverse returns a copy with reverse set.

func (Style) WithUnderline

func (s Style) WithUnderline(u bool) Style

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.

func (*SubScreen) Box

func (ss *SubScreen) Box(style Style)

Box draws a box in the SubScreen's coordinate space.

func (*SubScreen) Clear

func (ss *SubScreen) Clear()

Clear clears the SubScreen region.

func (*SubScreen) FillRect

func (ss *SubScreen) FillRect(x, y, w, h int, r rune, style Style)

FillRect fills a rectangle in the SubScreen's coordinate space.

func (*SubScreen) Set

func (ss *SubScreen) Set(x, y int, r rune, style Style)

Set places a rune in the SubScreen's coordinate space.

func (*SubScreen) SetString

func (ss *SubScreen) SetString(x, y int, str string, style Style) int

SetString writes a string in the SubScreen's coordinate space.

func (*SubScreen) Size

func (ss *SubScreen) Size() (width, height int)

Size returns the SubScreen dimensions.

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.

Jump to

Keyboard shortcuts

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