shuvarie-core 0.3.2

Blazingly fast AI coding TUI for chivalrous people (core module)
pub(crate) fn truncate_output(text: &str, max_chars: usize, hint: &str) -> Option<String> {
    if max_chars == 0 {
        return None;
    }
    let total = text.chars().count();
    if total <= max_chars {
        return None;
    }
    let truncated: String = text.chars().take(max_chars).collect();
    let omitted = total - max_chars;
    Some(format!(
        "{truncated}… (output truncated: {omitted} chars omitted — {hint})"
    ))
}

pub(crate) fn truncate_bytes(text: &str, max_bytes: usize, hint: &str) -> Option<String> {
    if max_bytes == 0 {
        return None;
    }
    if text.len() <= max_bytes {
        return None;
    }
    let mut cut = max_bytes;
    while cut > 0 && !text.is_char_boundary(cut) {
        cut -= 1;
    }
    let kept = &text[..cut];
    let omitted = text.len() - kept.len();
    Some(format!(
        "{kept}… (output truncated: {omitted} bytes omitted — {hint})"
    ))
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn under_cap_returns_none() {
        assert_eq!(truncate_output("hello", 10, "hint"), None);
        assert_eq!(truncate_output("hello", 5, "hint"), None);
    }

    #[test]
    fn zero_cap_disables_truncation() {
        assert_eq!(truncate_output("hello world", 0, "hint"), None);
    }

    #[test]
    fn over_cap_returns_truncated_with_marker() {
        let text = "a".repeat(120);
        let out = truncate_output(&text, 100, "use offset/limit").unwrap();
        assert!(out.starts_with(&"a".repeat(100)));
        assert!(out.contains("…"));
        assert!(out.contains("20 chars omitted"));
        assert!(out.contains("use offset/limit"));
    }

    #[test]
    fn char_not_byte_boundary() {
        let text = "éééé";
        let out = truncate_output(text, 2, "hint").unwrap();
        assert_eq!(out, "éé… (output truncated: 2 chars omitted — hint)");
    }

    #[test]
    fn byte_truncation_under_cap_and_zero() {
        assert_eq!(truncate_bytes("hello", 10, "hint"), None);
        assert_eq!(truncate_bytes("hello world", 0, "hint"), None);
    }

    #[test]
    fn byte_truncation_splits_at_char_boundary() {
        let text = "éééé";
        let out = truncate_bytes(text, 5, "hint").unwrap();
        assert!(out.starts_with("éé"), "{out}");
        assert!(out.contains("4 bytes omitted"), "{out}");
    }

    #[test]
    fn byte_truncation_ascii() {
        let out = truncate_bytes("abcdef", 4, "hint").unwrap();
        assert!(out.starts_with("abcd"), "{out}");
        assert!(out.contains("2 bytes omitted"), "{out}");
    }
}