pub_just/
color.rs

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}