2024-01-01 14:58:21 -05:00
|
|
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
2021-09-12 12:04:17 -04:00
|
|
|
|
2021-12-18 16:14:42 -05:00
|
|
|
use once_cell::sync::Lazy;
|
2020-12-13 13:45:53 -05:00
|
|
|
use std::fmt;
|
2024-01-16 08:58:01 -05:00
|
|
|
use std::fmt::Write as _;
|
2023-08-25 09:43:07 -04:00
|
|
|
use std::io::IsTerminal;
|
2023-01-14 23:18:58 -05:00
|
|
|
use termcolor::Ansi;
|
|
|
|
use termcolor::Color::Ansi256;
|
|
|
|
use termcolor::Color::Black;
|
|
|
|
use termcolor::Color::Blue;
|
|
|
|
use termcolor::Color::Cyan;
|
|
|
|
use termcolor::Color::Green;
|
2023-03-25 10:29:46 -04:00
|
|
|
use termcolor::Color::Magenta;
|
2023-01-14 23:18:58 -05:00
|
|
|
use termcolor::Color::Red;
|
|
|
|
use termcolor::Color::White;
|
|
|
|
use termcolor::Color::Yellow;
|
|
|
|
use termcolor::ColorSpec;
|
|
|
|
use termcolor::WriteColor;
|
2020-12-13 13:45:53 -05:00
|
|
|
|
|
|
|
#[cfg(windows)]
|
2023-01-14 23:18:58 -05:00
|
|
|
use termcolor::BufferWriter;
|
|
|
|
#[cfg(windows)]
|
|
|
|
use termcolor::ColorChoice;
|
2020-12-13 13:45:53 -05:00
|
|
|
|
2023-11-20 15:58:22 -05:00
|
|
|
static NO_COLOR: Lazy<bool> = Lazy::new(|| {
|
|
|
|
std::env::var_os("NO_COLOR")
|
|
|
|
.map(|v| !v.is_empty())
|
|
|
|
.unwrap_or(false)
|
|
|
|
});
|
2020-12-13 13:45:53 -05:00
|
|
|
|
2023-08-25 09:43:07 -04:00
|
|
|
static IS_TTY: Lazy<bool> = Lazy::new(|| std::io::stdout().is_terminal());
|
2022-02-28 22:37:50 -05:00
|
|
|
|
|
|
|
pub fn is_tty() -> bool {
|
|
|
|
*IS_TTY
|
|
|
|
}
|
|
|
|
|
2020-12-13 13:45:53 -05:00
|
|
|
pub fn use_color() -> bool {
|
2021-12-11 10:23:30 -05:00
|
|
|
!(*NO_COLOR)
|
2020-12-13 13:45:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(windows)]
|
|
|
|
pub fn enable_ansi() {
|
|
|
|
BufferWriter::stdout(ColorChoice::AlwaysAnsi);
|
|
|
|
}
|
|
|
|
|
2024-01-16 08:58:01 -05:00
|
|
|
/// A struct that can adapt a `fmt::Write` to a `std::io::Write`. If anything
|
|
|
|
/// that can not be represented as UTF-8 is written to this writer, it will
|
|
|
|
/// return an error.
|
|
|
|
struct StdFmtStdIoWriter<'a>(&'a mut dyn fmt::Write);
|
|
|
|
|
|
|
|
impl std::io::Write for StdFmtStdIoWriter<'_> {
|
|
|
|
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
|
|
|
let str = std::str::from_utf8(buf).map_err(|_| {
|
|
|
|
std::io::Error::new(
|
|
|
|
std::io::ErrorKind::Other,
|
|
|
|
"failed to convert bytes to str",
|
|
|
|
)
|
|
|
|
})?;
|
|
|
|
match self.0.write_str(str) {
|
|
|
|
Ok(_) => Ok(buf.len()),
|
|
|
|
Err(_) => Err(std::io::Error::new(
|
|
|
|
std::io::ErrorKind::Other,
|
|
|
|
"failed to write to fmt::Write",
|
|
|
|
)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn flush(&mut self) -> std::io::Result<()> {
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A struct that can adapt a `std::io::Write` to a `fmt::Write`.
|
|
|
|
struct StdIoStdFmtWriter<'a>(&'a mut dyn std::io::Write);
|
|
|
|
|
|
|
|
impl fmt::Write for StdIoStdFmtWriter<'_> {
|
|
|
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
|
|
|
self.0.write_all(s.as_bytes()).map_err(|_| fmt::Error)?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Style<I: fmt::Display> {
|
|
|
|
colorspec: ColorSpec,
|
|
|
|
inner: I,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<I: fmt::Display> fmt::Display for Style<I> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
if !use_color() {
|
|
|
|
return fmt::Display::fmt(&self.inner, f);
|
|
|
|
}
|
|
|
|
let mut ansi_writer = Ansi::new(StdFmtStdIoWriter(f));
|
|
|
|
ansi_writer
|
|
|
|
.set_color(&self.colorspec)
|
|
|
|
.map_err(|_| fmt::Error)?;
|
|
|
|
write!(StdIoStdFmtWriter(&mut ansi_writer), "{}", self.inner)?;
|
|
|
|
ansi_writer.reset().map_err(|_| fmt::Error)?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn style<'a>(
|
|
|
|
s: impl fmt::Display + 'a,
|
|
|
|
colorspec: ColorSpec,
|
|
|
|
) -> impl fmt::Display + 'a {
|
|
|
|
Style {
|
|
|
|
colorspec,
|
|
|
|
inner: s,
|
2020-12-13 13:45:53 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-16 08:58:01 -05:00
|
|
|
pub fn red_bold<'a>(s: impl fmt::Display + 'a) -> impl fmt::Display + 'a {
|
2020-12-13 13:45:53 -05:00
|
|
|
let mut style_spec = ColorSpec::new();
|
|
|
|
style_spec.set_fg(Some(Red)).set_bold(true);
|
2021-07-30 09:03:41 -04:00
|
|
|
style(s, style_spec)
|
2020-12-13 13:45:53 -05:00
|
|
|
}
|
|
|
|
|
2024-01-16 08:58:01 -05:00
|
|
|
pub fn green_bold<'a>(s: impl fmt::Display + 'a) -> impl fmt::Display + 'a {
|
2020-12-13 13:45:53 -05:00
|
|
|
let mut style_spec = ColorSpec::new();
|
|
|
|
style_spec.set_fg(Some(Green)).set_bold(true);
|
2021-07-30 09:03:41 -04:00
|
|
|
style(s, style_spec)
|
2020-12-13 13:45:53 -05:00
|
|
|
}
|
|
|
|
|
2024-01-16 08:58:01 -05:00
|
|
|
pub fn italic<'a>(s: impl fmt::Display + 'a) -> impl fmt::Display + 'a {
|
2021-09-12 12:04:17 -04:00
|
|
|
let mut style_spec = ColorSpec::new();
|
|
|
|
style_spec.set_italic(true);
|
|
|
|
style(s, style_spec)
|
|
|
|
}
|
|
|
|
|
2024-01-16 08:58:01 -05:00
|
|
|
pub fn italic_gray<'a>(s: impl fmt::Display + 'a) -> impl fmt::Display + 'a {
|
2021-09-12 12:04:17 -04:00
|
|
|
let mut style_spec = ColorSpec::new();
|
|
|
|
style_spec.set_fg(Some(Ansi256(8))).set_italic(true);
|
|
|
|
style(s, style_spec)
|
|
|
|
}
|
|
|
|
|
2024-01-16 08:58:01 -05:00
|
|
|
pub fn italic_bold<'a>(s: impl fmt::Display + 'a) -> impl fmt::Display + 'a {
|
2020-12-13 13:45:53 -05:00
|
|
|
let mut style_spec = ColorSpec::new();
|
|
|
|
style_spec.set_bold(true).set_italic(true);
|
2021-07-30 09:03:41 -04:00
|
|
|
style(s, style_spec)
|
2020-12-13 13:45:53 -05:00
|
|
|
}
|
|
|
|
|
2024-01-16 08:58:01 -05:00
|
|
|
pub fn white_on_red<'a>(s: impl fmt::Display + 'a) -> impl fmt::Display + 'a {
|
2020-12-13 13:45:53 -05:00
|
|
|
let mut style_spec = ColorSpec::new();
|
|
|
|
style_spec.set_bg(Some(Red)).set_fg(Some(White));
|
2021-07-30 09:03:41 -04:00
|
|
|
style(s, style_spec)
|
2020-12-13 13:45:53 -05:00
|
|
|
}
|
|
|
|
|
2024-01-16 08:58:01 -05:00
|
|
|
pub fn black_on_green<'a>(s: impl fmt::Display + 'a) -> impl fmt::Display + 'a {
|
2020-12-13 13:45:53 -05:00
|
|
|
let mut style_spec = ColorSpec::new();
|
|
|
|
style_spec.set_bg(Some(Green)).set_fg(Some(Black));
|
2021-07-30 09:03:41 -04:00
|
|
|
style(s, style_spec)
|
2020-12-13 13:45:53 -05:00
|
|
|
}
|
|
|
|
|
2024-01-16 08:58:01 -05:00
|
|
|
pub fn yellow<'a>(s: impl fmt::Display + 'a) -> impl fmt::Display + 'a {
|
2020-12-13 13:45:53 -05:00
|
|
|
let mut style_spec = ColorSpec::new();
|
|
|
|
style_spec.set_fg(Some(Yellow));
|
2021-07-30 09:03:41 -04:00
|
|
|
style(s, style_spec)
|
2020-12-13 13:45:53 -05:00
|
|
|
}
|
|
|
|
|
2024-01-16 08:58:01 -05:00
|
|
|
pub fn cyan<'a>(s: impl fmt::Display + 'a) -> impl fmt::Display + 'a {
|
2020-12-13 13:45:53 -05:00
|
|
|
let mut style_spec = ColorSpec::new();
|
|
|
|
style_spec.set_fg(Some(Cyan));
|
2021-07-30 09:03:41 -04:00
|
|
|
style(s, style_spec)
|
2020-12-13 13:45:53 -05:00
|
|
|
}
|
2023-12-12 09:45:45 -05:00
|
|
|
|
2024-01-16 08:58:01 -05:00
|
|
|
pub fn cyan_with_underline<'a>(
|
|
|
|
s: impl fmt::Display + 'a,
|
|
|
|
) -> impl fmt::Display + 'a {
|
2023-12-12 09:45:45 -05:00
|
|
|
let mut style_spec = ColorSpec::new();
|
|
|
|
style_spec.set_fg(Some(Cyan)).set_underline(true);
|
|
|
|
style(s, style_spec)
|
|
|
|
}
|
|
|
|
|
2024-01-16 08:58:01 -05:00
|
|
|
pub fn cyan_bold<'a>(s: impl fmt::Display + 'a) -> impl fmt::Display + 'a {
|
2023-03-25 10:29:46 -04:00
|
|
|
let mut style_spec = ColorSpec::new();
|
|
|
|
style_spec.set_fg(Some(Cyan)).set_bold(true);
|
|
|
|
style(s, style_spec)
|
|
|
|
}
|
|
|
|
|
2024-01-16 08:58:01 -05:00
|
|
|
pub fn magenta<'a>(s: impl fmt::Display + 'a) -> impl fmt::Display + 'a {
|
2023-03-25 10:29:46 -04:00
|
|
|
let mut style_spec = ColorSpec::new();
|
|
|
|
style_spec.set_fg(Some(Magenta));
|
|
|
|
style(s, style_spec)
|
|
|
|
}
|
2020-12-13 13:45:53 -05:00
|
|
|
|
2024-01-16 08:58:01 -05:00
|
|
|
pub fn red<'a>(s: impl fmt::Display + 'a) -> impl fmt::Display + 'a {
|
2020-12-13 13:45:53 -05:00
|
|
|
let mut style_spec = ColorSpec::new();
|
|
|
|
style_spec.set_fg(Some(Red));
|
2021-07-30 09:03:41 -04:00
|
|
|
style(s, style_spec)
|
2020-12-13 13:45:53 -05:00
|
|
|
}
|
|
|
|
|
2024-01-16 08:58:01 -05:00
|
|
|
pub fn green<'a>(s: impl fmt::Display + 'a) -> impl fmt::Display + 'a {
|
2020-12-13 13:45:53 -05:00
|
|
|
let mut style_spec = ColorSpec::new();
|
|
|
|
style_spec.set_fg(Some(Green));
|
2021-07-30 09:03:41 -04:00
|
|
|
style(s, style_spec)
|
2020-12-13 13:45:53 -05:00
|
|
|
}
|
|
|
|
|
2024-01-16 08:58:01 -05:00
|
|
|
pub fn bold<'a>(s: impl fmt::Display + 'a) -> impl fmt::Display + 'a {
|
2020-12-13 13:45:53 -05:00
|
|
|
let mut style_spec = ColorSpec::new();
|
|
|
|
style_spec.set_bold(true);
|
2021-07-30 09:03:41 -04:00
|
|
|
style(s, style_spec)
|
2020-12-13 13:45:53 -05:00
|
|
|
}
|
|
|
|
|
2024-01-16 08:58:01 -05:00
|
|
|
pub fn gray<'a>(s: impl fmt::Display + 'a) -> impl fmt::Display + 'a {
|
2020-12-13 13:45:53 -05:00
|
|
|
let mut style_spec = ColorSpec::new();
|
2022-04-24 15:00:26 -04:00
|
|
|
style_spec.set_fg(Some(Ansi256(245)));
|
2021-07-30 09:03:41 -04:00
|
|
|
style(s, style_spec)
|
2020-12-13 13:45:53 -05:00
|
|
|
}
|
|
|
|
|
2024-01-16 08:58:01 -05:00
|
|
|
pub fn intense_blue<'a>(s: impl fmt::Display + 'a) -> impl fmt::Display + 'a {
|
2020-12-13 13:45:53 -05:00
|
|
|
let mut style_spec = ColorSpec::new();
|
|
|
|
style_spec.set_fg(Some(Blue)).set_intense(true);
|
2021-07-30 09:03:41 -04:00
|
|
|
style(s, style_spec)
|
2020-12-13 13:45:53 -05:00
|
|
|
}
|
2022-05-09 04:56:13 -04:00
|
|
|
|
2024-01-16 08:58:01 -05:00
|
|
|
pub fn white_bold_on_red<'a>(
|
|
|
|
s: impl fmt::Display + 'a,
|
|
|
|
) -> impl fmt::Display + 'a {
|
2022-05-09 04:56:13 -04:00
|
|
|
let mut style_spec = ColorSpec::new();
|
|
|
|
style_spec
|
|
|
|
.set_bold(true)
|
|
|
|
.set_bg(Some(Red))
|
|
|
|
.set_fg(Some(White));
|
|
|
|
style(s, style_spec)
|
|
|
|
}
|