#[must_use]
pub fn escape(text: &str) -> String {
let mut out = String::with_capacity(text.len() + 8);
for line in text.split_inclusive('\n') {
let chars: Vec<char> = line.chars().collect();
let mut i = chars.iter().take_while(|c| **c == ' ').count();
out.extend(&chars[..i]);
if i < chars.len() {
match chars[i] {
'#' | '+' | '-' | '=' => out.push('\\'),
c if c.is_ascii_digit() => {
let digits_end = chars[i..]
.iter()
.position(|d| !d.is_ascii_digit())
.map_or(chars.len(), |offset| i + offset);
out.extend(&chars[i..digits_end]);
i = digits_end;
if matches!(chars.get(i), Some('.' | ')')) {
out.push('\\');
}
}
_ => {}
}
}
for &c in &chars[i..] {
if matches!(
c,
'\\' | '`' | '*' | '_' | '[' | ']' | '<' | '>' | '|' | '~' | '&'
) {
out.push('\\');
}
out.push(c);
}
}
out
}
#[cfg(test)]
#[path = "escape.test.rs"]
mod tests;
#[cfg(test)]
#[path = "escape.spec.rs"]
mod spec;