cellbuf

package
v0.0.0-...-ec0414e Latest Latest
Warning

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

Go to latest
Published: Jul 28, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

Documentation

Overview

Package cellbuf provides agentui's cell-grid model: a Buffer of styled grapheme cells, a diff-based ANSI emitter that writes only changed cells (or scrolls an unchanged vertical row run), cursor-command de-duplication that preserves the terminal's cursor blink timer, and synchronized-output framing (CSI 2026).

The design is a Go port of the rendering substrate used by xai-grok-pager (ratatui Buffer + custom draw path, Apache-2.0). Frames are rendered into a back Buffer, diffed against the front Buffer, and emitted as a minimal escape-sequence byte stream.

Index

Constants

View Source
const (
	BeginSync = "\x1b[?2026h"
	EndSync   = "\x1b[?2026l"
)

Synchronized-output markers (CSI ? 2026 h / l). Every frame is wrapped in a Begin/End pair so the terminal applies it atomically — critical to avoid flicker under tmux/zellij.

Variables

This section is empty.

Functions

func AppendSGR

func AppendSGR(out *[]byte, prev, next Style)

AppendSGR appends the SGR sequence that switches from prev style to next. A zero next style emits a bare reset when prev is non-zero.

func EmitDiff

func EmitDiff(out *[]byte, prev, next *Buffer) (changed bool)

EmitDiff computes the difference between prev and next and appends to out the minimal escape stream that transforms the screen: cursor moves only when the run is not adjacent, SGR emitted only when the style changes, and continuation cells skipped. Buffers must be the same size. Returns true if any cell was changed.

When the changed full-width rows are a pure vertical shift, EmitDiff may temporarily install a DECSTBM scrolling region and use CSI S/T before painting only the newly exposed rows. The optimization is deliberately conservative: at least two rows must survive the shift, all rows outside the region must be identical, and the scroll stream must be shorter than a proven lower bound for the ordinary cell diff. Any unmatched or marginal case falls back to the ordinary diff.

EmitDiff does not touch cursor visibility; callers wrap the frame with CursorState.Apply and (optionally) synchronized-update markers.

func EmitFull

func EmitFull(out *[]byte, next *Buffer)

EmitFull appends the escape stream for a full repaint of next (every cell, no diffing) — used after Invalidate or terminal resize.

func EncodeRow

func EncodeRow(cells []Cell) string

EncodeRow serializes one physical cell row into terminal-ready inline text. It emits only SGR/OSC8 state transitions and printable graphemes: no CUP, erase, CR or LF. The returned string always closes an open hyperlink and resets a non-default style, so callers may safely concatenate it with scrolling-region operations.

Types

type AttrMask

type AttrMask uint8

AttrMask is a bit set of text attributes.

const (
	AttrBold AttrMask = 1 << iota
	AttrDim
	AttrItalic
	AttrUnderline
	AttrReverse
	AttrStrike
)

type Buffer

type Buffer struct {
	W, H  int
	Cells []Cell
}

Buffer is a W×H grid of cells, row-major.

func NewBuffer

func NewBuffer(w, h int) *Buffer

NewBuffer returns a buffer of the given size filled with default cells.

func (*Buffer) Cell

func (b *Buffer) Cell(x, y int) *Cell

Cell returns the cell at (x, y), or nil when out of bounds.

func (*Buffer) CopyRows

func (b *Buffer) CopyRows(src *Buffer, srcTop, dstTop, n int)

CopyRows copies n full rows from src starting at srcTop into b starting at dstTop. Rows outside either buffer are skipped. Used for scratch-buffer partial rendering of clipped entries.

func (*Buffer) Fill

func (b *Buffer) Fill(r Rect, st Style)

Fill sets every cell inside r (clipped to the buffer) to a width-1 cell with empty content and the given style.

func (*Buffer) Reset

func (b *Buffer) Reset()

Reset clears every cell to the default (empty content, width 1, zero style).

func (*Buffer) Resize

func (b *Buffer) Resize(w, h int)

Resize grows or shrinks the buffer, clearing all content.

func (*Buffer) SetString

func (b *Buffer) SetString(x, y int, s string, st Style, clip Rect) int

SetString writes s starting at (x, y) with style st, clipping at the buffer edge and at clip.X+clip.W. Grapheme-aware: wide clusters occupy two cells (head + continuation) and are never split — a wide cluster that would straddle the boundary is dropped and the head cell padded with a space. Returns the number of columns advanced.

type Cell

type Cell struct {
	Content string
	Width   uint8 // 1 or 2; 0 = continuation of the wide cell to the left
	Style   Style
	// Link is an OSC 8 hyperlink target associated with this cell. It is
	// intentionally cell metadata rather than an SGR Style field because
	// hyperlink state has its own open/close protocol.
	Link string
}

Cell is one terminal cell. Content is a full grapheme cluster; the cell to the right of a width-2 cell is a continuation cell with Width == 0 and empty Content. An empty Content with Width == 1 renders as a space.

type Color

type Color struct {
	Set bool
	RGB RGB
}

Color is either the terminal default (Set == false) or a truecolor value.

func Blend

func Blend(base, top Color, opacity float64) Color

Blend linearly blends base toward top with opacity in [0,1]. If either color is unset the result is top unchanged.

func C

func C(r, g, b uint8) Color

C returns a set Color.

type CursorPos

type CursorPos struct {
	Visible bool
	X, Y    int
}

CursorPos is the desired cursor state after a frame.

type CursorState

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

CursorState de-duplicates cursor escape sequences across frames so an idle frame emits zero cursor commands and the terminal's cursor blink timer is never reset. Port of xai-grok-pager's CursorState (render/draw.rs):

  • no cell changes + same position → emit nothing (blink preserved)
  • cells changed + same position → MoveTo only (re-anchor after writes)
  • position changed → MoveTo (blink reset is expected)
  • visibility transition → Show/Hide only on the actual edge

func (*CursorState) Apply

func (c *CursorState) Apply(w io.Writer, next CursorPos, cellsChanged bool) error

Apply writes the minimal cursor commands for next given whether the frame wrote any cells, and records the new state.

func (*CursorState) Invalidate

func (c *CursorState) Invalidate()

Invalidate forgets the tracked state (e.g. after an external program used the terminal); the next Apply re-emits everything.

type RGB

type RGB struct{ R, G, B uint8 }

RGB is a 24-bit color.

type Rect

type Rect struct{ X, Y, W, H int }

Rect is a rectangle in buffer coordinates.

func (Rect) Contains

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

Contains reports whether (x, y) lies inside r.

type Style

type Style struct {
	FG, BG Color
	Attr   AttrMask
}

Style is the visual style of a cell.

Jump to

Keyboard shortcuts

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