indent_write/indentable.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
use core::fmt::{self, Display, Formatter, Write};
use crate::fmt::IndentWriter;
/// Methods for adapting [`Display`] objects to indent themselves when printed.
pub trait Indentable: Sized + Display {
/// Wrap this object so that its [`Display`] representation is indented
/// with the given `indent`. Each non-empty line of the formatted output
/// will be prefixed with the indent.
///
/// # Example:
///
/// ```
/// use indent_write::indentable::Indentable;
///
/// let content = "Line 1\nLine 2\n\nLine 3\n";
/// let indented = content.indented(" ");
/// let result = indented.to_string();
///
/// assert_eq!(result, " Line 1\n Line 2\n\n Line 3\n");
/// ```
#[must_use = "Indentables do nothing unless used"]
fn indented(self, indent: &str) -> Indented<'_, Self> {
Indented { item: self, indent }
}
/// Wrap this object so that its [`Display`] representation is indented
/// with the given `indent`. Each non-empty line *except for the first*
/// of the formatted output will be prefixed with the indent.
///
/// # Example:
///
/// ```
/// use indent_write::indentable::Indentable;
///
/// let content = "Line 1\nLine 2\n\nLine 3\n";
/// let indented = content.indented_skip_initial(" ");
/// let result = indented.to_string();
///
/// assert_eq!(result, "Line 1\n Line 2\n\n Line 3\n");
/// ```
#[must_use = "Indentables do nothing unless used"]
fn indented_skip_initial(self, indent: &str) -> IndentedSkipIntial<'_, Self> {
IndentedSkipIntial { item: self, indent }
}
}
impl<T: Display> Indentable for T {}
/// Wrapper struct that indents the [`Display`] representation of an item. When
/// printed with [`Display`], it will insert [`indent`][Self::indent] before
/// each non-empty line of the underlying [`item`][Self::item]'s [`Display`]
/// output.
///
/// Created with [`Indentable::indented`]; see its documentation for an example.
#[derive(Debug, Clone, Copy)]
pub struct Indented<'i, T: Display> {
/// The item to indent.
pub item: T,
/// The indentation to insert before each non-empty line.
pub indent: &'i str,
}
impl<T: Display> Display for Indented<'_, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(IndentWriter::new(self.indent, f), "{}", self.item)
}
}
/// Wrapper struct that indents the [`Display`] representation of an item. When
/// printed with [`Display`], it will insert [`indent`][Self::indent] before
/// each non-empty line _after the first_ of the underlying
/// [`item`][Self::item]'s [`Display`] output.
///
/// Created with [`Indentable::indented`]; see its documentation for an example.
#[derive(Debug, Clone, Copy)]
pub struct IndentedSkipIntial<'i, T: Display> {
/// The item to indent.
pub item: T,
/// The indentation to insert before each non-empty line.
pub indent: &'i str,
}
impl<T: Display> Display for IndentedSkipIntial<'_, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(
IndentWriter::new_skip_initial(self.indent, f),
"{}",
self.item
)
}
}