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: bool = self.style.write_prefix(f)?;
14 self.f.take().ok_or(fmt::Error).and_then(|c: F| 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(data: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}
81