Files
claude-statusline/src/color.rs
Taylor Eernisse b55d1aefd1 feat: complete Rust port of claude-statusline
Port the entire 2236-line bash statusline script to Rust.
Implements all 25 sections, 3-phase layout engine (render, priority
drop, flex/justify), file-based caching with flock, 9-level terminal
width detection, trend sparklines, and deep-merge JSON config.

Release binary: 864K with LTO. Render time: <1ms warm.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 14:21:57 -05:00

77 lines
2.1 KiB
Rust

use crate::config::ThemeColors;
use crate::theme::Theme;
pub const RESET: &str = "\x1b[0m";
pub const BOLD: &str = "\x1b[1m";
pub const DIM: &str = "\x1b[2m";
pub const RED: &str = "\x1b[31m";
pub const GREEN: &str = "\x1b[32m";
pub const YELLOW: &str = "\x1b[33m";
pub const BLUE: &str = "\x1b[34m";
pub const MAGENTA: &str = "\x1b[35m";
pub const CYAN: &str = "\x1b[36m";
pub const WHITE: &str = "\x1b[37m";
/// Resolve a color name to ANSI escape sequence(s).
pub fn resolve_color(name: &str, theme: Theme, palette: &ThemeColors) -> String {
if let Some(key) = name.strip_prefix("p:") {
let map = match theme {
Theme::Dark => &palette.dark,
Theme::Light => &palette.light,
};
if let Some(resolved) = map.get(key) {
return resolve_color(resolved, theme, palette);
}
return RESET.to_string();
}
let mut result = String::new();
for part in name.split_whitespace() {
result.push_str(match part {
"red" => RED,
"green" => GREEN,
"yellow" => YELLOW,
"blue" => BLUE,
"magenta" => MAGENTA,
"cyan" => CYAN,
"white" => WHITE,
"dim" => DIM,
"bold" => BOLD,
_ => "",
});
}
if result.is_empty() {
RESET.to_string()
} else {
result
}
}
/// Determine whether color output should be used.
pub fn should_use_color(cli_color: Option<&str>, config_color: &crate::config::ColorMode) -> bool {
if std::env::var("NO_COLOR").is_ok() {
return false;
}
if let Some(flag) = cli_color {
return match flag {
"always" => true,
"never" => false,
_ => atty_stdout(),
};
}
match config_color {
crate::config::ColorMode::Always => true,
crate::config::ColorMode::Never => false,
crate::config::ColorMode::Auto => {
atty_stdout() && std::env::var("TERM").map_or(true, |t| t != "dumb")
}
}
}
fn atty_stdout() -> bool {
unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 }
}