#![no_std]
extern crate alloc;
use core::fmt::Display;
use alloc::{format, string::String};
pub struct StyleBuilder {
bold: bool,
dim: bool,
italic: bool,
underline: bool,
blink: bool,
inverse: bool,
hidden: bool,
strikethrough: bool,
overline: bool,
color: Option<Color>,
bg_color: Option<BGColor>,
}
impl StyleBuilder {
#[must_use]
pub fn new() -> Self {
Self {
bold: false,
dim: false,
italic: false,
underline: false,
blink: false,
inverse: false,
hidden: false,
strikethrough: false,
overline: false,
color: None,
bg_color: None,
}
}
#[must_use]
pub fn bold(mut self) -> Self {
self.bold = true;
self
}
#[must_use]
pub fn dim(mut self) -> Self {
self.dim = true;
self
}
#[must_use]
pub fn italic(mut self) -> Self {
self.italic = true;
self
}
#[must_use]
pub fn underline(mut self) -> Self {
self.underline = true;
self
}
#[must_use]
pub fn blink(mut self) -> Self {
self.blink = true;
self
}
#[must_use]
pub fn inverse(mut self) -> Self {
self.inverse = true;
self
}
#[must_use]
pub fn hidden(mut self) -> Self {
self.hidden = true;
self
}
#[must_use]
pub fn strikethrough(mut self) -> Self {
self.strikethrough = true;
self
}
#[must_use]
pub fn overline(mut self) -> Self {
self.overline = true;
self
}
#[must_use]
pub fn black(mut self) -> Self {
self.color = Some(Color::Black);
self
}
#[must_use]
pub fn red(mut self) -> Self {
self.color = Some(Color::Red);
self
}
#[must_use]
pub fn green(mut self) -> Self {
self.color = Some(Color::Green);
self
}
#[must_use]
pub fn yellow(mut self) -> Self {
self.color = Some(Color::Yellow);
self
}
#[must_use]
pub fn blue(mut self) -> Self {
self.color = Some(Color::Blue);
self
}
#[must_use]
pub fn magenta(mut self) -> Self {
self.color = Some(Color::Magenta);
self
}
#[must_use]
pub fn cyan(mut self) -> Self {
self.color = Some(Color::Cyan);
self
}
#[must_use]
pub fn white(mut self) -> Self {
self.color = Some(Color::White);
self
}
#[must_use]
pub fn black_bright(mut self) -> Self {
self.color = Some(Color::BlackBright);
self
}
#[must_use]
pub fn red_bright(mut self) -> Self {
self.color = Some(Color::RedBright);
self
}
#[must_use]
pub fn green_bright(mut self) -> Self {
self.color = Some(Color::GreenBright);
self
}
#[must_use]
pub fn yellow_bright(mut self) -> Self {
self.color = Some(Color::YellowBright);
self
}
#[must_use]
pub fn blue_bright(mut self) -> Self {
self.color = Some(Color::BlueBright);
self
}
#[must_use]
pub fn magenta_bright(mut self) -> Self {
self.color = Some(Color::MagentaBright);
self
}
#[must_use]
pub fn cyan_bright(mut self) -> Self {
self.color = Some(Color::CyanBright);
self
}
#[must_use]
pub fn white_bright(mut self) -> Self {
self.color = Some(Color::WhiteBright);
self
}
#[must_use]
pub fn bg_black(mut self) -> Self {
self.bg_color = Some(BGColor::Black);
self
}
#[must_use]
pub fn bg_red(mut self) -> Self {
self.bg_color = Some(BGColor::Red);
self
}
#[must_use]
pub fn bg_green(mut self) -> Self {
self.bg_color = Some(BGColor::Green);
self
}
#[must_use]
pub fn bg_yellow(mut self) -> Self {
self.bg_color = Some(BGColor::Yellow);
self
}
#[must_use]
pub fn bg_blue(mut self) -> Self {
self.bg_color = Some(BGColor::Blue);
self
}
#[must_use]
pub fn bg_magenta(mut self) -> Self {
self.bg_color = Some(BGColor::Magenta);
self
}
#[must_use]
pub fn bg_cyan(mut self) -> Self {
self.bg_color = Some(BGColor::Cyan);
self
}
#[must_use]
pub fn bg_white(mut self) -> Self {
self.bg_color = Some(BGColor::White);
self
}
#[must_use]
pub fn bg_black_bright(mut self) -> Self {
self.bg_color = Some(BGColor::BlackBright);
self
}
#[must_use]
pub fn bg_red_bright(mut self) -> Self {
self.bg_color = Some(BGColor::RedBright);
self
}
#[must_use]
pub fn bg_green_bright(mut self) -> Self {
self.bg_color = Some(BGColor::GreenBright);
self
}
#[must_use]
pub fn bg_yellow_bright(mut self) -> Self {
self.bg_color = Some(BGColor::YellowBright);
self
}
#[must_use]
pub fn bg_blue_bright(mut self) -> Self {
self.bg_color = Some(BGColor::BlueBright);
self
}
#[must_use]
pub fn bg_magenta_bright(mut self) -> Self {
self.bg_color = Some(BGColor::MagentaBright);
self
}
#[must_use]
pub fn bg_cyan_bright(mut self) -> Self {
self.bg_color = Some(BGColor::CyanBright);
self
}
#[must_use]
pub fn bg_white_bright(mut self) -> Self {
self.bg_color = Some(BGColor::WhiteBright);
self
}
#[must_use]
pub fn build(self) -> Style {
let StyleBuilder {
bold,
dim,
italic,
underline,
blink,
inverse,
hidden,
strikethrough,
overline,
color,
bg_color,
} = self;
Style {
bold,
dim,
italic,
underline,
blink,
inverse,
hidden,
strikethrough,
overline,
color,
bg_color,
}
}
}
impl Default for StyleBuilder {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub struct Style {
bold: bool,
dim: bool,
italic: bool,
underline: bool,
blink: bool,
inverse: bool,
hidden: bool,
strikethrough: bool,
overline: bool,
color: Option<Color>,
bg_color: Option<BGColor>,
}
impl Style {
#[must_use]
pub fn new() -> Self {
Self {
bold: false,
dim: false,
italic: false,
underline: false,
blink: false,
inverse: false,
hidden: false,
strikethrough: false,
overline: false,
color: None,
bg_color: None,
}
}
#[must_use]
pub fn builder() -> StyleBuilder {
StyleBuilder::new()
}
#[must_use]
pub fn bold(&self) -> bool {
self.bold
}
#[must_use]
pub fn dim(&self) -> bool {
self.dim
}
#[must_use]
pub fn italic(&self) -> bool {
self.italic
}
#[must_use]
pub fn underline(&self) -> bool {
self.underline
}
#[must_use]
pub fn blink(&self) -> bool {
self.blink
}
#[must_use]
pub fn inverse(&self) -> bool {
self.inverse
}
#[must_use]
pub fn hidden(&self) -> bool {
self.hidden
}
#[must_use]
pub fn strikethrough(&self) -> bool {
self.strikethrough
}
#[must_use]
pub fn overline(&self) -> bool {
self.overline
}
#[must_use]
pub fn color(&self) -> Color {
match self.color {
Some(color) => color,
None => Color::Any,
}
}
#[must_use]
pub fn bg_color(&self) -> BGColor {
match self.bg_color {
Some(color) => color,
None => BGColor::Any,
}
}
#[must_use]
pub fn rgb_to_ansi256(red: u8, green: u8, blue: u8) -> u8 {
if red == green && green == blue {
if red < 8 {
return 16;
}
if red > 248 {
return 231;
}
return ((((red as f32 - 8.) / 247.) * 24.) + 232.) as u8;
}
(16. + (36. * (red as f32 / 255. * 5.))
+ (6. * (green as f32 / 255. * 5.))
+ (blue as f32 / 255. * 5.)) as u8
}
#[must_use]
pub fn stylize(&self, text: &str) -> String {
format!("{self}{text}{}", Self::reset())
}
fn is_default(&self) -> bool {
*self == Self::default()
}
fn reset() -> &'static str {
"\x1B[0m"
}
}
impl Display for Style {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if self.is_default() {
return Ok(());
}
write!(f, "\x1B[")?;
let mut written = false;
{
let mut write_char = |c| {
if written {
write!(f, ";")?;
}
written = true;
write!(f, "{}", c)?;
Ok(())
};
if self.bold {
write_char('1')?;
}
if self.dim {
write_char('2')?;
}
if self.italic {
write_char('3')?;
}
if self.underline {
write_char('4')?;
}
if self.blink {
write_char('5')?;
}
if self.inverse {
write_char('7')?;
}
if self.hidden {
write_char('8')?;
}
if self.strikethrough {
write_char('9')?;
}
if self.overline {
write!(f, "53")?;
}
}
if let Some(color) = self.bg_color {
if written {
write!(f, ";{color}")?;
} else {
write!(f, "{color}")?;
written = true;
}
}
if let Some(color) = self.color {
if written {
write!(f, ";{color}")?;
} else {
write!(f, "{color}")?;
}
}
write!(f, "m")
}
}
impl Default for Style {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub enum Color {
Any,
Black,
Red,
Green,
Yellow,
Blue,
Magenta,
Cyan,
White,
BlackBright,
RedBright,
GreenBright,
YellowBright,
BlueBright,
MagentaBright,
CyanBright,
WhiteBright,
Ansi256(u8),
RGB(u8, u8, u8),
}
impl Color {
#[must_use]
pub fn close(&self) -> &'static str {
"\x1B[39m"
}
#[must_use]
pub fn open(&self) -> String {
format!("\x1B[{self}m")
}
#[must_use]
pub fn paint(&self, text: &str) -> String {
format!("{}{text}{}", self.open(), self.close())
}
}
impl Display for Color {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Color::Any => write!(f, ""),
Color::Black => write!(f, "30"),
Color::Red => write!(f, "31"),
Color::Green => write!(f, "32"),
Color::Yellow => write!(f, "33"),
Color::Blue => write!(f, "34"),
Color::Magenta => write!(f, "35"),
Color::Cyan => write!(f, "36"),
Color::White => write!(f, "37"),
Color::BlackBright => write!(f, "90"),
Color::RedBright => write!(f, "91"),
Color::GreenBright => write!(f, "92"),
Color::YellowBright => write!(f, "93"),
Color::BlueBright => write!(f, "94"),
Color::MagentaBright => write!(f, "95"),
Color::CyanBright => write!(f, "96"),
Color::WhiteBright => write!(f, "97"),
Color::Ansi256(num) => write!(f, "38;5;{}", &num),
Color::RGB(r, g, b) => write!(f, "38;2;{};{};{}", &r, &g, &b),
}
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub enum BGColor {
Any,
Black,
Red,
Green,
Yellow,
Blue,
Magenta,
Cyan,
White,
BlackBright,
RedBright,
GreenBright,
YellowBright,
BlueBright,
MagentaBright,
CyanBright,
WhiteBright,
Ansi256(u8),
RGB(u8, u8, u8),
}
impl BGColor {
#[must_use]
pub fn close(&self) -> &'static str {
"\x1B[49m"
}
#[must_use]
pub fn open(&self) -> String {
format!("\x1B[{self}m")
}
#[must_use]
pub fn paint(&self, text: &str) -> String {
format!("{}{text}{}", self.open(), self.close())
}
}
impl Display for BGColor {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
BGColor::Any => write!(f, ""),
BGColor::Black => write!(f, "40"),
BGColor::Red => write!(f, "41"),
BGColor::Green => write!(f, "42"),
BGColor::Yellow => write!(f, "43"),
BGColor::Blue => write!(f, "44"),
BGColor::Magenta => write!(f, "45"),
BGColor::Cyan => write!(f, "46"),
BGColor::White => write!(f, "47"),
BGColor::BlackBright => write!(f, "100"),
BGColor::RedBright => write!(f, "101"),
BGColor::GreenBright => write!(f, "102"),
BGColor::YellowBright => write!(f, "103"),
BGColor::BlueBright => write!(f, "104"),
BGColor::MagentaBright => write!(f, "105"),
BGColor::CyanBright => write!(f, "106"),
BGColor::WhiteBright => write!(f, "107"),
BGColor::Ansi256(num) => write!(f, "48;5;{}", &num),
BGColor::RGB(r, g, b) => write!(f, "48;2;{};{};{}", &r, &g, &b),
}
}
}