1 | use std::{cell::Cell, fmt}; |
2 | |
3 | use crate::{Colour, Style}; |
4 | |
5 | /// An `DisplayANSI` includes a format function and a `Style` |
6 | struct DisplayANSI<F: FnOnce(&mut fmt::Formatter) -> fmt::Result> { |
7 | style: Style, |
8 | f: Cell<Option<F>>, |
9 | } |
10 | |
11 | impl<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 | |
22 | impl 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 | |
45 | impl 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)] |
70 | mod 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 | |