use std::{
borrow::Cow,
fmt::{Debug, Display},
io::IsTerminal,
};
use nu_ansi_term::{AnsiGenericString, Color, Style};
#[derive(Debug, Copy, Clone)]
pub struct ColorCtx {
no_color: bool,
stdout_isatty: bool,
stderr_isatty: bool,
}
#[derive(PartialEq, Debug, Clone)]
pub enum Painting<'a, S: ToOwned + ?Sized>
where
<S as ToOwned>::Owned: Debug,
{
Plain(Cow<'a, S>),
Styled(AnsiGenericString<'a, S>),
}
impl<'a, S: 'a + ToOwned + ?Sized> Display for Painting<'a, S>
where
<S as ToOwned>::Owned: Debug,
Cow<'a, S>: Display,
AnsiGenericString<'a, S>: Display,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Painting::Plain(inner) => inner.fmt(f),
Painting::Styled(inner) => inner.fmt(f),
}
}
}
impl ColorCtx {
pub fn from_env() -> Self {
Self {
no_color: std::env::var_os("NO_COLOR").is_some_and(|x| !x.is_empty()),
stdout_isatty: std::io::stdout().is_terminal(),
stderr_isatty: std::io::stderr().is_terminal(),
}
}
pub fn paint<'a, P: Paint, I, S: 'a + ToOwned + ?Sized>(
&self,
p: P,
input: I,
) -> Painting<'a, S>
where
I: Into<Cow<'a, S>>,
<S as ToOwned>::Owned: Debug,
{
if self.no_color || !self.stdout_isatty {
Painting::Plain(input.into())
} else {
Painting::Styled(p.paint(input))
}
}
pub fn paint_err<'a, P: Paint, I, S: 'a + ToOwned + ?Sized>(
&self,
p: P,
input: I,
) -> Painting<'a, S>
where
I: Into<Cow<'a, S>>,
<S as ToOwned>::Owned: Debug,
{
if self.no_color || !self.stderr_isatty {
Painting::Plain(input.into())
} else {
Painting::Styled(p.paint(input))
}
}
}
pub trait Paint {
fn paint<'a, I, S: 'a + ToOwned + ?Sized>(self, input: I) -> AnsiGenericString<'a, S>
where
I: Into<Cow<'a, S>>,
<S as ToOwned>::Owned: Debug;
}
impl Paint for Style {
fn paint<'a, I, S: 'a + ToOwned + ?Sized>(self, input: I) -> AnsiGenericString<'a, S>
where
I: Into<Cow<'a, S>>,
<S as ToOwned>::Owned: Debug,
{
self.paint(input)
}
}
impl Paint for Color {
fn paint<'a, I, S: 'a + ToOwned + ?Sized>(self, input: I) -> AnsiGenericString<'a, S>
where
I: Into<Cow<'a, S>>,
<S as ToOwned>::Owned: Debug,
{
self.paint(input)
}
}