module TUI::Term

Defined in:

tui/core/term.cr

Constant Summary

BJ = "┴"
BL = "╰"
BLINK = "\e[5m"
BOLD = "\e[1m"
BR = "╯"
CJ = "┼"
DIM = "\e[2m"
HL = "─"
ITALIC = "\e[3m"
LJ = "├"
RESET = "\e[0m"
REVERSE = "\e[7m"
RJ = "┤"
STRIKETHROUGH = "\e[9m"
TJ = "┬"
TL = "╭"

Box-drawing characters. Corners are rounded (matching lazygit's border style); T-junctions/cross stay square, which is standard even in rounded-corner box styles (there's no rounded T-junction glyph).

TR = "╮"
UNDERLINE = "\e[4m"
VL = "│"

Class Method Summary

Class Method Detail

def self.apply(style : Style, s : String) : String #

Concatenates the SGR codes for every attribute set on style, then applies them all at once and resets at the end — the composable counterpart to #bold/#dim/#reverse/#fg/#bg, which each only ever apply one attribute and previously had to be manually nested to combine (e.g. Term.fg(:red, Term.bold(s))). A default Style.new (every field false/nil) is a no-op: returns s unchanged.


[View source]
def self.bg(color : Color, s : String) : String #

[View source]
def self.bold(s : String) : String #

[View source]
def self.border_line(segment_widths : Array(Int32), left : String, fill : String, junction : String, right : String) : String #

Composes one horizontal border row: left + N segments of fill repeated to each width, joined by junction, + right. Segment widths are the caller's raw inner width per span — callers add their own padding conventions (e.g. markdown table cells add 2 for the space around cell text; Buffer's box/hline segments don't). Style-agnostic by design: callers either pre-apply style to the glyph args (Buffer) or wrap the plain result afterward (Markdown's InlineRun), so no Style parameter is added here.


[View source]
def self.clear : String #

[View source]
def self.dim(s : String) : String #

[View source]
def self.enter_alt_screen : String #

[View source]
def self.enter_bracketed_paste : String #

Bracketed paste mode (mode 2004): the terminal wraps a pasted block in \e[200~/\e[201~ markers instead of sending it as ordinary keystrokes, so Keys.parse_bracketed_paste can recognize it as one paste operation. This is the only paste-related signal a terminal app can actually receive — there's no way to intercept a native clipboard shortcut (e.g. Cmd-V) itself, since the terminal emulator handles that before the app ever sees any bytes.


[View source]
def self.enter_mouse : String #

SGR extended mouse reporting (mode 1000 reports button/wheel events, mode 1006 switches to the SGR encoding Keys.parse_sgr_mouse expects — plain mode 1000 alone caps coordinates at 223 and uses a different, ambiguous byte encoding).


[View source]
def self.enter_raw : Nil #

[View source]
def self.escape(style : Style) : String #

The full escape sequence for style (e.g. "\e[1;31m"), or "" for a no-op default Style.new — for #overlay, which injects a complete escape sequence after every existing one in a string rather than wrapping start/end like #apply does.


[View source]
def self.exit_raw : Nil #

[View source]
def self.fg(color : Color, s : String) : String #

[View source]
def self.fit(s : String, width : Int32, align : Align = Align::Left) : String #

Pad or truncate to exactly width visible columns. align controls where padding goes when the string is shorter than width — a string needing truncation ignores it (there's no room for padding either way).


[View source]
def self.hide_cursor : String #

[View source]
def self.leave_alt_screen : String #

[View source]
def self.leave_bracketed_paste : String #

[View source]
def self.leave_mouse : String #

[View source]
def self.move(row : Int32, col : Int32) : String #

[View source]
def self.overlay(s : String, code : String) : String #

Layers an extra SGR code (e.g. REVERSE or BOLD) on top of whatever styling s already carries, rather than replacing it — used to highlight a row (cursor/selection) without discarding its cells' own colors. Unlike #bold/#dim/#reverse, this never strips existing codes and never appends a trailing reset, so Buffer#set's per-cell style accumulation picks up both the original color and the overlay for the same cell.


[View source]
def self.reverse(s : String) : String #

[View source]
def self.sgr_code(style : Style) : String #

The bare SGR code string for style, with no wrapping \e[/m/ RESET — the numeric parameters only, e.g. "1;31". Combine with #escape (or use #apply/#overlay directly) to get an actual escape sequence a terminal understands.


[View source]
def self.show_cursor : String #

[View source]
def self.size : NamedTuple(rows: Int32, cols: Int32) #

[View source]
def self.strip_ansi(s : String) : String #

Strip all ANSI escape sequences, returning plain visible text.


[View source]
def self.trunc(s : String, width : Int32) : String #

Truncate string to width visible columns, appending "…" if cut. Preserves embedded ANSI codes up to the cut point (rather than stripping them) so a styled string that needs truncating doesn't lose its color/style — only the characters past width are dropped, exactly like the untruncated case already does.


[View source]
def self.visible_size(s : String) : Int32 #

Visible (printable) length — excludes ANSI escape sequences.


[View source]