module TermBuf::EnvironmentDetector

Overview

Guesses what a terminal can do from the environment it was started in.

This runs before anything is written to the terminal, and it is all a non-interactive session ever gets. It is deliberately pessimistic: a name nobody recognises comes back with nothing, because a screen full of escape sequences is worse than plain text.

Probing runs afterwards and overrides whatever this decided, so being wrong here costs accuracy only where a terminal cannot be asked directly.

Extended Modules

Defined in:

termbuf/caps/environment.cr

Constant Summary

BLINKING = Capability::Blink | Capability::RapidBlink

Blinking text, which some current terminals parse and then ignore.

There is no query for this and terminfo is no help: ghostty's own entry declares blink=\E[5m and nothing on screen blinks. An attribute that is inert rather than harmful is exactly the kind nobody bothers to report accurately, so the only evidence is having looked.

GHOSTTY = (Capabilities::MODERN.flags | KITTY_EXTRAS) & (~BLINKING)

A current terminal that does not blink. Capabilities.normalize drops the rapid variant along with the slow one, so taking both off here is belt and braces.

KITTY_EXTRAS = (Capability::KittyGraphics | Capability::KittyKeyboard) | Capability::KittyColorStack

What kitty and its imitators add on top of a current terminal.

MARKER_VARIABLES = [{"KITTY_WINDOW_ID", Capabilities::MODERN.flags | KITTY_EXTRAS}, {"GHOSTTY_RESOURCES_DIR", GHOSTTY}, {"WEZTERM_PANE", Capabilities::MODERN.flags | Capability::KittyGraphics}, {"WEZTERM_EXECUTABLE", Capabilities::MODERN.flags | Capability::KittyGraphics}, {"ALACRITTY_WINDOW_ID", Capabilities::MODERN.flags}, {"KONSOLE_VERSION", (Capabilities::XTERM.flags | Capability::TrueColor) | Capability::Osc8Links}, {"ITERM_SESSION_ID", Capabilities::MODERN.flags}]

Set by a terminal that has no TERM_PROGRAM of its own.

PROGRAM_PATTERNS = [{"ghostty", GHOSTTY}, {"WezTerm", Capabilities::MODERN.flags | Capability::KittyGraphics}, {"iTerm.app", Capabilities::MODERN.flags}, {"vscode", Capabilities::MODERN.flags}, {"Hyper", Capabilities::XTERM.flags | Capability::TrueColor}, {"rio", Capabilities::MODERN.flags}, {"alacritty", Capabilities::MODERN.flags}, {"Apple_Terminal", Capabilities::XTERM.flags}]

Matched against TERM_PROGRAM. These beat the TERM guess, since the terminal names itself here rather than naming its terminfo entry.

TERM_PATTERNS = [{/\Adumb/, Capability::None}, {/kitty/, Capabilities::MODERN.flags | KITTY_EXTRAS}, {/ghostty/, GHOSTTY}, {/wezterm/, Capabilities::MODERN.flags | Capability::KittyGraphics}, {/alacritty/, Capabilities::MODERN.flags}, {/\Afoot/, Capabilities::MODERN.flags}, {/\Acontour/, Capabilities::MODERN.flags}, {/\Ario/, Capabilities::MODERN.flags}, {/(256color|direct)/, Capabilities::XTERM.flags}, {/\A(xterm|screen|tmux|rxvt|vte|gnome|konsole|st|ansi|linux|putty|eterm)/, Capabilities::ANSI.flags}, {/\Avt(2|3|4|5)\d\d/, Capabilities::ANSI.flags}, {/\Avt100/, ((((Capability::Bold | Capability::Underline) | Capability::Reverse) | Capability::Blink) | Capability::ScrollRegion) | Capability::AltScreen}]

Matched against TERM, most specific first.

THROUGH_MULTIPLEXER = (KITTY_EXTRAS | Capability::KittyGraphicsTempFile) | Capability::SynchronizedOutput

A multiplexer sits between the application and the terminal and does not forward everything. The kitty protocols in particular are swallowed, so they come off until a probe says otherwise.

Instance Method Summary

Instance Method Detail

def denials(name : String | Nil) : Capability #

Capabilities name is known not to have, whatever else in the environment implies one.

This is separate from the pattern tables because composition is additive: under ghostty with a TERM of xterm-256color, the xterm entry would put blink back after the ghostty entry left it out. A name that identifies the terminal outranks one that only describes a family.


[View source]
def detect(env : Hash(String, String)) : Capabilities #

Guesses from TERM, TERM_PROGRAM, COLORTERM, VTE_VERSION, and the marker variables terminals set for themselves.


[View source]