bright 0.4.1

Beautiful terminal color
Documentation
#![allow(dead_code)]
use std::fmt;

#[derive(Debug, Clone, Copy)]
pub enum Style {
    Bold,
    Dim,
    Italic,
    Underline,
    SlowBlink,
    FastBlink,
    Invert,
    Hidden,
    CrossOut,
}

#[derive(Debug, Clone, Copy)]
pub enum Color {
    Black,
    Red,
    Green,
    Yellow,
    Blue,
    Magenta,
    Cyan,
    White,
    Rgb(u8, u8, u8),
}

#[derive(Debug, Clone, Copy)]
enum Value {
    Single(u8),
    Multiple(u8, u8, u8, u8, u8),
}

fn get_style_value(style: &Style) -> String {
    match style {
        Style::Bold => 1,
        Style::Dim => 2,
        Style::Italic => 3,
        Style::Underline => 4,
        Style::SlowBlink => 5,
        Style::FastBlink => 6,
        Style::Invert => 7,
        Style::Hidden => 8,
        Style::CrossOut => 9,
    }
    .to_string()
}

fn get_color_value(color: &Color) -> Value {
    match color {
        Color::Black => Value::Single(30),
        Color::Red => Value::Single(31),
        Color::Green => Value::Single(32),
        Color::Yellow => Value::Single(33),
        Color::Blue => Value::Single(34),
        Color::Magenta => Value::Single(35),
        Color::Cyan => Value::Single(36),
        Color::White => Value::Single(37),
        Color::Rgb(r, g, b) => Value::Multiple(38, 2, *r, *g, *b),
    }
}

fn get_background_color_value(color: &Color) -> Value {
    match color {
        Color::Black => Value::Single(40),
        Color::Red => Value::Single(41),
        Color::Green => Value::Single(42),
        Color::Yellow => Value::Single(43),
        Color::Blue => Value::Single(44),
        Color::Magenta => Value::Single(45),
        Color::Cyan => Value::Single(46),
        Color::White => Value::Single(47),
        Color::Rgb(r, g, b) => Value::Multiple(48, 2, *r, *g, *b),
    }
}

fn merge_value(value: Value) -> String {
    match value {
        Value::Single(data) => data.to_string(),
        Value::Multiple(a_, b_, r, g, b) => format!("{};{};{};{};{}", a_, b_, r, g, b),
    }
}

#[derive(Debug)]
pub struct Bright {
    text: String,
    color: Option<Color>,
    background: Option<Color>,
    style: Option<Style>,
}

impl Bright {
    pub fn new<T: AsRef<str>>(text: T) -> Bright {
        Bright {
            text: text.as_ref().to_string(),
            color: None,
            background: None,
            style: None,
        }
    }
}

impl Default for Bright {
    fn default() -> Self {
        Bright {
            text: String::default(),
            color: None,
            background: None,
            style: None,
        }
    }
}

impl fmt::Display for Bright {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let style = self.style.as_ref().map(get_style_value);
        let color = self.color.as_ref().map(get_color_value);
        let background = self.background.as_ref().map(get_background_color_value);

        let mut options = Vec::with_capacity(3);
        if let Some(style) = style {
            options.push(style);
        }
        if let Some(color) = color {
            options.push(merge_value(color));
        }
        if let Some(color) = background {
            options.push(merge_value(color));
        }

        write!(f, "\x1B[{}m{}\x1B[0m", options.join(";"), self.text)
    }
}

macro_rules! def_str_style {
    ($name: ident, $style: path) => {
        fn $name(self) -> Bright {
            Bright {
                text: String::from(self),
                style: Some($style),
                ..Bright::default()
            }
        }
    };
}

macro_rules! def_str_color {
    ($name: ident, $color: path) => {
        fn $name(self) -> Bright {
            Bright {
                text: String::from(self),
                color: Some($color),
                ..Bright::default()
            }
        }
    };
}

macro_rules! def_str_background_color {
    ($name: ident, $color: path) => {
        fn $name(self) -> Bright {
            Bright {
                text: String::from(self),
                background: Some($color),
                ..Bright::default()
            }
        }
    };
}

macro_rules! def_style {
    ($name: ident, $style: path) => {
        pub fn $name(self) -> Bright {
            Bright {
                style: Some($style),
                ..self
            }
        }
    };
}

macro_rules! def_color {
    ($name: ident, $color: path) => {
        pub fn $name(self) -> Bright {
            Bright {
                color: Some($color),
                ..self
            }
        }
    };
}

macro_rules! def_background_color {
    ($name: ident, $color: path) => {
        pub fn $name(self) -> Bright {
            Bright {
                background: Some($color),
                ..self
            }
        }
    };
}

