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