ANSI-aware terminal-cell measurement and layout.
Terminal width differs from UTF-8 byte length and Unicode rune count. These helpers treat combining marks and joiners as zero-width, common East Asian and emoji characters as two cells, and joined emoji as one grapheme.
Types
TextAlignment = enum alignLeft, alignCenter, alignRight
- Horizontal alignment used by padAnsi. Source Edit
Procs
proc displayWidth(value: string): int {....raises: [], tags: [], forbids: [].}
- Returns the width of the widest line in terminal cells. ANSI controls do not count; combining marks, variation selectors, and joiners do not add a cell; common East Asian and emoji graphemes occupy two cells. Thai and Lao spacing vowels and letters occupy one cell each, while their nonspacing marks stay attached to the base character. Source Edit
proc sliceAnsi(value: string; startCell, maxWidth: int): string {. ...raises: [ValueError], tags: [], forbids: [].}
- Extracts whole graphemes from the first display line while retaining ANSI style and OSC-8 hyperlink state. A wide grapheme is never split. Active styles and hyperlinks are closed at the end of the returned text. Source Edit
proc truncateAnsi(value: string; maxWidth: int; suffix = "…"): string {. ...raises: [ValueError], tags: [], forbids: [].}
- Truncates a single display line and appends suffix when needed. When truncating, active styles and hyperlinks are closed before the suffix. Source Edit
proc wrapAnsi(value: string; width: int; mode = wrapWords): seq[string] {. ...raises: [ValueError], tags: [], forbids: [].}
- Wraps styled text to width cells. Explicit newlines are honored and active SGR and OSC-8 hyperlink state is restored on each produced line. Whitespace at a word-wrap boundary is omitted. ANSI state is carried forward across skipped whitespace and newlines without rescanning earlier lines. Produced lines close their active styles and hyperlinks. Source Edit