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>
This commit is contained in:
76
src/color.rs
Normal file
76
src/color.rs
Normal file
@@ -0,0 +1,76 @@
|
||||
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 }
|
||||
}
|
||||
Reference in New Issue
Block a user