use serde_json::Value;
pub(crate) fn format_line_range(start: u64, end: u64) -> String {
if start == end || end == 0 {
format!("L{start}")
} else {
format!("L{start}-{end}")
}
}
#[allow(dead_code)] pub(crate) fn truncate_path(path: &str, max_len: usize) -> String {
if path.len() <= max_len {
return path.to_string();
}
if max_len < 5 {
let end = crate::tools::floor_char_boundary(path, max_len);
return path[..end].to_string();
}
let keep_end = max_len / 2;
let keep_start = max_len - keep_end - 1; let start = crate::tools::floor_char_boundary(path, keep_start);
let tail_offset = crate::tools::floor_char_boundary(path, path.len() - keep_end);
format!("{}…{}", &path[..start], &path[tail_offset..])
}
pub(crate) fn format_overflow(overflow: &Value) -> String {
let shown = overflow["shown"].as_u64().unwrap_or(0);
let total = overflow["total"].as_u64().unwrap_or(0);
let hint = overflow["hint"].as_str().unwrap_or("");
if total > shown {
format!(" … showing {shown} of {total} — {hint}")
} else {
format!(" … showing first {shown} — {hint}")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn line_range_single() {
assert_eq!(format_line_range(35, 35), "L35");
}
#[test]
fn line_range_span() {
assert_eq!(format_line_range(35, 50), "L35-50");
}
#[test]
fn line_range_zero_end() {
assert_eq!(format_line_range(10, 0), "L10");
}
#[test]
fn truncate_short_path() {
assert_eq!(truncate_path("src/main.rs", 30), "src/main.rs");
}
#[test]
fn truncate_long_path() {
let long = "src/tools/very/deeply/nested/path/to/file.rs";
let result = truncate_path(long, 25);
assert!(
result.chars().count() <= 25,
"got len {} for '{}'",
result.chars().count(),
result
);
assert!(result.contains('…'));
}
#[test]
fn truncate_path_unicode_does_not_panic() {
let unicode_segment = "─".repeat(30); let path = format!("src/tools/{}/file.rs", unicode_segment);
let result = truncate_path(&path, 25);
assert!(result.contains('…'), "must contain ellipsis");
assert!(std::str::from_utf8(result.as_bytes()).is_ok());
}
#[test]
fn overflow_with_total() {
let ov = serde_json::json!({
"shown": 50, "total": 234, "hint": "narrow with path="
});
let result = format_overflow(&ov);
assert!(result.contains("50 of 234"));
assert!(result.contains("narrow with path="));
}
#[test]
fn overflow_without_total() {
let ov = serde_json::json!({
"shown": 50, "total": 50, "hint": "use more specific pattern"
});
let result = format_overflow(&ov);
assert!(result.contains("first 50"));
}
}