pub trait Colorful {
    fn bold(self) -> Bright;
    fn dim(self) -> Bright;
    fn italic(self) -> Bright;
    fn underline(self) -> Bright;
    fn slow_blink(self) -> Bright;
    fn fast_blink(self) -> Bright;
    fn invert(self) -> Bright;
    fn hidden(self) -> Bright;
    fn cross_out(self) -> Bright;

    fn black(self) -> Bright;
    fn red(self) -> Bright;
    fn green(self) -> Bright;
    fn yellow(self) -> Bright;
    fn blue(self) -> Bright;
    fn magenta(self) -> Bright;
    fn cyan(self) -> Bright;
    fn white(self) -> Bright;
    fn rgb(self, r: u8, g: u8, b: u8) -> Bright;

    fn bg_black(self) -> Bright;
    fn bg_red(self) -> Bright;
    fn bg_green(self) -> Bright;
    fn bg_yellow(self) -> Bright;
    fn bg_blue(self) -> Bright;
    fn bg_magenta(self) -> Bright;
    fn bg_cyan(self) -> Bright;
    fn bg_white(self) -> Bright;
    fn bg_rgb(self, r: u8, g: u8, b: u8) -> Bright;
}

impl Bright {
    def_style!(bold, Style::Bold);
    def_style!(dim, Style::Dim);
    def_style!(italic, Style::Italic);
    def_style!(underline, Style::Underline);
    def_style!(slow_blink, Style::SlowBlink);
    def_style!(fast_blink, Style::FastBlink);
    def_style!(invert, Style::Invert);
    def_style!(hidden, Style::Hidden);
    def_style!(cross_out, Style::CrossOut);

    def_color!(black, Color::Black);
    def_color!(red, Color::Red);
    def_color!(green, Color::Green);
    def_color!(yellow, Color::Yellow);
    def_color!(blue, Color::Blue);
    def_color!(magenta, Color::Magenta);
    def_color!(cyan, Color::Cyan);
    def_color!(white, Color::White);
    pub fn rgb(self, r: u8, g: u8, b: u8) -> Bright {
        Bright {
            color: Some(Color::Rgb(r, g, b)),
            ..self
        }
    }

    def_background_color!(bg_black, Color::Black);
    def_background_color!(bg_red, Color::Red);
    def_background_color!(bg_green, Color::Green);
    def_background_color!(bg_yellow, Color::Yellow);
    def_background_color!(bg_blue, Color::Blue);
    def_background_color!(bg_magenta, Color::Magenta);
    def_background_color!(bg_cyan, Color::Cyan);
    def_background_color!(bg_white, Color::White);
    pub fn bg_rgb(self, r: u8, g: u8, b: u8) -> Bright {
        Bright {
            background: Some(Color::Rgb(r, g, b)),
            ..self
        }
    }
}

macro_rules! def_extend {
    () => {
        def_str_style!(bold, Style::Bold);
        def_str_style!(dim, Style::Dim);
        def_str_style!(italic, Style::Italic);
        def_str_style!(underline, Style::Underline);
        def_str_style!(slow_blink, Style::SlowBlink);
        def_str_style!(fast_blink, Style::FastBlink);
        def_str_style!(invert, Style::Invert);
        def_str_style!(hidden, Style::Hidden);
        def_str_style!(cross_out, Style::CrossOut);

        def_str_color!(black, Color::Black);
        def_str_color!(red, Color::Red);
        def_str_color!(green, Color::Green);
        def_str_color!(yellow, Color::Yellow);
        def_str_color!(blue, Color::Blue);
        def_str_color!(magenta, Color::Magenta);
        def_str_color!(cyan, Color::Cyan);
        def_str_color!(white, Color::White);
        fn rgb(self, r: u8, g: u8, b: u8) -> Bright {
            Bright {
                text: String::from(self),
                color: Some(Color::Rgb(r, g, b)),
                ..Bright::default()
            }
        }

        def_str_background_color!(bg_black, Color::Black);
        def_str_background_color!(bg_red, Color::Red);
        def_str_background_color!(bg_green, Color::Green);
        def_str_background_color!(bg_yellow, Color::Yellow);
        def_str_background_color!(bg_blue, Color::Blue);
        def_str_background_color!(bg_magenta, Color::Magenta);
        def_str_background_color!(bg_cyan, Color::Cyan);
        def_str_background_color!(bg_white, Color::White);
        fn bg_rgb(self, r: u8, g: u8, b: u8) -> Bright {
            Bright {
                text: String::from(self),
                background: Some(Color::Rgb(r, g, b)),
                ..Bright::default()
            }
        }
    };
}

impl<'a> Colorful for &'a str {
    def_extend!();
}

impl Colorful for String {
    def_extend!();
}