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}
153