use std::fmt;
pub(crate) struct Indented<'a, D: ?Sized> {
inner: &'a mut D,
needs_indent: bool,
indentation: &'static str,
}
impl<T> fmt::Write for Indented<'_, T>
where
T: fmt::Write + ?Sized,
{
fn write_str(&mut self, s: &str) -> fmt::Result {
for (ind, line) in s.split('\n').enumerate() {
if ind > 0 {
self.inner.write_char('\n')?;
self.needs_indent = true;
}
if self.needs_indent {
if line.is_empty() {
continue;
}
write!(self.inner, "{}", self.indentation)?;
self.needs_indent = false;
}
self.inner.write_fmt(format_args!("{}", line))?;
}
Ok(())
}
}
pub(crate) fn indented<'a, D: ?Sized>(f: &'a mut D, indentation: &'static str) -> Indented<'a, D> {
Indented {
inner: f,
needs_indent: true,
indentation,
}
}
#[cfg(test)]
mod tests {
use core::fmt::Write as _;
use super::*;
#[test]
fn no_digits() {
let input = "verify\nthis";
let expected = " verify\n this";
let mut output = String::new();
indented(&mut output, " ").write_str(input).unwrap();
assert_eq!(expected, output);
}
#[test]
fn with_str() {
let input = "verify\nthis";
let expected = "...verify\n...this";
let mut output = String::new();
indented(&mut output, "...").write_str(input).unwrap();
assert_eq!(expected, output);
}
#[test]
fn dyn_write() {
let input = "verify\nthis";
let expected = " verify\n this";
let mut output = String::new();
let writer: &mut dyn fmt::Write = &mut output;
indented(writer, " ").write_str(input).unwrap();
assert_eq!(expected, output);
}
#[test]
fn nice_api_2() {
let input = "verify\nthis";
let expected = " verify\n this";
let output = &mut String::new();
write!(indented(output, " "), "{}", input).unwrap();
assert_eq!(expected, output);
}
#[test]
fn trailing_newlines() {
let input = "verify\nthis\n";
let expected = " verify\n this\n";
let output = &mut String::new();
write!(indented(output, " "), "{}", input).unwrap();
assert_eq!(expected, output);
}
#[test]
fn several_interpolations() {
let input = "verify\nthis\n";
let expected = " verify\n this\n and verify\n this\n";
let output = &mut String::new();
write!(indented(output, " "), "{} and {}", input, input).unwrap();
assert_eq!(expected, output);
}
}