← All libraries

CandyBuffer

🍬 CandyBuffer

Cell-grid value objects for terminal rendering

port of charmbracelet/vte buffer cell-grid leaf-package

Immutable Buffer (2-D cell grid) and Cell (rune, style, link, width) value objects forming the shared data model for terminal rendering across the SugarCraft ecosystem. Wide-char (CJK/emoji) handled via width=2 with mandatory continuation cells.

Install

composer require sugarcraft/candy-buffer

Quickstart

use SugarCraft\Buffer\Buffer;
use SugarCraft\Buffer\Cell;
use SugarCraft\Buffer\Style;

// Create a 20x3 buffer filled with blank cells.
$buf = Buffer::new(20, 3);

// Set a cell at (col=5, row=1).
$buf = $buf->withCellAt(5, 1, Cell::new('H'));

// Blit a 2x2 sub-buffer at origin.
$sub = Buffer::new(2, 2)->withCellAt(0, 0, Cell::new('A'));
$buf = $buf->withRegion($sub, Buffer::new(2, 2));

// Read a cell back.
$cell = $buf->cellAt(5, 1);
echo $cell->rune(); // 'H'

// Access dimensions.
echo $buf->width();  // 20
echo $buf->height(); // 3

What's in the box

BufferImmutable 2-D cell grid with fluent with*() mutation. Bounds-checked cellAt() throws OutOfRangeException. Private mutate() pattern for with*() methods.
CellReadonly value object: rune (string), style (?Style), link (?Hyperlink), width (int). Cell::continuation() for wide-char neighbour cells. No with*() — rebuild via new.
Position2-D coordinate (col, row) with bare accessors. Mirrors charmbracelet/vte Position.
RegionRectangular sub-region defined by Position origin + width/height. contains() helper for hit-testing.
Style (minimal)Stripped-down per-cell style: fg (0xRRGGBB), bg (0xRRGGBB), attrs (bitmask). Rich styling lives in candy-sprinkles/Style.
HyperlinkOSC 8 anchor — url and optional id grouping field.
Wide char handlingwidth=2 cells (CJK, emoji) require a width=0 continuation cell at col+1. Callers are responsible for placing continuation cells correctly.

Use it for

Source & demos

TODO: Buffer::diff()

The Buffer::diff() method is declared but not yet implemented. Step-26 (step-14/15/16/17/18 consumer migration unblocked first) implements the delta-ANSI emitter supporting ECH/REP/ICH/DCH sequences for bandwidth-efficient SSH rendering.

Try the quickstart →

API

ClassMethodDescription
Buffernew(int, int)Factory: creates width×height grid of blank cells
BuffercellAt(int, int)Bounds-checked cell accessor; throws OutOfRangeException
BufferwithCellAt(int, int, Cell)Immutable cell setter; returns new Buffer
BufferwithRegion(Region, Buffer)Blit source Buffer into this Buffer's region; returns new Buffer
Bufferwidth(), height(), region()Dimension accessors
Bufferdiff(Buffer)Stub — returns []; step-26 implements delta-ANSI emitter
Cellnew(string, ?Style, ?Hyperlink, int)Factory with rune, style, link, width (1 or 2)
Cellrune(), style(), link(), width()Property accessors
Cellcontinuation()Factory: empty rune, null style/link, width=0
Positionnew(int, int)Factory: col, row
Regionnew(Position, int, int)Factory: origin, width, height
Regioncontains(int, int)Hit-test a cell coordinate
Stylenew(?int, ?int, int)Factory: fg (0xRRGGBB), bg, attrs bitmask
Hyperlinknew(string, string)Factory: url, id