1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
mod ansi;
pub mod color;
pub mod colorize;
pub mod gradient;
pub mod style;

use ansi::*;
pub use color::*;
pub use colorize::*;
pub use gradient::*;
pub use style::*;

use std::fmt;

#[derive(Debug, Clone)]
pub struct ColoredText {
    foreground_color_style: ColorStyle,
    background_color_style: ColorStyle,
    text: String,
}

impl ColoredText {
    #[inline]
    fn new(text: &str) -> Self {
        Self {
            foreground_color_style: ColorStyle::Colorless,
            background_color_style: ColorStyle::Colorless,
            text: text.to_string(),
        }
    }

    #[inline]
    fn with_foreground_color<C: Into<ColorStyle>>(&self, color: C) -> Self {
        Self {
            foreground_color_style: color.into(),
            background_color_style: self.background_color_style,
            text: self.text.clone(),
        }
    }

    #[inline]
    fn with_background_color<C: Into<ColorStyle>>(&self, color: C) -> Self {
        Self {
            foreground_color_style: self.foreground_color_style,
            background_color_style: color.into(),
            text: self.text.clone(),
        }
    }
}

impl fmt::Display for ColoredText {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match (self.foreground_color_style, self.background_color_style) {
            (ColorStyle::Single(fg), ColorStyle::Single(bg)) => {
                write!(f, "\x1B[{};{}m{}\x1B[0",
                    fg.ansi_color_code(TargetGround::Foreground),
                    bg.ansi_color_code(TargetGround::Background),
                    self.text)
            }
            (ColorStyle::Single(fg), ColorStyle::Gradient(bg)) => {
                write!(f, "\x1B[{}m{}", 
                    fg.ansi_color_code(TargetGround::Foreground),
                    bg.build(&self.text, TargetGround::Background))
            }
            (ColorStyle::Single(fg), ColorStyle::Colorless) => {
                write!(f, "\x1B[{}m{}\x1B[0", 
                    fg.ansi_color_code(TargetGround::Foreground),
                    self.text)
            }
            (ColorStyle::Gradient(fg), ColorStyle::Single(bg)) => {
                write!(f, "\x1B[{}m{}",
                    bg.ansi_color_code(TargetGround::Background),
                    fg.build(&self.text, TargetGround::Foreground))
            }
            (ColorStyle::Gradient(fg), ColorStyle::Gradient(bg)) => {
                write!(f, "{}", build_all_gradient_text(&self.text, fg, bg))
            }
            (ColorStyle::Gradient(fg), ColorStyle::Colorless) => {
                write!(f, "{}", fg.build(&self.text, TargetGround::Foreground))
            }
            (ColorStyle::Colorless, ColorStyle::Single(bg)) => {
                write!(f, "\x1B[{}m{}\x1B[0",
                    bg.ansi_color_code(TargetGround::Background),
                    self.text)
            }
            (ColorStyle::Colorless, ColorStyle::Gradient(bg)) => {
                write!(f, "{}", bg.build(&self.text, TargetGround::Background))
            }
            (ColorStyle::Colorless, ColorStyle::Colorless) => {
                write!(f, "{}", self.text)
            }
        }
    }
}

pub trait Apply : Into<ColorStyle> {
    fn to<T: Colorize + ?Sized>(self, t: &T) -> ColoredText {
        t.fg::<Self>(self)
    }

    fn under<T: Colorize  + ?Sized>(self, t: &T) -> ColoredText {
        t.bg::<Self>(self)
    }
}

impl Apply for RGB { }
impl Apply for HSL { }
impl Apply for Color { }
impl Apply for Gradient { }