pub fn excerpt(body: &str, max_chars: usize) -> String {
let cleaned: String = body
.chars()
.map(|c| if c.is_control() { ' ' } else { c })
.collect();
let mut out = String::with_capacity(max_chars);
let mut last_was_space = false;
for c in cleaned.trim().chars() {
if out.chars().count() >= max_chars {
out.push('…');
break;
}
if c == ' ' {
if last_was_space {
continue;
}
last_was_space = true;
} else {
last_was_space = false;
}
out.push(c);
}
if out.is_empty() {
return "<nothing>".to_owned();
}
out
}
#[cfg(test)]
mod tests {
use super::excerpt;
#[test]
fn control_characters_are_replaced_not_passed_through() {
let out = excerpt("a\u{1b}[31mred\u{7}b", 100);
assert!(!out.chars().any(char::is_control), "{out:?}");
assert!(out.contains("red"), "{out:?}");
}
#[test]
fn text_within_the_limit_is_returned_intact_without_a_marker() {
assert_eq!(excerpt("short", 100), "short");
}
#[test]
fn text_over_the_limit_is_cut_and_marked() {
let out = excerpt(&"x".repeat(50), 10);
assert_eq!(out.chars().count(), 11, "{out:?}");
assert!(out.ends_with('…'), "{out:?}");
}
#[test]
fn runs_of_space_collapse_and_the_edges_are_trimmed() {
assert_eq!(excerpt(" a\t\t\tb ", 100), "a b");
}
#[test]
fn empty_input_names_itself_rather_than_quoting_nothing() {
assert_eq!(excerpt(" ", 100), "<nothing>");
}
#[test]
fn the_limit_counts_characters_not_bytes() {
let out = excerpt(&"—".repeat(10), 10);
assert_eq!(out.chars().count(), 10, "{out:?}");
assert!(!out.ends_with('…'), "{out:?}");
}
}