Feature Description
Automatic RGB-to-ANSI color downgrade when the terminal doesn't support truecolor.
Problem or Use Case
Ratatui + crossterm doesn't do any terminal color capability detection. When a theme uses Color::Rgb values (which all the built-in themes except Default already do), xleak emits raw RGB escape codes on the assumption the user's terminal is capable of correctly rendering. On terminals that don't support truecolor — macOS Terminal.app is the big one — the result is garbled or blinking text rather than a graceful fallback.
In #47 I added a basic COLORTERM env var check that warns on stderr if truecolor isn't advertised. It's cool to print a warning, it's cooler to gracefully handle the error.
Proposed Solution
When the terminal doesn't advertise truecolor support, map each Color::Rgb(r, g, b) in the active theme to the nearest ANSI-256 color. The math is a Euclidean distance search against the 256-color palette, there's a supports-color crate that handles the detection side across platforms.
The downside is that approximated colors can look noticeably different from the originals. A carefully tuned Dracula theme mapped to 256 colors might look "close enough" or might look muddy. Hard to know without trying it.
Alternatives Considered
- Warning only (current state): xleak checks COLORTERM at startup and warns if truecolor isn't advertised. This is honest and actionable, but doesn't fix the display.
- Per-theme fallback colors: Let users specify e.g. header_fg_fallback = "blue" alongside header_fg = "#7aa2f7". Full user control, but doubles the config surface area for a niche use case.
- Do nothing: The main terminals people use with TUI tools (iTerm2, WezTerm, Alacritty, Kitty, Windows Terminal) all support truecolor. macOS Terminal.app is really the only common holdout. The warning might be good enough.
Additional Context
Implementation Notes
- Use supports-color to detect terminal capabilities (truecolor / 256 / 16 / none)
- If truecolor isn't available, walk the active ColorScheme and replace each Color::Rgb with the nearest Color::Indexed from the 256-color palette
- Do this once at startup, not per-frame
- Keep the existing stderr warning as a fallback for edge cases where detection is wrong
That's maybe 50-80 lines plus the new dependency. The existing named-color themes (foreground = "cyan") would be unaffected since they already use ANSI colors.
A couple of questions before I start on this:
- Are you okay with adding supports-color as a dependency?
- Should this be opt-in (--force-truecolor to skip downgrade) or opt-out (--no-color-downgrade)?
Feature Description
Automatic RGB-to-ANSI color downgrade when the terminal doesn't support truecolor.
Problem or Use Case
Ratatui + crossterm doesn't do any terminal color capability detection. When a theme uses
Color::Rgbvalues (which all the built-in themes except Default already do), xleak emits raw RGB escape codes on the assumption the user's terminal is capable of correctly rendering. On terminals that don't support truecolor — macOS Terminal.app is the big one — the result is garbled or blinking text rather than a graceful fallback.In #47 I added a basic
COLORTERMenv var check that warns on stderr if truecolor isn't advertised. It's cool to print a warning, it's cooler to gracefully handle the error.Proposed Solution
When the terminal doesn't advertise truecolor support, map each
Color::Rgb(r, g, b)in the active theme to the nearest ANSI-256 color. The math is a Euclidean distance search against the 256-color palette, there's a supports-color crate that handles the detection side across platforms.The downside is that approximated colors can look noticeably different from the originals. A carefully tuned Dracula theme mapped to 256 colors might look "close enough" or might look muddy. Hard to know without trying it.
Alternatives Considered
Additional Context
Implementation Notes
That's maybe 50-80 lines plus the new dependency. The existing named-color themes (foreground = "cyan") would be unaffected since they already use ANSI colors.
A couple of questions before I start on this: