Files
claude-statusline/src/section/custom.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

67 lines
2.3 KiB
Rust

use crate::color;
use crate::section::{RenderContext, SectionOutput};
use crate::shell;
use std::time::Duration;
/// Render a custom command section by ID.
pub fn render(id: &str, ctx: &RenderContext) -> Option<SectionOutput> {
let cmd_cfg = ctx.config.custom.iter().find(|c| c.id == id)?;
let ttl = Duration::from_secs(cmd_cfg.ttl);
let timeout = Duration::from_millis(ctx.config.global.shell_timeout_ms);
let cache_key = format!("custom_{id}");
let cached = ctx.cache.get(&cache_key, ttl);
let output_str = cached.or_else(|| {
let result = if let Some(ref exec) = cmd_cfg.exec {
if exec.is_empty() {
return None;
}
let args: Vec<&str> = exec[1..].iter().map(|s| s.as_str()).collect();
shell::exec_with_timeout(&exec[0], &args, None, timeout)
} else if let Some(ref command) = cmd_cfg.command {
shell::exec_with_timeout("sh", &["-c", command], None, timeout)
} else {
None
};
if let Some(ref val) = result {
ctx.cache.set(&cache_key, val);
}
result
})?;
if output_str.is_empty() {
return None;
}
let label = cmd_cfg.label.as_deref().unwrap_or("");
let raw = if label.is_empty() {
output_str.clone()
} else {
format!("{label}: {output_str}")
};
let ansi = if ctx.color_enabled {
if let Some(ref color_cfg) = cmd_cfg.color {
if let Some(matched_color) = color_cfg.match_map.get(&output_str) {
let c = color::resolve_color(matched_color, ctx.theme, &ctx.config.colors);
format!("{c}{raw}{}", color::RESET)
} else if let Some(ref default_c) = cmd_cfg.default_color {
let c = color::resolve_color(default_c, ctx.theme, &ctx.config.colors);
format!("{c}{raw}{}", color::RESET)
} else {
raw.clone()
}
} else if let Some(ref default_c) = cmd_cfg.default_color {
let c = color::resolve_color(default_c, ctx.theme, &ctx.config.colors);
format!("{c}{raw}{}", color::RESET)
} else {
raw.clone()
}
} else {
raw.clone()
};
Some(SectionOutput { raw, ansi })
}