yansi_term/
display.rs

1use std::{cell::Cell, fmt};
2
3use crate::{Colour, Style};
4
5/// An `DisplayANSI` includes a format function and a `Style`
6struct DisplayANSI<F: FnOnce(&mut fmt::Formatter) -> fmt::Result> {
7    style: Style,
8    f: Cell<Option<F>>,
9}
10
11impl<F: FnOnce(&mut fmt::Formatter) -> fmt::Result> fmt::Display for DisplayANSI<F> {
12    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
13        let written = self.style.write_prefix(f)?;
14        self.f.take().ok_or(fmt::Error).and_then(|c| c(f))?;
15        if written {
16            Style::write_reset(f)?;
17        }
18        Ok(())
19    }
20}
21
22impl Style {
23    /// Paints the given text with this style
24    #[inline]
25    pub fn paint<'a>(self, input: &'a str) -> impl fmt::Display + 'a {
26        DisplayANSI {
27            f: Cell::new(Some(move |f: &mut fmt::Formatter| f.write_str(input))),
28            style: self,
29        }
30    }
31
32    /// Paints the given format function with this style
33    #[inline]
34    pub fn paint_fn<F: FnOnce(&mut fmt::Formatter) -> fmt::Result>(
35        self,
36        f: F,
37    ) -> impl fmt::Display {
38        DisplayANSI {
39            f: Cell::new(Some(f)),
40            style: self,
41        }
42    }
43}
44
45impl Colour {
46    /// Paints the given text with this colour
47    /// This is a short-cut so you don’t have to use `Blue.normal()` just
48    /// to get blue text.
49    ///
50    /// ```
51    /// use yansi_term::Colour::Blue;
52    /// println!("{}", Blue.paint("da ba dee"));
53    /// ```
54    #[inline]
55    pub fn paint<'a>(self, input: &'a str) -> impl fmt::Display + 'a {
56        self.normal().paint(input)
57    }
58
59    /// Paints the given format function with this colour
60    #[inline]
61    pub fn paint_fn<F: FnOnce(&mut fmt::Formatter) -> fmt::Result>(
62        self,
63        f: F,
64    ) -> impl fmt::Display {
65        self.normal().paint_fn(f)
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72
73    #[test]
74    fn no_control_codes_for_plain() {
75        let one = Style::default().paint("one");
76        let two = Style::default().paint("two");
77        let output = format!("{}{}", one, two);
78        assert_eq!(output, "onetwo");
79    }
80}