ansiconst 0.2.1

Library for declaring nestable ANSI styles in const context
Documentation
use crate::{Ansi, Color::*, Coloree::{self, *}, Effect::{self, *}, Toggle, ToggleColor};
use std::fmt;

enum State { Clean, Dirty }

impl State {
    #[inline]
    fn write_str<W: fmt::Write>(&self, w: &mut W, s: &str) -> Result<Self, fmt::Error> {
        self._write_separator(w)?;
        w.write_str(s)?;
        Ok(Self::Dirty)
    }
    #[cfg(feature="color256")]
    #[inline]
    fn write_fmt<W: fmt::Write>(&self, w: &mut W, fmt: fmt::Arguments<'_>) -> Result<Self, fmt::Error> {
        self._write_separator(w)?;
        w.write_fmt(fmt)?;
        Ok(Self::Dirty)
    }

    #[inline]
    fn _write_separator<W: fmt::Write>(&self, w: &mut W) -> fmt::Result {
        match self {
            Self::Clean => w.write_str("\x1B["),
            Self::Dirty => w.write_str(";"),
        }
    }
    #[inline]
    fn write_terminator<W: fmt::Write>(&self, w: &mut W) -> Result<Self, fmt::Error> {
        match self {
            Self::Clean => (),
            Self::Dirty => w.write_str("m")?,
        }
        Ok(Self::Clean)
    }
}

pub(crate) struct Formatter<'a,'f> where 'f: 'a {
    f: &'a mut fmt::Formatter<'f>,
    state: State,
}

impl<'a,'f> Formatter<'a,'f> where 'f: 'a {
    #[inline]
    pub(crate) fn fmt_ansi(f: &'a mut fmt::Formatter<'f>, ansi: Ansi) -> fmt::Result {
        if !ansi.is_empty() {
            let mut w = Self::new(f);
            ansi.write(&mut w)?;
            w.write_terminator()?;
        }
        Ok(())
    }
    #[inline]
    fn new(f: &'a mut fmt::Formatter<'f>) -> Self {
        Self { f, state: State::Clean }
    }
    #[inline]
    fn write_str(&mut self, s: &str) -> fmt::Result {
        self.state = self.state.write_str(self.f, s)?;
        Ok(())
    }
    #[cfg(feature="color256")]
    #[inline]
    fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> fmt::Result {
        self.state = self.state.write_fmt(self.f, fmt)?;
        Ok(())
    }
    #[inline]
    fn write_terminator(&mut self) -> fmt::Result {
        self.state = self.state.write_terminator(self.f)?;
        Ok(())
    }

    pub(crate) fn write_reset(&mut self) -> fmt::Result { self.write_str("0") }

    pub(crate) fn write_color(&mut self, color: Coloree, value: ToggleColor) -> fmt::Result {
        match (color, value) {
            (Text,       ToggleColor::Reset) => { self.write_str("39") },
            (Background, ToggleColor::Reset) => { self.write_str("49") },
            (Text,       ToggleColor::Set(c)) => match c {
                #[cfg(feature="color256")]
                ColorNum(n)  => { self.write_fmt(format_args!("38;5;{}", n)) },
                #[cfg(feature="rgb")]
                Rgb(r,g,b)   => { self.write_fmt(format_args!("38;2;{};{};{}", r, g, b)) },
                Black        => { self.write_str( "30") },
                Red          => { self.write_str( "31") },
                Green        => { self.write_str( "32") },
                Yellow       => { self.write_str( "33") },
                Blue         => { self.write_str( "34") },
                Purple       => { self.write_str( "35") },
                Cyan         => { self.write_str( "36") },
                White        => { self.write_str( "37") },
                BrightBlack  => { self.write_str( "90") },
                BrightRed    => { self.write_str( "91") },
                BrightGreen  => { self.write_str( "92") },
                BrightYellow => { self.write_str( "93") },
                BrightBlue   => { self.write_str( "94") },
                BrightPurple => { self.write_str( "95") },
                BrightCyan   => { self.write_str( "96") },
                BrightWhite  => { self.write_str( "97") },
            },
            (Background, ToggleColor::Set(c)) => match c {
                #[cfg(feature="color256")]
                ColorNum(n)  => { self.write_fmt(format_args!("48;5;{}", n)) },
                #[cfg(feature="rgb")]
                Rgb(r,g,b)   => { self.write_fmt(format_args!("48;2;{};{};{}", r, g, b)) },
                Black        => { self.write_str( "40") },
                Red          => { self.write_str( "41") },
                Green        => { self.write_str( "42") },
                Yellow       => { self.write_str( "43") },
                Blue         => { self.write_str( "44") },
                Purple       => { self.write_str( "45") },
                Cyan         => { self.write_str( "46") },
                White        => { self.write_str( "47") },
                BrightBlack  => { self.write_str("100") },
                BrightRed    => { self.write_str("101") },
                BrightGreen  => { self.write_str("102") },
                BrightYellow => { self.write_str("103") },
                BrightBlue   => { self.write_str("104") },
                BrightPurple => { self.write_str("105") },
                BrightCyan   => { self.write_str("106") },
                BrightWhite  => { self.write_str("107") },
            },
        }
    }

    pub(crate) fn write_effect(&mut self, effect: Effect, value: Toggle) -> fmt::Result {
        match (effect, value) {
            (Bold,       Toggle::Reset) => { self.write_str("22") },
            (Faint,      Toggle::Reset) => { self.write_str("22") },
            (Italic,     Toggle::Reset) => { self.write_str("23") },
            (Underline,  Toggle::Reset) => { self.write_str("24") },
            (Blink,      Toggle::Reset) => { self.write_str("25") },
            (Reverse,    Toggle::Reset) => { self.write_str("27") },
            (Hidden,     Toggle::Reset) => { self.write_str("28") },
            (Strike,     Toggle::Reset) => { self.write_str("29") },
            (Bold,         Toggle::Set) => { self.write_str( "1") },
            (Faint,        Toggle::Set) => { self.write_str( "2") },
            (Italic,       Toggle::Set) => { self.write_str( "3") },
            (Underline,    Toggle::Set) => { self.write_str( "4") },
            (Blink,        Toggle::Set) => { self.write_str( "5") },
            (Reverse,      Toggle::Set) => { self.write_str( "7") },
            (Hidden,       Toggle::Set) => { self.write_str( "8") },
            (Strike,       Toggle::Set) => { self.write_str( "9") },
        }
    }
}