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