• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::builder::StyledStr;
2 use crate::util::color::ColorChoice;
3 
4 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
5 pub(crate) enum Stream {
6     Stdout,
7     Stderr,
8 }
9 
10 #[derive(Clone, Debug)]
11 pub(crate) struct Colorizer {
12     stream: Stream,
13     #[allow(unused)]
14     color_when: ColorChoice,
15     content: StyledStr,
16 }
17 
18 impl Colorizer {
new(stream: Stream, color_when: ColorChoice) -> Self19     pub(crate) fn new(stream: Stream, color_when: ColorChoice) -> Self {
20         Colorizer {
21             stream,
22             color_when,
23             content: Default::default(),
24         }
25     }
26 
with_content(mut self, content: StyledStr) -> Self27     pub(crate) fn with_content(mut self, content: StyledStr) -> Self {
28         self.content = content;
29         self
30     }
31 }
32 
33 /// Printing methods.
34 impl Colorizer {
35     #[cfg(feature = "color")]
print(&self) -> std::io::Result<()>36     pub(crate) fn print(&self) -> std::io::Result<()> {
37         use termcolor::{BufferWriter, ColorChoice as DepColorChoice};
38 
39         let color_when = match self.color_when {
40             ColorChoice::Always => DepColorChoice::Always,
41             ColorChoice::Auto if is_a_tty(self.stream) => DepColorChoice::Auto,
42             _ => DepColorChoice::Never,
43         };
44 
45         let writer = match self.stream {
46             Stream::Stderr => BufferWriter::stderr(color_when),
47             Stream::Stdout => BufferWriter::stdout(color_when),
48         };
49 
50         let mut buffer = writer.buffer();
51         ok!(self.content.write_colored(&mut buffer));
52         writer.print(&buffer)
53     }
54 
55     #[cfg(not(feature = "color"))]
print(&self) -> std::io::Result<()>56     pub(crate) fn print(&self) -> std::io::Result<()> {
57         use std::io::Write;
58 
59         // [e]println can't be used here because it panics
60         // if something went wrong. We don't want that.
61         match self.stream {
62             Stream::Stdout => {
63                 let stdout = std::io::stdout();
64                 let mut stdout = stdout.lock();
65                 write!(stdout, "{}", self)
66             }
67             Stream::Stderr => {
68                 let stderr = std::io::stderr();
69                 let mut stderr = stderr.lock();
70                 write!(stderr, "{}", self)
71             }
72         }
73     }
74 }
75 
76 /// Color-unaware printing. Never uses coloring.
77 impl std::fmt::Display for Colorizer {
fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result78     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
79         self.content.fmt(f)
80     }
81 }
82 
83 #[cfg(feature = "color")]
is_a_tty(stream: Stream) -> bool84 fn is_a_tty(stream: Stream) -> bool {
85     use is_terminal::IsTerminal;
86     match stream {
87         Stream::Stdout => std::io::stdout().is_terminal(),
88         Stream::Stderr => std::io::stderr().is_terminal(),
89     }
90 }
91