Module: Tuile::TerminalBackground

Defined in:
lib/tuile/terminal_background.rb,
sig/tuile.rbs

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:

  1. 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.
  2. 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.

Returns:

  • (Float)

    seconds.

0.1
QUERY =

The OSC 11 background-color query, BEL-terminated.

Returns:

  • (String)
"\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.

Returns:

  • (Regexp)
%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.

Returns:

  • (String)
"\e[?2031h"
NOTIFY_OFF =

Disables mode 2031 again; written when the event loop exits.

Returns:

  • (String)
"\e[?2031l"

Class Method Summary collapse

Class Method Details

.detect(input: $stdin, output: $stdout, env: ENV, timeout: QUERY_TIMEOUT) ⇒ Object

Detects the terminal background. Queries OSC 11 when both input and output are TTYs, falling back to COLORFGBG.

@param input — where the OSC 11 reply arrives (the TTY input).

@param output — where the query is written (the TTY output).

@param env — environment for the COLORFGBG fallback; defaults to ENV (which duck-types the [] lookup).

@param timeout — max seconds to wait for the OSC 11 reply.

@return:light, :dark, or nil when undetectable.



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