pub fn printable(text: &str) -> String {
escaped(text, |c| c == '\n' || c == '\t')
}
pub fn printable_line(text: &str) -> String {
escaped(text, |_| false)
}
fn escaped(text: &str, keep: impl Fn(char) -> bool) -> String {
let mut out = String::with_capacity(text.len());
for c in text.chars() {
if c.is_control() && !keep(c) {
out.extend(c.escape_unicode());
} else {
out.push(c);
}
}
out
}
#[cfg(test)]
mod tests {
use super::printable;
use super::printable_line;
#[test]
fn ordinary_text_is_untouched() {
assert_eq!(printable("r3: adds add/six.txt"), "r3: adds add/six.txt");
assert_eq!(printable_line("add/six.txt"), "add/six.txt");
}
#[test]
fn an_escape_sequence_is_shown_rather_than_run() {
let hostile = "clean\u{1b}[2J\u{1b}[Hnothing here";
let safe = printable(hostile);
assert!(
!safe.contains('\u{1b}'),
"an ESC reached the terminal: {safe:?}"
);
assert_eq!(safe, "clean\\u{1b}[2J\\u{1b}[Hnothing here");
}
#[test]
fn the_c1_introducer_is_escaped_too() {
assert_eq!(printable("a\u{9b}31m"), "a\\u{9b}31m");
}
#[test]
fn a_multi_line_message_keeps_its_lines() {
assert_eq!(printable("first\nsecond\tthird"), "first\nsecond\tthird");
}
#[test]
fn a_path_cannot_forge_a_line() {
let forged = "legit.csv\n3 files removed:\n important.parquet";
let safe = printable_line(forged);
assert!(!safe.contains('\n'), "a path kept a line break: {safe:?}");
assert_eq!(
safe,
"legit.csv\\u{a}3 files removed:\\u{a} important.parquet"
);
}
#[test]
fn a_path_cannot_forge_a_column_either() {
assert_eq!(printable_line("a\tb"), "a\\u{9}b");
}
}