module Foundation

Defined in:

foundation/ansi.cr
foundation/color_space.cr
foundation/env.cr
foundation/palette.cr
foundation/profile.cr
foundation/sgr.cr
foundation/width.cr

Constant Summary

CSI = "\e["

Control Sequence Introducer

ESCAPE_PATTERN = /\ \e\[ [\x30-\x3F]* [\x20-\x2F]* [\x40-\x7E] # CSI | \e\] .*? (?: \x07 | \e\\ ) # OSC (terminated by BEL or ST) | \e [\x20-\x7E] # other two-byte ESC /x

Matches a single ANSI escape sequence: CSI, OSC (Operating System Command) with BEL (Bell) or ST (String Terminator), or two byte ESC. No need for full parsing here, a regex is sufficient for stripping these.

RESET_HYPERLINK = "\e]8;;\e\\"

Closes any open hyperlink span, to be placed after the linked text.

RESET_STYLE = "\e[0m"
SGR_PATTERN = /\e\[([0-9;:]*)m/

Matches a single SGR sequence, capturing its parameter bytes (digits, ';', and ':')

ST = "\e\\"

String Terminator for OSC sequences

Class Method Summary

Class Method Detail

def self.cut(string : String, start : Int32, finish : Int32) : String #

Returns the slice of string between visible cell positions start (inclusive) and finish (exclusive), preserving ANSI sequences.


[View source]
def self.downsample(rgb : RGB, profile : Profile) : SGRColor | Nil #

Returns the best SGR color for rgb at profile, or nil if the profile has no color. Nearest color is found by CIELAB ΔE76 distance.


[View source]
def self.each_segment(string : String, & : SegmentKind, String -> ) : Nil #

Splits string into ordered segments, yielding kind, content for each segment. Text and various escape sequences are separated so callers can measure or slice visible content while preserving and tracking embedded ANSI.


[View source]
def self.grapheme_width(grapheme : String) : Int32 #

Returns the terminal cell-width of a single grapheme cluster:

  • 0 for zero-width control/combining
  • 2 for wide East-Asian and emoji clusters
  • 1 otherwise

[View source]
def self.hyperlink(url : String, **params) : String #

Opens a hyperlink span pointing to url. Optional params are encoded as k=v pairs joined by ':'.

Trust the caller. Caller is responsible for ensuring that url is free of control characters.


[View source]
def self.parse_sgr(string : String) : Attributes #

Parses every SGR sequence found in string and folds them into one Attributes. Text, OSC, and non-SGR escapes are ignored, and malformed input never raises.

TODO Refactor, this is crazy complex fr fr


[View source]
def self.string_width(string : String) : Int32 #

Returns visible width of string in terminal cells. Grapheme clusters are the measurement unit, ANSI escape sequences count as zero.


[View source]
def self.strip(string : String) : String #

Strips all ANSI escape sequences from string, leaving only printable content.


[View source]
def self.truncate(string : String, width : Int32, tail : String = "") : String #

Truncates string to a visible width of at most width, appending tail when truncation occurs. ANSI escape sequences are never broken. Width is measured in terminal cells over grapheme clusters.


[View source]
def self.truncate_left(string : String, n : Int32, prefix : String = "") : String #

Truncate string from the left by n visible cells, prepending prefix when content is removed. ANSI escape sequences from the removed region are preserved so leading style is always retained.


[View source]
def self.wrap(string : String, width : Int32, breakpoints : String = " -") : String #

Wraps string to lines of at most width visible cells, preferring word boundaries and hard-breaking tokens longer than width. Width is measured in terminal cells over grapheme clusters.

ANSI escape sequences and OSC8 hyperlinks are preserved across breaks. A hyphen is always a breakpoint, as well as any character in breakpoints.


[View source]