Skip to content
docsv0.3.0

Grapheme

Grapheme-aware string utilities. The PHP port of pi-tui's `visibleWidth()` / `truncateToWidth()` / `wrapTextWithAnsi()`, plus the CJK wide-glyph handling pi-tui does via `Intl.Segmenter` grapheme segmentation and a `cjkBreakRegex`. PHP has the `intl` extension, so we lean on `IntlBreakIterator` for grapheme boundaries and `IntlChar::isWide()` / `::isprint()` for the 1-vs-2 column width that CJK ideographs and wide emoji need. Everything here is pure — no state, no I/O. A TUI renderer or layout engine that cares about terminal columns (not byte count, not codepoint count) should go through these helpers rather than `strlen()` / `mb_strlen()`. Wide-character convention (matches xterm / Kitty / WezTerm): - CJK ideographs, full-width Latin, Hangul syllables, wide emoji → 2 cells - Combining marks, zero-width joiners, variation selectors → 0 cells - Everything else printable → 1 cell

Grapheme::visibleWidth()

public static function visibleWidth(string $text): int

Returns the visible column width of `$text`: 2 per wide grapheme, 1 per normal grapheme, 0 per combining/zero-width grapheme. ANSI escape sequences (CSI, OSC, APC) are stripped first so styling does not inflate the count.

Parameters

Parameters of visibleWidth()
NameTypeDescription
$textstring

Grapheme::truncateToWidth()

public static function truncateToWidth(string $text, int $width, string $ellipsis = '…'): string

Truncates `$text` to at most `$width` visible columns, optionally appending an ellipsis (default `…`, U+2026 — 1 cell wide) when the text was cut. Preserves ANSI escapes by truncating only the visible run and emitting a final reset so styles never bleed past the cut. Mirrors pi-tui's `truncateToWidth()` semantics.

Parameters

Parameters of truncateToWidth()
NameTypeDescription
$textstring
$widthint
$ellipsisstring

Grapheme::padEndToWidth()

public static function padEndToWidth(string $text, int $width): string

Pads `$text` on the right with spaces until it is exactly `$width` visible columns wide. Truncates (no ellipsis) when already wider. Preserves ANSI escapes — the visible width is measured, the padding is appended as plain spaces after the final reset.

Parameters

Parameters of padEndToWidth()
NameTypeDescription
$textstring
$widthint

Grapheme::graphemes()

public static function graphemes(string $plain): array

Splits `$plain` (no ANSI) into an array of graphemes, each a string of one or more UTF-8 codepoints that form a single user-perceived character. Uses `IntlBreakIterator::createCharacterInstance` when the `intl` extension is available; falls back to `preg_match_all('/./us')` (codepoint-level) when not.

Parameters

Parameters of graphemes()
NameTypeDescription
$plainstring

Grapheme::graphemeWidth()

public static function graphemeWidth(string $grapheme): int

Returns the visible column width of a single grapheme. Combining marks and zero-width joiners contribute 0; CJK wide chars and wide emoji contribute 2; everything else printable contributes 1.

Parameters

Parameters of graphemeWidth()
NameTypeDescription
$graphemestring