#![allow(dead_code)]
use fmt::Debug;
use std::{
fmt::{self, Display, Formatter},
num::NonZeroU8,
};
#[derive(Default, Copy, Clone)]
pub struct AnsiColor {
fg: Option<NonZeroU8>,
bg: Option<NonZeroU8>,
bold: bool,
italic: bool,
}
impl AnsiColor {
const BLACK: Self = Self::new(232, 0);
const RED: Self = Self::new(1, 0);
const GREEN: Self = Self::new(2, 0);
const BLUE: Self = Self::new(4, 0);
const PURPLE: Self = Self::new(5, 0);
const DARK_CYAN: Self = Self::new(6, 0);
const LIGHT_GREY: Self = Self::new(7, 0);
const DARK_GREY: Self = Self::new(8, 0);
const BRIGHT_RED: Self = Self::new(9, 0);
const LIGHT_GREEN: Self = Self::new(10, 0);
const YELLOW: Self = Self::new(11, 0);
const LIGHT_BLUE: Self = Self::new(12, 0);
const MAGENTA: Self = Self::new(13, 0);
const CYAN: Self = Self::new(14, 0);
const WHITE: Self = Self::new(15, 0);
const DEFAULT: Self = Self::new(0, 0);
pub fn black() -> Self {
Self::BLACK
}
pub fn red() -> Self {
Self::RED
}
pub fn green() -> Self {
Self::GREEN
}
pub fn blue() -> Self {
Self::BLUE
}
pub fn purple() -> Self {
Self::PURPLE
}
pub fn dark_cyan() -> Self {
Self::DARK_CYAN
}
pub fn light_grey() -> Self {
Self::LIGHT_GREY
}
pub fn dark_grey() -> Self {
Self::DARK_GREY
}
pub fn bright_red() -> Self {
Self::BRIGHT_RED
}
pub fn light_green() -> Self {
Self::LIGHT_GREEN
}
pub fn yellow() -> Self {
Self::YELLOW
}
pub fn light_blue() -> Self {
Self::LIGHT_BLUE
}
pub fn magenta() -> Self {
Self::MAGENTA
}
pub fn cyan() -> Self {
Self::CYAN
}
pub fn white() -> Self {
Self::WHITE
}
pub const fn new(fg: u8, bg: u8) -> Self {
Self {
fg: NonZeroU8::new(fg),
bg: NonZeroU8::new(bg),
bold: false,
italic: false,
}
}
}
impl Display for AnsiColor {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
if let Some(n) = self.fg {
write!(f, "\x1b[38;5;{}m", n)?;
}
if let Some(n) = self.bg {
write!(f, "\x1b[48;5;{}m", n)?;
}
if self.bold {
write!(f, "\x1b[1m")?;
}
if self.italic {
write!(f, "\x1b[3m")?;
}
Ok(())
}
}
pub struct Colored<'a, T: 'a> {
val: &'a T,
col: AnsiColor,
}
impl<T> Colored<'_, T> {
pub fn with_fg_color(self, fg: u8) -> Self {
Self {
col: AnsiColor::new(fg, self.col.bg.map_or(0, |n| n.into())),
val: self.val,
}
}
pub fn with_bg_color(self, bg: u8) -> Self {
Self {
col: AnsiColor::new(self.col.fg.map_or(0, |n| n.into()), bg),
val: self.val,
}
}
pub fn bold(self) -> Self {
self.with_bold(true)
}
pub fn italic(self) -> Self {
self.with_italic(true)
}
pub fn with_bold(self, bold: bool) -> Self {
Self {
val: self.val,
col: AnsiColor { bold, ..self.col },
}
}
pub fn with_italic(self, italic: bool) -> Self {
Self {
val: self.val,
col: AnsiColor { italic, ..self.col },
}
}
}
impl<T: Display> Display for Colored<'_, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}{}\x1b[m", self.col, self.val)
}
}
#[doc(hidden)]
pub trait Colorable {
fn black(&self) -> Colored<Self>
where
Self: Sized,
{
Colored {
col: AnsiColor::black(),
val: self,
}
}
fn red(&self) -> Colored<Self>
where
Self: Sized,
{
Colored {
col: AnsiColor::red(),
val: self,
}
}
fn green(&self) -> Colored<Self>
where
Self: Sized,
{
Colored {
col: AnsiColor::green(),
val: self,
}
}
fn blue(&self) -> Colored<Self>
where
Self: Sized,
{
Colored {
col: AnsiColor::blue(),
val: self,
}
}
fn purple(&self) -> Colored<Self>
where
Self: Sized,
{
Colored {
col: AnsiColor::purple(),
val: self,
}
}
fn dark_cyan(&self) -> Colored<Self>
where
Self: Sized,
{
Colored {
col: AnsiColor::dark_cyan(),
val: self,
}
}
fn light_grey(&self) -> Colored<Self>
where
Self: Sized,
{
Colored {
col: AnsiColor::light_grey(),
val: self,
}
}
fn dark_grey(&self) -> Colored<Self>
where
Self: Sized,
{
Colored {
col: AnsiColor::dark_grey(),
val: self,
}
}
fn bright_red(&self) -> Colored<Self>
where
Self: Sized,
{
Colored {
col: AnsiColor::bright_red(),
val: self,
}
}
fn light_green(&self) -> Colored<Self>
where
Self: Sized,
{
Colored {
col: AnsiColor::light_green(),
val: self,
}
}
fn yellow(&self) -> Colored<Self>
where
Self: Sized,
{
Colored {
col: AnsiColor::yellow(),
val: self,
}
}
fn light_blue(&self) -> Colored<Self>
where
Self: Sized,
{
Colored {
col: AnsiColor::light_blue(),
val: self,
}
}
fn magenta(&self) -> Colored<Self>
where
Self: Sized,
{
Colored {
col: AnsiColor::magenta(),
val: self,
}
}
fn cyan(&self) -> Colored<Self>
where
Self: Sized,
{
Colored {
col: AnsiColor::cyan(),
val: self,
}
}
fn white(&self) -> Colored<Self>
where
Self: Sized,
{
Colored {
col: AnsiColor::white(),
val: self,
}
}
fn bold(&self) -> Colored<Self>
where
Self: Sized,
{
Colored {
val: self,
col: AnsiColor {
bold: true,
..Default::default()
},
}
}
fn italic(&self) -> Colored<Self>
where
Self: Sized,
{
Colored {
val: self,
col: AnsiColor {
italic: true,
..Default::default()
},
}
}
fn with_fg_color(&self, fg: u8) -> Colored<Self>
where
Self: Sized,
{
Colored {
col: AnsiColor::new(fg, 0),
val: self,
}
}
fn with_fg_bg(&self, fg: u8, bg: u8) -> Colored<Self>
where
Self: Sized,
{
Colored {
col: AnsiColor::new(fg, bg),
val: self,
}
}
}
impl<T: Display> Colorable for T {}
pub struct ColoredDbg<'a, T: 'a> {
val: &'a T,
col: AnsiColor,
}
impl<T> ColoredDbg<'_, T> {
pub fn with_fg_color_dbg(self, fg: u8) -> Self {
Self {
col: AnsiColor::new(fg, self.col.bg.map_or(0, |n| n.into())),
val: self.val,
}
}
pub fn with_bg_color_dbg(self, bg: u8) -> Self {
Self {
col: AnsiColor::new(self.col.fg.map_or(0, |n| n.into()), bg),
val: self.val,
}
}
pub fn bold_dbg(self) -> Self {
self.with_bold_dbg(true)
}
pub fn italic_dbg(self) -> Self {
self.with_italic_dbg(true)
}
pub fn with_bold_dbg(self, bold: bool) -> Self {
Self {
val: self.val,
col: AnsiColor { bold, ..self.col },
}
}
pub fn with_italic_dbg(self, italic: bool) -> Self {
Self {
val: self.val,
col: AnsiColor { italic, ..self.col },
}
}
}
impl<T: Debug> Debug for ColoredDbg<'_, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}{:?}\x1b[m", self.col, self.val)
}
}
#[doc(hidden)]
pub trait ColorableDbg {
fn black_dbg(&self) -> ColoredDbg<Self>
where
Self: Sized,
{
ColoredDbg {
col: AnsiColor::black(),
val: self,
}
}
fn red_dbg(&self) -> ColoredDbg<Self>
where
Self: Sized,
{
ColoredDbg {
col: AnsiColor::red(),
val: self,
}
}
fn green_dbg(&self) -> ColoredDbg<Self>
where
Self: Sized,
{
ColoredDbg {
col: AnsiColor::green(),
val: self,
}
}
fn blue_dbg(&self) -> ColoredDbg<Self>
where
Self: Sized,
{
ColoredDbg {
col: AnsiColor::blue(),
val: self,
}
}
fn purple_dbg(&self) -> ColoredDbg<Self>
where
Self: Sized,
{
ColoredDbg {
col: AnsiColor::purple(),
val: self,
}
}
fn dark_cyan_dbg(&self) -> ColoredDbg<Self>
where
Self: Sized,
{
ColoredDbg {
col: AnsiColor::dark_cyan(),
val: self,
}
}
fn light_grey_dbg(&self) -> ColoredDbg<Self>
where
Self: Sized,
{
ColoredDbg {
col: AnsiColor::light_grey(),
val: self,
}
}
fn dark_grey_dbg(&self) -> ColoredDbg<Self>
where
Self: Sized,
{
ColoredDbg {
col: AnsiColor::dark_grey(),
val: self,
}
}
fn bright_red_dbg(&self) -> ColoredDbg<Self>
where
Self: Sized,
{
ColoredDbg {
col: AnsiColor::bright_red(),
val: self,
}
}
fn light_green_dbg(&self) -> ColoredDbg<Self>
where
Self: Sized,
{
ColoredDbg {
col: AnsiColor::light_green(),
val: self,
}
}
fn yellow_dbg(&self) -> ColoredDbg<Self>
where
Self: Sized,
{
ColoredDbg {
col: AnsiColor::yellow(),
val: self,
}
}
fn light_blue_dbg(&self) -> ColoredDbg<Self>
where
Self: Sized,
{
ColoredDbg {
col: AnsiColor::light_blue(),
val: self,
}
}
fn magenta_dbg(&self) -> ColoredDbg<Self>
where
Self: Sized,
{
ColoredDbg {
col: AnsiColor::magenta(),
val: self,
}
}
fn cyan_dbg(&self) -> ColoredDbg<Self>
where
Self: Sized,
{
ColoredDbg {
col: AnsiColor::cyan(),
val: self,
}
}
fn white_dbg(&self) -> ColoredDbg<Self>
where
Self: Sized,
{
ColoredDbg {
col: AnsiColor::white(),
val: self,
}
}
fn bold_dbg(&self) -> ColoredDbg<Self>
where
Self: Sized,
{
ColoredDbg {
val: self,
col: AnsiColor {
bold: true,
..Default::default()
},
}
}
fn italic_dbg(&self) -> ColoredDbg<Self>
where
Self: Sized,
{
ColoredDbg {
val: self,
col: AnsiColor {
italic: true,
..Default::default()
},
}
}
fn with_fg_color_dbg(&self, fg: u8) -> ColoredDbg<Self>
where
Self: Sized,
{
ColoredDbg {
col: AnsiColor::new(fg, 0),
val: self,
}
}
fn with_fg_bg_dbg(&self, fg: u8, bg: u8) -> ColoredDbg<Self>
where
Self: Sized,
{
ColoredDbg {
col: AnsiColor::new(fg, bg),
val: self,
}
}
}
impl<T: Debug> ColorableDbg for T {}