class Tput::Features

Overview

Terminal features auto-detection.

Detection depends on the terminal emulator (Tput::Emulator) and the term type (ENV["TERM"]), both of which must be known before feature detection runs.

Included Modules

Defined in:

tput/dump.cr
tput/features.cr

Constant Summary

BASELINE_PROBE_SOURCE = "not probed (call Tput#probe!)"

Provenance recorded for probe-only fields before any probe runs. After Tput#probe! runs (see #mark_probed!), a field still carrying this baseline means "asked but not reported".

DA1_ATTR = {1 => "132 columns", 2 => "printer", 3 => "ReGIS graphics", 4 => "sixel graphics", 6 => "selective erase", 7 => "soft fonts (DRCS)", 8 => "user-defined keys", 9 => "national replacement charsets", 15 => "technical characters", 16 => "locator port", 17 => "terminal state interrogation", 18 => "windowing", 21 => "horizontal scrolling", 22 => "ANSI color", 28 => "rectangular editing", 29 => "ANSI text locator"}

DA1 feature attributes (the parameters after the conformance level).

DA1_CLASS = {1 => "VT100", 2 => "VT100 (AVO)", 6 => "VT102", 7 => "VT131", 12 => "VT125", 62 => "VT220", 63 => "VT320", 64 => "VT420", 65 => "VT510"}

DA1 first-parameter conformance levels (CSI ? Pp ; … c).

DA2_TYPE = {0 => "VT100", 1 => "VT220", 2 => "VT240", 18 => "VT330", 19 => "VT340", 24 => "VT320", 32 => "VT382", 41 => "VT420", 61 => "VT510", 64 => "VT520", 65 => "VT525"}

