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:
Taylor Eernisse
2026-02-06 14:21:57 -05:00
commit b55d1aefd1
65 changed files with 12439 additions and 0 deletions

63
src/layout/justify.rs Normal file
View File

@@ -0,0 +1,63 @@
use crate::config::JustifyMode;
use crate::format;
use crate::layout::ActiveSection;
/// Distribute extra space evenly across gaps between sections.
/// Center the separator core (e.g., `|` from ` | `) within each gap.
/// Remainder chars distributed left-to-right.
pub fn justify(
active: &[ActiveSection],
term_width: u16,
separator: &str,
_mode: JustifyMode,
) -> String {
let content_width: usize = active
.iter()
.map(|s| format::display_width(&s.output.raw))
.sum();
let num_gaps = active.len().saturating_sub(1);
if num_gaps == 0 {
return active
.first()
.map(|s| s.output.ansi.clone())
.unwrap_or_default();
}
let available = (term_width as usize).saturating_sub(content_width);
let gap_width = available / num_gaps;
let gap_remainder = available % num_gaps;
// Extract separator core (non-space chars, e.g. "|" from " | ")
let sep_core = separator.trim();
let sep_core_len = format::display_width(sep_core);
let mut output = String::new();
for (i, sec) in active.iter().enumerate() {
if i > 0 {
let this_gap = gap_width + usize::from(i - 1 < gap_remainder);
let gap_str = build_gap(sep_core, sep_core_len, this_gap);
output.push_str(&format!(
"{}{gap_str}{}",
crate::color::DIM,
crate::color::RESET
));
}
output.push_str(&sec.output.ansi);
}
output
}
/// Center the separator core within a gap of `total` columns.
fn build_gap(core: &str, core_len: usize, total: usize) -> String {
if core.is_empty() || core_len == 0 {
return " ".repeat(total);
}
let pad_total = total.saturating_sub(core_len);
let pad_left = pad_total / 2;
let pad_right = pad_total - pad_left;
format!("{}{core}{}", " ".repeat(pad_left), " ".repeat(pad_right))
}