coloriz 0.2.0

A simple library for colorful temrinal
Documentation
//! A library for Rust that provides utilities
//! to colorizing terminal outputs and styling strings.
//!
//! Coloriz helps to make your terminal colorful.  
//!
//! # Quick Example
//!
//! ```rs
//! use coloriz::*;
//!
//! fn main() {
//!     let text = "Lorem ipsum";
//!     println!("{}", text.fg(Color::Cyan));
//!     println!("{}", text.bg(Color::BrightBlack).fg(Color::Red));
//!     println!("{}", text.fg(HSL::new(0.03, 0.7, 0.666)));
//!     println!("{}", text.fg((167, 232, 78))); // the same as text.fg(RGB::new(167, 232, 78))
//!     println!("{}", text.fg_gradient(RGB::from_hex(0xFF6712), RGB::from_hex(0x1087FF)));
//!     println!("{}", Color::BrightMagenta.to(text));
//!     println!("{}", Color::BrightMagenta.under(text));
//! }
//! ```

mod ansi;
mod color;
mod colorize;
mod gradient;
mod style;

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

use std::fmt;

/// A string that may be colorized
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StyledText {
    foreground_color_style: ColorStyle,
    background_color_style: ColorStyle,
    style: Style,
    pub text: String,
}

impl StyledText {
    /// Creates a [ColoredText] from `text` without any color styles
    #[inline]
    pub fn new(text: &str) -> Self {
        Self {
            foreground_color_style: ColorStyle::Colorless,
            background_color_style: ColorStyle::Colorless,
            style: Style::new(),
            text: text.to_string(),
        }
    }

    /// Returns the foreground color style of `self`
    #[inline]
    pub fn foreground(&self) -> ColorStyle {
        self.foreground_color_style
    }

    /// Returns the background color style of `self`
    #[inline]
    pub fn background(&self) -> ColorStyle {
        self.background_color_style
    }

    pub fn styles(&self) -> Vec<StyleMode> {
        self.style.styles()
    }

    #[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,
            style: self.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(),
            style: self.style,
            text: self.text.clone(),
        }
    }

    fn with_style_mode(&self, mode: StyleMode) -> Self {
        Self {
            foreground_color_style: self.foreground_color_style,
            background_color_style: self.background_color_style,
            style: self.style.add_style_mode(mode),
            text: self.text.clone(),
        }
    }
}

impl From<String> for StyledText {
    fn from(s: String) -> Self {
        StyledText::new(&s)
    }
}

impl From<&str> for StyledText {
    fn from(s: &str) -> Self {
        StyledText::new(s)
    }
}

impl fmt::Display for StyledText {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "\x1B[{}m", self.style.ansi_code())?;
        match (self.foreground_color_style, self.background_color_style) {
            (ColorStyle::Single(fg), ColorStyle::Single(bg)) => {
                write!(
                    f,
                    "\x1B[{};{}m{}\x1B[0m",
                    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[0m",
                    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[0m",
                    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, "{}\x1B[0m", self.text)
            }
        }
    }
}

/// A Color that can apply to text
pub trait ColorApply: Into<ColorStyle> {
    /// Applies `self` to the foreground color of `c`
    ///
    /// # Example
    /// ```
    /// let red = Color::Red.to("lorem ipsum");
    /// assert_eq!(red, "lorem ipsum".fg(Color::Red));
    /// ```
    fn to<C>(self, c: C) -> StyledText
    where
        C: Colorize + ?Sized,
    {
        c.fg::<Self>(self)
    }

    /// Applies `self` to the background color of `c`
    ///    
    /// # Example
    /// ```
    /// let green = Color::Green.under("lorem ipsum");
    /// assert_eq!(green, "lorem ipsum".bg(Color::Green));
    /// ```
    fn under<C>(self, c: C) -> StyledText
    where
        C: Colorize + ?Sized,
    {
        c.bg::<Self>(self)
    }
}

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