2020-08-22 09:43:58 +00:00
|
|
|
#[cfg(not(feature = "color"))]
|
|
|
|
use crate::util::termcolor::{Color, ColorChoice};
|
2020-04-12 08:20:08 +00:00
|
|
|
#[cfg(feature = "color")]
|
2020-08-22 09:43:58 +00:00
|
|
|
use termcolor::{Color, ColorChoice};
|
2020-04-12 01:39:13 +00:00
|
|
|
|
2020-04-27 18:47:08 +00:00
|
|
|
use std::{
|
2020-08-22 09:43:58 +00:00
|
|
|
fmt::{self, Display, Formatter},
|
|
|
|
io::{self, Write},
|
2020-04-27 18:47:08 +00:00
|
|
|
};
|
2016-05-30 08:07:44 +00:00
|
|
|
|
|
|
|
#[cfg(feature = "color")]
|
2020-04-12 01:39:13 +00:00
|
|
|
fn is_a_tty(stderr: bool) -> bool {
|
2020-04-22 18:14:47 +00:00
|
|
|
debug!("is_a_tty: stderr={:?}", stderr);
|
2020-04-12 01:39:13 +00:00
|
|
|
|
2017-02-19 16:12:55 +00:00
|
|
|
let stream = if stderr {
|
|
|
|
atty::Stream::Stderr
|
|
|
|
} else {
|
|
|
|
atty::Stream::Stdout
|
|
|
|
};
|
2020-04-12 01:39:13 +00:00
|
|
|
|
2017-02-19 16:12:55 +00:00
|
|
|
atty::is(stream)
|
2016-05-30 08:07:44 +00:00
|
|
|
}
|
|
|
|
|
2020-08-22 09:43:58 +00:00
|
|
|
#[derive(Debug)]
|
2020-03-19 07:17:52 +00:00
|
|
|
pub(crate) struct Colorizer {
|
2020-08-22 09:43:58 +00:00
|
|
|
use_stderr: bool,
|
|
|
|
color_when: ColorChoice,
|
|
|
|
pieces: Vec<(String, Option<Color>)>,
|
2016-05-30 08:07:44 +00:00
|
|
|
}
|
|
|
|
|
2020-08-22 09:43:58 +00:00
|
|
|
impl Colorizer {
|
|
|
|
#[inline]
|
|
|
|
pub(crate) fn new(use_stderr: bool, color_when: ColorChoice) -> Self {
|
|
|
|
Colorizer {
|
|
|
|
use_stderr,
|
|
|
|
color_when,
|
|
|
|
pieces: vec![],
|
|
|
|
}
|
2020-04-12 01:39:13 +00:00
|
|
|
}
|
|
|
|
|
2020-08-22 09:43:58 +00:00
|
|
|
#[inline]
|
|
|
|
pub(crate) fn good(&mut self, msg: impl Into<String>) {
|
|
|
|
self.pieces.push((msg.into(), Some(Color::Green)));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub(crate) fn warning(&mut self, msg: impl Into<String>) {
|
|
|
|
self.pieces.push((msg.into(), Some(Color::Yellow)));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub(crate) fn error(&mut self, msg: impl Into<String>) {
|
|
|
|
self.pieces.push((msg.into(), Some(Color::Red)));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub(crate) fn none(&mut self, msg: impl Into<String>) {
|
|
|
|
self.pieces.push((msg.into(), None));
|
2020-04-12 01:39:13 +00:00
|
|
|
}
|
2016-05-30 08:07:44 +00:00
|
|
|
}
|
|
|
|
|
2020-08-22 09:43:58 +00:00
|
|
|
/// Printing methods.
|
2016-05-30 08:07:44 +00:00
|
|
|
impl Colorizer {
|
2020-08-22 09:43:58 +00:00
|
|
|
#[cfg(feature = "color")]
|
|
|
|
pub(crate) fn print(&self) -> io::Result<()> {
|
|
|
|
use termcolor::{BufferWriter, ColorSpec, WriteColor};
|
|
|
|
|
|
|
|
let color_when = if is_a_tty(self.use_stderr) {
|
|
|
|
self.color_when
|
2020-04-12 01:39:13 +00:00
|
|
|
} else {
|
|
|
|
ColorChoice::Never
|
|
|
|
};
|
|
|
|
|
2020-08-22 09:43:58 +00:00
|
|
|
let writer = if self.use_stderr {
|
|
|
|
BufferWriter::stderr(color_when)
|
2020-04-12 01:39:13 +00:00
|
|
|
} else {
|
2020-08-22 09:43:58 +00:00
|
|
|
BufferWriter::stdout(color_when)
|
2020-04-12 01:39:13 +00:00
|
|
|
};
|
|
|
|
|
2020-08-22 09:43:58 +00:00
|
|
|
let mut buffer = writer.buffer();
|
2020-04-12 01:39:13 +00:00
|
|
|
|
2020-08-22 09:43:58 +00:00
|
|
|
for piece in &self.pieces {
|
|
|
|
let mut color = ColorSpec::new();
|
|
|
|
color.set_fg(piece.1);
|
|
|
|
if piece.1 == Some(Color::Red) {
|
|
|
|
color.set_bold(true);
|
|
|
|
}
|
2017-05-26 22:25:38 +00:00
|
|
|
|
2020-08-22 09:43:58 +00:00
|
|
|
buffer.set_color(&color)?;
|
|
|
|
buffer.write_all(piece.0.as_bytes())?;
|
|
|
|
buffer.reset()?;
|
|
|
|
}
|
2016-05-30 08:07:44 +00:00
|
|
|
|
2020-08-22 09:43:58 +00:00
|
|
|
writer.print(&buffer)
|
2016-05-30 08:07:44 +00:00
|
|
|
}
|
|
|
|
|
2020-04-12 01:39:13 +00:00
|
|
|
#[cfg(not(feature = "color"))]
|
2020-08-22 09:43:58 +00:00
|
|
|
pub(crate) fn print(&self) -> io::Result<()> {
|
|
|
|
// [e]println can't be used here because it panics
|
|
|
|
// if something went wrong. We don't want that.
|
|
|
|
if self.use_stderr {
|
|
|
|
let stderr = std::io::stderr();
|
|
|
|
let mut stderr = stderr.lock();
|
|
|
|
write!(stderr, "{}", self)
|
|
|
|
} else {
|
|
|
|
let stdout = std::io::stdout();
|
|
|
|
let mut stdout = stdout.lock();
|
|
|
|
write!(stdout, "{}", self)
|
|
|
|
}
|
2020-01-31 09:13:44 +00:00
|
|
|
}
|
2016-05-30 08:07:44 +00:00
|
|
|
}
|
|
|
|
|
2020-08-22 09:43:58 +00:00
|
|
|
/// Color-unaware printing. Never uses coloring.
|
|
|
|
impl Display for Colorizer {
|
|
|
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
|
|
for piece in &self.pieces {
|
|
|
|
Display::fmt(&piece.0, f)?;
|
|
|
|
}
|
2015-09-04 15:38:48 +00:00
|
|
|
|
2020-08-22 09:43:58 +00:00
|
|
|
Ok(())
|
2015-09-04 15:38:48 +00:00
|
|
|
}
|
2015-09-07 01:07:46 +00:00
|
|
|
}
|