1use {
2 super::*,
3 ansi_term::{ANSIGenericString, Color::*, Prefix, Style, Suffix},
4 std::io::{self, IsTerminal},
5};
6
7#[derive(Copy, Clone, Debug, PartialEq)]
8pub struct Color {
9 is_terminal: bool,
10 style: Style,
11 use_color: UseColor,
12}
13
14impl Color {
15 fn restyle(self, style: Style) -> Self {
16 Self { style, ..self }
17 }
18
19 fn redirect(self, stream: impl IsTerminal) -> Self {
20 Self {
21 is_terminal: stream.is_terminal(),
22 ..self
23 }
24 }
25
26 fn effective_style(&self) -> Style {
27 if self.active() {
28 self.style
29 } else {
30 Style::new()
31 }
32 }
33
34 pub fn auto() -> Self {
35 Self::default()
36 }
37
38 pub fn always() -> Self {
39 Self {
40 use_color: UseColor::Always,
41 ..Self::default()
42 }
43 }
44
45 pub fn never() -> Self {
46 Self {
47 use_color: UseColor::Never,
48 ..Self::default()
49 }
50 }
51
52 pub fn stderr(self) -> Self {
53 self.redirect(io::stderr())
54 }
55
56 pub fn stdout(self) -> Self {
57 self.redirect(io::stdout())
58 }
59
60 pub fn context(self) -> Self {
61 self.restyle(Style::new().fg(Blue).bold())
62 }
63
64 pub fn doc(self) -> Self {
65 self.restyle(Style::new().fg(Blue))
66 }
67
68 pub fn doc_backtick(self) -> Self {
69 self.restyle(Style::new().fg(Cyan))
70 }
71
72 pub fn error(self) -> Self {
73 self.restyle(Style::new().fg(Red).bold())
74 }
75
76 pub fn group(self) -> Self {
77 self.restyle(Style::new().fg(Yellow).bold())
78 }
79
80 pub fn warning(self) -> Self {
81 self.restyle(Style::new().fg(Yellow).bold())
82 }
83
84 pub fn banner(self) -> Self {
85 self.restyle(Style::new().fg(Cyan).bold())
86 }
87
88 pub fn command(self, foreground: Option<ansi_term::Color>) -> Self {
89 self.restyle(Style {
90 foreground,
91 is_bold: true,
92 ..Style::default()
93 })
94 }
95
96 pub fn parameter(self) -> Self {
97 self.restyle(Style::new().fg(Cyan))
98 }
99
100 pub fn message(self) -> Self {
101 self.restyle(Style::new().bold())
102 }
103
104 pub fn annotation(self) -> Self {
105 self.restyle(Style::new().fg(Purple))
106 }
107
108 pub fn string(self) -> Self {
109 self.restyle(Style::new().fg(Green))
110 }
111
112 pub fn diff_added(self) -> Self {
113 self.restyle(Style::new().fg(Green))
114 }
115
116 pub fn diff_deleted(self) -> Self {
117 self.restyle(Style::new().fg(Red))
118 }
119
120 pub fn active(&self) -> bool {
121 match self.use_color {
122 UseColor::Always => true,
123 UseColor::Never => false,
124 UseColor::Auto => self.is_terminal,
125 }
126 }
127
128 pub fn paint<'a>(&self, text: &'a str) -> ANSIGenericString<'a, str> {
129 self.effective_style().paint(text)
130 }
131
132 pub fn prefix(&self) -> Prefix {
133 self.effective_style().prefix()
134 }
135
136 pub fn suffix(&self) -> Suffix {
137 self.effective_style().suffix()
138 }
139}
140
141impl From<UseColor> for Color {
142 fn from(use_color: UseColor) -> Self {
143 Self {
144 use_color,
145 ..Default::default()
146 }
147 }
148}
149
150impl Default for Color {
151 fn default() -> Self {
152 Self {
153 is_terminal: false,
154 style: Style::new(),
155 use_color: UseColor::Auto,
156 }
157 }
158}