use std::fmt::Display;
use std::io::IsTerminal;
use clap::ColorChoice;
use color_eyre::owo_colors::OwoColorize;
mod icons;
pub struct Colorizer {
is_terminal: bool,
color_choice: ColorChoice,
}
impl Colorizer {
pub fn new(out: &impl IsTerminal, color_choice: ColorChoice) -> Self {
Self {
is_terminal: out.is_terminal(),
color_choice,
}
}
pub fn color(&self) -> &ColorChoice {
&self.color_choice
}
fn colorize_with<'i, 'o, I, F, O>(&self, input: &'i I, color_fn: F) -> Box<dyn Display + 'o>
where
'i: 'o,
I: Display + ?Sized,
O: Display + 'o,
F: Fn(&'i I) -> O,
{
match self.color_choice {
ColorChoice::Never => Box::new(input),
ColorChoice::Always => Box::new(color_fn(input)),
ColorChoice::Auto => {
if self.is_terminal {
Box::new(color_fn(input))
} else {
Box::new(input)
}
}
}
}
#[expect(
clippy::unused_self,
reason = "So refactors may be easier by keeping an API identical to the other icons."
)]
pub fn none_icon(&self) -> impl Display {
icons::NONE
}
pub fn unknown_icon(&self) -> impl Display {
self.colorize_with(&icons::UNKNOWN, |icon| icon.bold().yellow().to_string())
}
pub fn todo_icon(&self) -> impl Display {
self.colorize_with(&icons::TODO, |icon| icon.bold().blue().to_string())
}
pub fn new_icon(&self) -> impl Display {
self.colorize_with(&icons::NEW, |icon| icon.bold().green().to_string())
}
pub fn err_icon(&self) -> impl Display {
self.colorize_with(&icons::ERR, char::red)
}
pub fn ok_icon(&self) -> impl Display {
self.colorize_with(&icons::OK, char::green)
}
}