Module: Tuile::TerminalBackground
- Defined in:
- lib/tuile/terminal_background.rb
Overview
Detects whether the terminal background is light or dark, so Screen can pick Tuile::Theme::LIGHT or Tuile::Theme::DARK automatically at startup.
Two mechanisms, in order of reliability:
-
**OSC 11 query** — writes ‘ESC ] 11 ; ? BEL` to the terminal; modern terminals (xterm, kitty, alacritty, wezterm, iTerm2, GNOME Terminal, Windows Terminal) reply on stdin with the background color (`e]11;rgb:RRRR/GGGG/BBBB` + BEL or ST). The color’s relative luminance against a 0.5 threshold decides light vs dark. Terminals that don’t support the query simply never reply, so the read is bounded by a short timeout.
-
**‘COLORFGBG` env var** — rxvt/konsole export `“fg;bg”` ANSI palette indices. Less reliable (stale across SSH/tmux, often unset); used only when OSC 11 yields nothing.
**Timing matters**: the OSC 11 reply arrives on stdin, so the query must complete before EventQueue#start_key_thread owns stdin —otherwise the reply bytes get consumed as garbage keystrokes. Screen calls TerminalBackground.detect from its constructor, which apps run before Screen#run_event_loop; don’t call this after the event loop started.
Constant Summary collapse
- QUERY_TIMEOUT =
How long to wait for the OSC 11 reply. Generous for a local terminal; bounded so unsupporting terminals (which never reply) don’t stall startup.
0.1- QUERY =
The OSC 11 background-color query, BEL-terminated.
"\e]11;?\a"- REPLY =
Matches the OSC 11 reply. Components are 1–4 hex digits each (terminals vary); ‘rgba:` (4 components) also matches — the alpha tail is ignored.
%r{\e\]11;rgba?:(\h{1,4})/(\h{1,4})/(\h{1,4})}- NOTIFY_ON =
Enables mode 2031: the terminal pushes a color-scheme report (‘e[?997;1n` dark / `e[?997;2n` light) whenever the OS appearance flips — see EventQueue::ColorSchemeEvent. Terminals without support ignore the sequence. Written by Screen#run_event_loop.
"\e[?2031h"- NOTIFY_OFF =
Disables mode 2031 again; written when the event loop exits.
"\e[?2031l"
Class Method Summary collapse
-
.detect(input: $stdin, output: $stdout, env: ENV, timeout: QUERY_TIMEOUT) ⇒ Symbol?
Detects the terminal background.
Class Method Details
.detect(input: $stdin, output: $stdout, env: ENV, timeout: QUERY_TIMEOUT) ⇒ Symbol?
Detects the terminal background. Queries OSC 11 when both ‘input` and `output` are TTYs, falling back to `COLORFGBG`.
63 64 65 66 |
# File 'lib/tuile/terminal_background.rb', line 63 def detect(input: $stdin, output: $stdout, env: ENV, timeout: QUERY_TIMEOUT) osc = query_osc11(input, output, timeout) if input.tty? && output.tty? osc || from_colorfgbg(env["COLORFGBG"]) end |