mod chain;
mod claude;
mod config;
mod install;
mod render;
mod system;
mod theme;
use std::io::Read;
use std::process::ExitCode;
fn main() -> ExitCode {
let args: Vec<String> = std::env::args().skip(1).collect();
let subcommand = args.first().map(String::as_str);
match subcommand {
None | Some("render") => {
run_render_pipeline();
ExitCode::SUCCESS
}
Some("install") => match install::install() {
Ok(()) => ExitCode::SUCCESS,
Err(error) => {
eprintln!("understatus: 설치 실패: {error:#}");
ExitCode::FAILURE
}
},
Some("uninstall") => match install::uninstall() {
Ok(()) => ExitCode::SUCCESS,
Err(error) => {
eprintln!("understatus: 제거 실패: {error:#}");
ExitCode::FAILURE
}
},
Some("--help") | Some("-h") => {
print_help();
ExitCode::SUCCESS
}
Some("--version") | Some("-V") => {
print_version();
ExitCode::SUCCESS
}
Some(other) => {
eprintln!("understatus: 알 수 없는 서브커맨드 '{other}'. --help 참조.");
ExitCode::FAILURE
}
}
}
fn run_render_pipeline() {
let raw_stdin = read_stdin();
let claude_input = claude::parse_claude_input(&raw_stdin);
let cfg = config::load_config();
let snapshot = system::sample_system(&cfg);
debug_assert!(
theme::samples_per_period(&cfg, cfg.refresh.interval_seconds) >= 6,
"펄스 지각성 불변식 위반: samples_per_period < 6 (pulse_period={}s, refreshInterval={}s)",
cfg.pulse.pulse_period_seconds,
cfg.refresh.interval_seconds
);
let prev_pulse_on = chain::read_prev_pulse_state();
let now_ms = now_millis();
let pulse_on = theme::pulse_gate(snapshot.cpu_percent, prev_pulse_on, &cfg);
chain::write_pulse_state(pulse_on);
let self_segment = render::render(&claude_input, &snapshot, &cfg, now_ms, pulse_on);
let chain_output = match cfg.chain.chain_command.as_deref() {
Some(command) if !command.is_empty() => chain::run_chain(command, &raw_stdin, &cfg),
_ => String::new(),
};
let color_on = std::env::var_os("NO_COLOR").is_none() && cfg.color.mode != "none";
let line =
render::compose_with_seam(&self_segment, &chain_output, &cfg.chain.order, &cfg, color_on);
println!("{line}");
}
fn read_stdin() -> String {
let mut buffer = String::new();
let _ = std::io::stdin().read_to_string(&mut buffer);
buffer
}
fn now_millis() -> u128 {
use std::time::{SystemTime, UNIX_EPOCH};
SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|elapsed| elapsed.as_millis())
.unwrap_or(0)
}
fn print_help() {
println!(
"understatus {} — AI 코딩 CLI용 macOS statusline 애드온\n\
\n\
사용법:\n\
\x20 understatus [render] stdin JSON을 읽어 statusline 한 줄을 출력(기본)\n\
\x20 understatus install 기존 statusLine을 보존(체이닝)하며 비파괴 설치\n\
\x20 understatus uninstall 원본 설정을 정확 복원하며 제거\n\
\x20 understatus --help 이 도움말 출력\n\
\x20 understatus --version 버전 출력",
env!("CARGO_PKG_VERSION")
);
}
fn print_version() {
println!("understatus {}", env!("CARGO_PKG_VERSION"));
}