DA2 first-parameter terminal-type codes (CSI > Pp ; Pv ; Pc c). Modern emulators reuse a base code (often 0 or 41) and encode their build in Pv (see #da2_decoded).

Log = ::Log.for((self.name.gsub("::", '.')).underscore)

Constructors

Instance Method Summary

Constructor Detail

def self.new(pull : JSON::PullParser) #

[View source]
def self.new(tput : Tput) #

[View source]

Instance Method Detail

def acsc : ACSHash #

[View source]
def acscr : ACSHash #

[View source]
def ambiguous_width : Int32 | Nil #

Rendered width (in cells) of an ambiguous-width character, measured via DSR/CPR. 1 = narrow, 2 = wide; nil if not probed.


[View source]
def ambiguous_width=(ambiguous_width : Int32 | Nil) #

Rendered width (in cells) of an ambiguous-width character, measured via DSR/CPR. 1 = narrow, 2 = wide; nil if not probed.


[View source]
def ansi_cursor? : Bool #

Whether the terminal's cursor-movement capabilities (cup, cuu, cud, cuf, cub) are byte-for-byte standard ANSI/VT100. When true, Tput builds sequences directly instead of paying a tparm FFI call per move (~6x faster; cursor moves dominate frame rendering). Verified at startup by running each capability through terminfo and comparing to the canonical ANSI sequence; any deviation falls back to the terminfo path.


[View source]
def ansi_edit? : Bool #

Like #ansi_cursor?, but for the line-editing capabilities ich, il, dl, dch, ech and rep (insert/delete/erase chars and lines).


[View source]
def ansi_hpa? : Bool #

Like #ansi_cursor?, but for the column-address capability hpa (cursor_char_absolute / char_pos_absolute).


[View source]
def ansi_scroll? : Bool #

Like #ansi_cursor?, but for the scroll capabilities csr (scroll region), parm_index (SU) and parm_rindex (SD).


[View source]
def ansi_vpa? : Bool #

Like #ansi_cursor?, but for the row-address capability vpa (cursor_line_absolute).


[View source]
def broken_acs? : Bool #

Does the terminal have broken ACS chars?


[View source]
def color? : Bool #

Color support flag (a yes/no)


[View source]
def confirm_cursor_color!(source : String) : Nil #

Marks the hardware cursor as recolorable after a successful live probe.


[View source]
def confirm_cursor_style!(source : String) : Nil #

Marks the hardware cursor as styleable (shape/blink) after a successful live probe, recording source as provenance.


[View source]
def confirm_kitty_keyboard!(flags : Int32, source : String) : Nil #

Records that the terminal speaks the kitty keyboard protocol; flags are the active enhancement bits it reported. Called by Tput#probe!.


[View source]
def confirm_modify_other_keys!(level : Int32, source : String) : Nil #

Records the terminal's modifyOtherKeys level. Called by Tput#probe!.


[View source]
def confirm_truecolor!(source : String) : Nil #

Marks the terminal as 24-bit truecolor-capable (e.g. after a successful live probe), updating derived color fields and recording source as provenance for both truecolor and #number_of_colors.


[View source]
def cursor_color=(cursor_color : Bool) #

Does the terminal support recoloring its hardware cursor via OSC 12 (OSC 12 ; color ST)? Upgraded to confirmed true by Tput#probe! when the terminal answers an OSC 12 color query.


[View source]
def cursor_color? : Bool #

Does the terminal support recoloring its hardware cursor via OSC 12 (OSC 12 ; color ST)? Upgraded to confirmed true by Tput#probe! when the terminal answers an OSC 12 color query.


[View source]
def cursor_style=(cursor_style : Bool) #

Does the terminal support styling its hardware cursor — shape and blink via DECSCUSR (CSI Ps SP q), or iTerm2's proprietary OSC 50? Detected from the emulator/term name, upgraded to confirmed true by Tput#probe! when a DECRQSS readback succeeds. When false, Crysterm draws an artificial cursor instead (see Screen#apply_cursor).


[View source]
def cursor_style? : Bool #

Does the terminal support styling its hardware cursor — shape and blink via DECSCUSR (CSI Ps SP q), or iTerm2's proprietary OSC 50? Detected from the emulator/term name, upgraded to confirmed true by Tput#probe! when a DECRQSS readback succeeds. When false, Crysterm draws an artificial cursor instead (see Screen#apply_cursor).


[View source]
def da2_decoded : String | Nil #

Human-readable decode of the probed DA2 reply: terminal type and firmware/version field. nil when not probed/answered.


[View source]
def da2_params : Array(Int32) | Nil #

Secondary device-attributes (DA2, CSI > c) parameters [type, version, keyboard], or nil if not probed/unanswered. More reliable than the env-var heuristics in Emulator.


[View source]
def da2_params=(da2_params : Array(Int32) | Nil) #

Secondary device-attributes (DA2, CSI > c) parameters [type, version, keyboard], or nil if not probed/unanswered. More reliable than the env-var heuristics in Emulator.


[View source]
def da_decoded : Array(String) #

Human-readable decode of the probed DA1 reply: conformance class followed by each recognized feature attribute. Empty when not probed/answered.


[View source]
def da_params : Array(Int32) | Nil #

Numeric parameters from the DA1 (CSI c) device-attributes reply.


[View source]
def da_params=(da_params : Array(Int32) | Nil) #

Numeric parameters from the DA1 (CSI c) device-attributes reply.


[View source]
def default_background : RGB | Nil #

Default background color reported via OSC 11.


[View source]
def default_background=(default_background : RGB | Nil) #

Default background color reported via OSC 11.


[View source]
def default_foreground : RGB | Nil #

Default foreground color reported via OSC 10.


[View source]
def default_foreground=(default_foreground : RGB | Nil) #

Default foreground color reported via OSC 10.


[View source]
def detect_ansi_cursor #

[View source]
def detect_ansi_edit #

ich/il/dl/dch/ech (line-editing) verified standard ANSI.

rep is deliberately excluded: terminfo's rep is two-parameter, emitting the character and the repeat (%p1%c%p2%{1}%-%db, e.g. xterm), so it's not byte-equal to the one-parameter CSI Pn b this fast path would build — it would never verify, pinning the whole group to the tparm path. repeat_preceding_character keeps its own put(&.rep?) route instead.


[View source]
def detect_ansi_hpa #

hpa (column_address, CHA — CSI Ps G) verified standard ANSI.


[View source]
def detect_ansi_scroll #

csr (DECSTBM)/parm_index (SU)/parm_rindex (SD) verified standard ANSI.


[View source]
def detect_ansi_vpa #

vpa (row_address, VPA — CSI Ps d) verified standard ANSI.


[View source]
def detect_broken_acs #

Detects whether terminal has broken ACS characters


[View source]
def detect_cursor_color #

Detects whether the terminal can recolor its hardware cursor (OSC 12).


[View source]
def detect_cursor_style #

Detects whether the terminal can style its hardware cursor (shape/blink).

No terminfo capability for DECSCUSR exists in the base set, so this is a conservative best-effort guess from the emulator/term name; Tput#probe! confirms the rest at runtime via a DECRQSS readback.


[View source]
def detect_magic_cookie #

[View source]
def detect_number_of_colors #

Detects number of colors supported by the terminal (2 - 16M)


[View source]
def detect_padding #

[View source]
def detect_pc_rom_charset #

Detects whether terminal supports PC ROM charset


[View source]
def detect_setbuf #

[View source]
def detect_truecolor #

Detects whether the terminal supports 24-bit direct ("true") color.

No single channel is universal, so check in order of reliability:

  • COLORTERM=truecolor/24bit — env hint from most modern emulators.
  • terminfo RGB — ncurses' direct-color capability (any form counts).
  • terminfo Tc — older tmux/community extended-boolean convention.
  • terminfo Max_colors >= 16_777_216 — full 24-bit space declared directly.
  • terminfo setrgbf/setrgbb — direct-color fg/bg setter strings.

[View source]
def detect_unicode #

Detects Unicode support


[View source]
def detections : Hash(String, Tput::Detection) #

All feature detections (static + probed) in one map.


[View source]
def get_console_cp #

Gets console codepage (Windows-specific)


[View source]
def in_band_resize=(in_band_resize : Bool) #

Whether the terminal supports in-band resize notifications (DEC private mode 2048), probed via DECRQM at startup. When true, a consumer can prefer in-band resize reports over SIGWINCH.


[View source]
def in_band_resize? : Bool #

Whether the terminal supports in-band resize notifications (DEC private mode 2048), probed via DECRQM at startup. When true, a consumer can prefer in-band resize reports over SIGWINCH.


[View source]
def inspect(io) #

[View source]
def kitty_keyboard? : Bool #

Whether the terminal speaks the kitty keyboard protocol (it answered the CSI ? u probe).


[View source]
def kitty_keyboard_flags : Int32 | Nil #

Kitty keyboard protocol flags reported in answer to a CSI ? u query, or nil if unanswered (unsupported). A non-nil value — even 0 — means the protocol is supported; the number is the active enhancement flags. See Tput::Keyboard.


[View source]
def kitty_keyboard_flags=(kitty_keyboard_flags : Int32 | Nil) #

Kitty keyboard protocol flags reported in answer to a CSI ? u query, or nil if unanswered (unsupported). A non-nil value — even 0 — means the protocol is supported; the number is the active enhancement flags. See Tput::Keyboard.


[View source]
def magic_cookie? : Bool #

[View source]
def mark_probed! : Nil #

Records that a live probe has run, rewriting any field still carrying BASELINE_PROBE_SOURCE to say a probe ran and got no reply (rather than the now-misleading "not probed"). Called by Tput#probe!.


[View source]
def modify_other_keys : Int32 | Nil #

The xterm modifyOtherKeys level reported in answer to a CSI ? 4 m query (0, 1, or 2), or nil if unanswered. See Tput::Keyboard.


[View source]
def modify_other_keys=(modify_other_keys : Int32 | Nil) #

The xterm modifyOtherKeys level reported in answer to a CSI ? 4 m query (0, 1, or 2), or nil if unanswered. See Tput::Keyboard.


[View source]
def modify_other_keys? : Bool #

Whether the terminal supports xterm modifyOtherKeys (it answered the CSI ? 4 m probe).


[View source]
def number_of_colors : Int32 #

Number of colors supported by the terminal


[View source]
def padding? : Bool #

[View source]
def palette : Array(RGB | Nil) #

The 16 indexed palette colors reported via OSC 4 (nil per entry until probed, or if the terminal didn't answer for that index).


[View source]
def palette=(palette : Array(RGB | Nil)) #

The 16 indexed palette colors reported via OSC 4 (nil per entry until probed, or if the terminal didn't answer for that index).


[View source]
def parse_acs #

Parses terminal's ACS characters and returns ASCII->ACS and ACS->ASCII mappings.


[View source]
def pc_rom_charset? : Bool #

Does the terminal support PC ROM charset?


[View source]
def pixel_mouse=(pixel_mouse : Bool) #

Whether the terminal supports SGR-Pixels mouse reporting (DEC private mode 1016), probed via DECRQM at startup. When true, a consumer can enable pixel-resolution mouse coordinates (see Output::Mouse#enable_mouse's pixels argument). Independent of whether the terminal reports a cell pixel size — a consumer still needs that to derive cell coordinates.


[View source]
def pixel_mouse? : Bool #

Whether the terminal supports SGR-Pixels mouse reporting (DEC private mode 1016), probed via DECRQM at startup. When true, a consumer can enable pixel-resolution mouse coordinates (see Output::Mouse#enable_mouse's pixels argument). Independent of whether the terminal reports a cell pixel size — a consumer still needs that to derive cell coordinates.


[View source]
def probed=(probed : Bool) #

Whether a live probe (Tput#probe!) has run. Distinguishes "asked but not reported" from "no probe has happened yet" so Tput#dump can stop saying "(not probed)" once probing occurs.


[View source]
def probed? : Bool #

Whether a live probe (Tput#probe!) has run. Distinguishes "asked but not reported" from "no probe has happened yet" so Tput#dump can stop saying "(not probed)" once probing occurs.


[View source]
def probed_detections : Hash(String, Tput::Detection) #

{name => Detection} for the live-probed features. Values read (not probed) until Tput#probe! has run and the terminal replied.


[View source]
def setbuf? : Bool #

[View source]
def sources : Hash(String, String) #

For each detected field (by name), a human-readable description of how its value was determined (env var, Tput constructor option, terminfo capability, or live probing). Populated by detect_* and Tput#probe!. Surfaced via Tput#dump.


[View source]
def static_detections : Hash(String, Tput::Detection) #

{name => Detection} for the statically-detected features (env vars, terminfo, constructor options).


[View source]
def terminal_version : String | Nil #

Terminal name and version as reported by XTVERSION (CSI > 0 q), e.g. "kitty(0.32.0)", or nil if not probed/unanswered.


[View source]
def terminal_version=(terminal_version : String | Nil) #

Terminal name and version as reported by XTVERSION (CSI > 0 q), e.g. "kitty(0.32.0)", or nil if not probed/unanswered.


[View source]
def truecolor=(truecolor : Bool) #

Does the terminal support 24-bit direct ("true") color? Set by #detect_truecolor, upgraded to true by Tput#probe! if a live DECRQSS readback confirms it (see Tput::Probe).


[View source]
def truecolor? : Bool #

Does the terminal support 24-bit direct ("true") color? Set by #detect_truecolor, upgraded to true by Tput#probe! if a live DECRQSS readback confirms it (see Tput::Probe).


[View source]
def unicode? : Bool #

Is unicode supported?


[View source]