| use crate::builder::StyledStr; |
| use crate::util::color::ColorChoice; |
| |
| #[derive(Copy, Clone, Debug, PartialEq, Eq)] |
| pub(crate) enum Stream { |
| Stdout, |
| Stderr, |
| } |
| |
| #[derive(Clone, Debug)] |
| pub(crate) struct Colorizer { |
| stream: Stream, |
| #[allow(unused)] |
| color_when: ColorChoice, |
| content: StyledStr, |
| } |
| |
| impl Colorizer { |
| pub(crate) fn new(stream: Stream, color_when: ColorChoice) -> Self { |
| Colorizer { |
| stream, |
| color_when, |
| content: Default::default(), |
| } |
| } |
| |
| pub(crate) fn with_content(mut self, content: StyledStr) -> Self { |
| self.content = content; |
| self |
| } |
| } |
| |
| /// Printing methods. |
| impl Colorizer { |
| #[cfg(feature = "color")] |
| pub(crate) fn print(&self) -> std::io::Result<()> { |
| use termcolor::{BufferWriter, ColorChoice as DepColorChoice}; |
| |
| let color_when = match self.color_when { |
| ColorChoice::Always => DepColorChoice::Always, |
| ColorChoice::Auto if is_a_tty(self.stream) => DepColorChoice::Auto, |
| _ => DepColorChoice::Never, |
| }; |
| |
| let writer = match self.stream { |
| Stream::Stderr => BufferWriter::stderr(color_when), |
| Stream::Stdout => BufferWriter::stdout(color_when), |
| }; |
| |
| let mut buffer = writer.buffer(); |
| ok!(self.content.write_colored(&mut buffer)); |
| writer.print(&buffer) |
| } |
| |
| #[cfg(not(feature = "color"))] |
| pub(crate) fn print(&self) -> std::io::Result<()> { |
| use std::io::Write; |
| |
| // [e]println can't be used here because it panics |
| // if something went wrong. We don't want that. |
| match self.stream { |
| Stream::Stdout => { |
| let stdout = std::io::stdout(); |
| let mut stdout = stdout.lock(); |
| write!(stdout, "{}", self) |
| } |
| Stream::Stderr => { |
| let stderr = std::io::stderr(); |
| let mut stderr = stderr.lock(); |
| write!(stderr, "{}", self) |
| } |
| } |
| } |
| } |
| |
| /// Color-unaware printing. Never uses coloring. |
| impl std::fmt::Display for Colorizer { |
| fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |
| self.content.fmt(f) |
| } |
| } |
| |
| #[cfg(feature = "color")] |
| fn is_a_tty(stream: Stream) -> bool { |
| use is_terminal::IsTerminal; |
| match stream { |
| Stream::Stdout => std::io::stdout().is_terminal(), |
| Stream::Stderr => std::io::stderr().is_terminal(), |
| } |
| } |