nu_ansi_term/
debug.rs

1use crate::style::Style;
2use std::fmt;
3
4/// Styles have a special `Debug` implementation that only shows the fields that
5/// are set. Fields that haven’t been touched aren’t included in the output.
6///
7/// This behaviour gets bypassed when using the alternate formatting mode
8/// `format!("{:#?}")`.
9///
10///     use nu_ansi_term::Color::{Red, Blue};
11///     assert_eq!("Style { fg(Red), on(Blue), bold, italic }",
12///                format!("{:?}", Red.on(Blue).bold().italic()));
13impl fmt::Debug for Style {
14    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
15        if fmt.alternate() {
16            fmt.debug_struct("Style")
17                .field("foreground", &self.foreground)
18                .field("background", &self.background)
19                .field("blink", &self.is_blink)
20                .field("bold", &self.is_bold)
21                .field("dimmed", &self.is_dimmed)
22                .field("hidden", &self.is_hidden)
23                .field("italic", &self.is_italic)
24                .field("reverse", &self.is_reverse)
25                .field("strikethrough", &self.is_strikethrough)
26                .field("underline", &self.is_underline)
27                .finish()
28        } else if self.is_plain() {
29            fmt.write_str("Style {}")
30        } else {
31            fmt.write_str("Style { ")?;
32
33            let mut written_anything = false;
34
35            if let Some(fg) = self.foreground {
36                if written_anything {
37                    fmt.write_str(", ")?
38                }
39                written_anything = true;
40                write!(fmt, "fg({:?})", fg)?
41            }
42
43            if let Some(bg) = self.background {
44                if written_anything {
45                    fmt.write_str(", ")?
46                }
47                written_anything = true;
48                write!(fmt, "on({:?})", bg)?
49            }
50
51            {
52                let mut write_flag = |name| {
53                    if written_anything {
54                        fmt.write_str(", ")?
55                    }
56                    written_anything = true;
57                    fmt.write_str(name)
58                };
59
60                if self.is_blink {
61                    write_flag("blink")?
62                }
63                if self.is_bold {
64                    write_flag("bold")?
65                }
66                if self.is_dimmed {
67                    write_flag("dimmed")?
68                }
69                if self.is_hidden {
70                    write_flag("hidden")?
71                }
72                if self.is_italic {
73                    write_flag("italic")?
74                }
75                if self.is_reverse {
76                    write_flag("reverse")?
77                }
78                if self.is_strikethrough {
79                    write_flag("strikethrough")?
80                }
81                if self.is_underline {
82                    write_flag("underline")?
83                }
84            }
85
86            write!(fmt, " }}")
87        }
88    }
89}
90
91#[cfg(test)]
92mod test {
93    use crate::style::Color::*;
94    use crate::style::Style;
95
96    fn style() -> Style {
97        Style::new()
98    }
99
100    macro_rules! test {
101        ($name: ident: $obj: expr => $result: expr) => {
102            #[test]
103            fn $name() {
104                assert_eq!($result, format!("{:?}", $obj));
105            }
106        };
107    }
108
109    test!(empty:   style()                  => "Style {}");
110    test!(bold:    style().bold()           => "Style { bold }");
111    test!(italic:  style().italic()         => "Style { italic }");
112    test!(both:    style().bold().italic()  => "Style { bold, italic }");
113
114    test!(red:     Red.normal()                     => "Style { fg(Red) }");
115    test!(redblue: Red.normal().on(Rgb(3, 2, 4))    => "Style { fg(Red), on(Rgb(3, 2, 4)) }");
116
117    test!(everything:
118            Red.on(Blue).blink().bold().dimmed().hidden().italic().reverse().strikethrough().underline() =>
119            "Style { fg(Red), on(Blue), blink, bold, dimmed, hidden, italic, reverse, strikethrough, underline }");
120
121    #[test]
122    fn long_and_detailed() {
123        extern crate regex;
124        let expected_debug = "Style { fg(Blue), bold }";
125        let expected_pretty_repat = r##"(?x)
126        Style\s+\{\s+
127            foreground:\s+Some\(\s+
128                Blue,?\s+
129            \),\s+
130            background:\s+None,\s+
131            blink:\s+false,\s+
132            bold:\s+true,\s+
133            dimmed:\s+false,\s+
134            hidden:\s+false,\s+
135            italic:\s+false,\s+
136            reverse:\s+false,\s+
137            strikethrough:\s+
138            false,\s+
139            underline:\s+false,?\s+
140            \}"##;
141        let re = regex::Regex::new(expected_pretty_repat).unwrap();
142
143        let style = Blue.bold();
144        let style_fmt_debug = format!("{:?}", style);
145        let style_fmt_pretty = format!("{:#?}", style);
146        println!("style_fmt_debug:\n{}", style_fmt_debug);
147        println!("style_fmt_pretty:\n{}", style_fmt_pretty);
148
149        assert_eq!(expected_debug, style_fmt_debug);
150        assert!(re.is_match(&style_fmt_pretty));
151    }
152}