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