use super::{RenderContext, RenderResult, RenderedSegment, Segment, SegmentDefaults};
use crate::data_context::DataContext;
use crate::theme::Role;
pub struct CostSegment;
const PRIORITY: u8 = 192;
impl Segment for CostSegment {
fn render(&self, ctx: &DataContext, _rc: &RenderContext) -> RenderResult {
let Some(cost) = ctx.status.cost.as_ref() else {
crate::lsm_debug!("cost: status.cost absent; hiding");
return Ok(None);
};
let Some(usd) = cost.total_cost_usd else {
crate::lsm_debug!("cost: total_cost_usd null; hiding");
return Ok(None);
};
Ok(Some(
RenderedSegment::new(format!("${usd:.2}")).with_role(Role::Muted),
))
}
fn defaults(&self) -> SegmentDefaults {
SegmentDefaults::with_priority(PRIORITY)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::input::{CostMetrics, ModelInfo, StatusContext, Tool, WorkspaceInfo};
use std::path::PathBuf;
use std::sync::Arc;
fn rc() -> RenderContext {
RenderContext::new(80)
}
fn ctx(cost: Option<CostMetrics>) -> DataContext {
DataContext::new(StatusContext {
tool: Tool::ClaudeCode,
model: Some(ModelInfo {
display_name: "X".into(),
}),
workspace: Some(WorkspaceInfo {
project_dir: PathBuf::from("/repo"),
git_worktree: None,
}),
context_window: None,
cost,
effort: None,
vim: None,
output_style: None,
agent_name: None,
version: None,
raw: Arc::new(serde_json::Value::Null),
})
}
fn cost_of(usd: f64) -> CostMetrics {
CostMetrics {
total_cost_usd: Some(usd),
total_duration_ms: Some(0),
total_api_duration_ms: Some(0),
total_lines_added: Some(0),
total_lines_removed: Some(0),
}
}
#[test]
fn renders_two_decimal_places_with_muted_role() {
assert_eq!(
CostSegment
.render(&ctx(Some(cost_of(1.234))), &rc())
.unwrap(),
Some(RenderedSegment::new("$1.23").with_role(Role::Muted))
);
}
#[test]
fn renders_zero_cost() {
assert_eq!(
CostSegment.render(&ctx(Some(cost_of(0.0))), &rc()).unwrap(),
Some(RenderedSegment::new("$0.00").with_role(Role::Muted))
);
}
#[test]
fn hidden_when_cost_absent() {
assert_eq!(CostSegment.render(&ctx(None), &rc()).unwrap(), None);
}
#[test]
fn defaults_use_expected_priority() {
assert_eq!(CostSegment.defaults().priority, PRIORITY);
}
}