#![allow(dead_code)]
use fmt::Debug;
use once_cell::sync::Lazy;
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: Lazy<Self> = Lazy::new(|| Self::new(232, 0));
const RED: Lazy<Self> = Lazy::new(|| Self::new(1, 0));
const GREEN: Lazy<Self> = Lazy::new(|| Self::new(2, 0));
const BLUE: Lazy<Self> = Lazy::new(|| Self::new(4, 0));
const PURPLE: Lazy<Self> = Lazy::new(|| Self::new(5, 0));
const DARK_CYAN: Lazy<Self> = Lazy::new(|| Self::new(6, 0));
const LIGHT_GREY: Lazy<Self> = Lazy::new(|| Self::new(7, 0));
const DARK_GREY: Lazy<Self> = Lazy::new(|| Self::new(8, 0));
const BRIGHT_RED: Lazy<Self> = Lazy::new(|| Self::new(9, 0));
const LIGHT_GREEN: Lazy<Self> = Lazy::new(|| Self::new(10, 0));
const YELLOW: Lazy<Self> = Lazy::new(|| Self::new(11, 0));
const LIGHT_BLUE: Lazy<Self> = Lazy::new(|| Self::new(12, 0));
const MAGENTA: Lazy<Self> = Lazy::new(|| Self::new(13, 0));
const CYAN: Lazy<Self> = Lazy::new(|| Self::new(14, 0));
const WHITE: Lazy<Self> = Lazy::new(|| Self::new(15, 0));
const DEFAULT: Lazy<Self> = Lazy::new(|| Self::new(0, 0));
pub fn black() -> Self {
Self::BLACK.clone()
}
pub fn red() -> Self {
Self::RED.clone()
}
pub fn green() -> Self {
Self::GREEN.clone()
}
pub fn blue() -> Self {
Self::BLUE.clone()
}
pub fn purple() -> Self {
Self::PURPLE.clone()
}
pub fn dark_cyan() -> Self {
Self::DARK_CYAN.clone()
}
pub fn light_grey() -> Self {
Self::LIGHT_GREY.clone()
}
pub fn dark_grey() -> Self {
Self::DARK_GREY.clone()
}
pub fn bright_red() -> Self {
Self::BRIGHT_RED.clone()
}
pub fn light_green() -> Self {
Self::LIGHT_GREEN.clone()
}
pub fn yellow() -> Self {
Self::YELLOW.clone()
}
pub fn light_blue() -> Self {
Self::LIGHT_BLUE.clone()
}
pub fn magenta() -> Self {
Self::MAGENTA.clone()
}
pub fn cyan() -> Self {
Self::CYAN.clone()
}
pub fn white() -> Self {
Self::WHITE.clone()
}
pub fn new(fg: u8, bg: u8) -> Self {
Self {
fg: NonZeroU8::new(fg),
bg: NonZeroU8::new(bg),
..Default::default()
}
}
}
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 {}