use std::fmt;
use super::{Color, Style};
use crate::prompt::are_colors_enabled;
const STYLE_BOLD: u8 = 1 << 0;
const STYLE_DIM: u8 = 1 << 1;
const STYLE_ITALIC: u8 = 1 << 2;
const STYLE_UNDERLINE: u8 = 1 << 3;
const STYLE_BLINK: u8 = 1 << 4;
const STYLE_REVERSE: u8 = 1 << 5;
const STYLE_HIDDEN: u8 = 1 << 6;
const STYLE_STRIKETHROUGH: u8 = 1 << 7;
#[derive(Debug)]
pub struct StyledText<T> {
pub text: T,
pub fg: Option<Color>,
pub bg: Option<Color>,
pub style_mask: u8,
}
impl<T> StyledText<T> {
#[must_use]
pub const fn new(text: T) -> Self {
Self {
text,
fg: None,
bg: None,
style_mask: 0,
}
}
#[must_use]
pub const fn color(mut self, color: Color) -> Self {
self.fg = Some(color);
self
}
#[must_use]
pub const fn bg(mut self, color: Color) -> Self {
self.bg = Some(color);
self
}
#[must_use]
pub const fn fixed(mut self, n: u8) -> Self {
self.fg = Some(Color::Fixed(n));
self
}
#[must_use]
pub const fn rgb(mut self, r: u8, g: u8, b: u8) -> Self {
self.fg = Some(Color::Rgb(r, g, b));
self
}
#[must_use]
pub const fn bg_fixed(mut self, n: u8) -> Self {
self.bg = Some(Color::Fixed(n));
self
}
#[must_use]
pub const fn bg_rgb(mut self, r: u8, g: u8, b: u8) -> Self {
self.bg = Some(Color::Rgb(r, g, b));
self
}
#[must_use]
pub const fn reset(mut self) -> Self {
self.fg = Some(Color::Reset);
self.bg = Some(Color::Reset);
self.style_mask = 0;
self
}
#[must_use]
pub const fn black(mut self) -> Self {
self.fg = Some(Color::Black);
self
}
#[must_use]
pub const fn bright_black(mut self) -> Self {
self.fg = Some(Color::BrightBlack);
self
}
#[must_use]
pub const fn bright_red(mut self) -> Self {
self.fg = Some(Color::BrightRed);
self
}
#[must_use]
pub const fn bright_green(mut self) -> Self {
self.fg = Some(Color::BrightGreen);
self
}
#[must_use]
pub const fn bright_yellow(mut self) -> Self {
self.fg = Some(Color::BrightYellow);
self
}
#[must_use]
pub const fn bright_blue(mut self) -> Self {
self.fg = Some(Color::BrightBlue);
self
}
#[must_use]
pub const fn bright_magenta(mut self) -> Self {
self.fg = Some(Color::BrightMagenta);
self
}
#[must_use]
pub const fn bright_cyan(mut self) -> Self {
self.fg = Some(Color::BrightCyan);
self
}
#[must_use]
pub const fn bright_white(mut self) -> Self {
self.fg = Some(Color::BrightWhite);
self
}
#[must_use]
pub const fn red(mut self) -> Self {
self.fg = Some(Color::Red);
self
}
#[must_use]
pub const fn green(mut self) -> Self {
self.fg = Some(Color::Green);
self
}
#[must_use]
pub const fn yellow(mut self) -> Self {
self.fg = Some(Color::Yellow);
self
}
#[must_use]
pub const fn blue(mut self) -> Self {
self.fg = Some(Color::Blue);
self
}
#[must_use]
pub const fn magenta(mut self) -> Self {
self.fg = Some(Color::Magenta);
self
}
#[must_use]
pub const fn cyan(mut self) -> Self {
self.fg = Some(Color::Cyan);
self
}
#[must_use]
pub const fn white(mut self) -> Self {
self.fg = Some(Color::White);
self
}
#[must_use]
pub const fn bg_black(mut self) -> Self {
self.bg = Some(Color::Black);
self
}
#[must_use]
pub const fn bg_bright_black(mut self) -> Self {
self.bg = Some(Color::BrightBlack);
self
}
#[must_use]
pub const fn bg_bright_red(mut self) -> Self {
self.bg = Some(Color::BrightRed);
self
}
#[must_use]
pub const fn bg_bright_green(mut self) -> Self {
self.bg = Some(Color::BrightGreen);
self
}
#[must_use]
pub const fn bg_bright_yellow(mut self) -> Self {
self.bg = Some(Color::BrightYellow);
self
}
#[must_use]
pub const fn bg_bright_blue(mut self) -> Self {
self.bg = Some(Color::BrightBlue);
self
}
#[must_use]
pub const fn bg_bright_magenta(mut self) -> Self {
self.bg = Some(Color::BrightMagenta);
self
}
#[must_use]
pub const fn bg_bright_cyan(mut self) -> Self {
self.bg = Some(Color::BrightCyan);
self
}
#[must_use]
pub const fn bg_bright_white(mut self) -> Self {
self.bg = Some(Color::BrightWhite);
self
}
#[must_use]
pub const fn bg_red(mut self) -> Self {
self.bg = Some(Color::Red);
self
}
#[must_use]
pub const fn bg_green(mut self) -> Self {
self.bg = Some(Color::Green);
self
}
#[must_use]
pub const fn bg_yellow(mut self) -> Self {
self.bg = Some(Color::Yellow);
self
}
#[must_use]
pub const fn bg_blue(mut self) -> Self {
self.bg = Some(Color::Blue);
self
}
#[must_use]
pub const fn bg_magenta(mut self) -> Self {
self.bg = Some(Color::Magenta);
self
}
#[must_use]
pub const fn bg_cyan(mut self) -> Self {
self.bg = Some(Color::Cyan);
self
}
#[must_use]
pub const fn bg_white(mut self) -> Self {
self.bg = Some(Color::White);
self
}
#[must_use]
pub const fn underline(mut self) -> Self {
self.style_mask |= STYLE_UNDERLINE;
self
}
#[must_use]
pub const fn dim(mut self) -> Self {
self.style_mask |= STYLE_DIM;
self
}
#[must_use]
pub const fn italic(mut self) -> Self {
self.style_mask |= STYLE_ITALIC;
self
}
#[must_use]
pub const fn blink(mut self) -> Self {
self.style_mask |= STYLE_BLINK;
self
}
#[must_use]
pub const fn reverse(mut self) -> Self {
self.style_mask |= STYLE_REVERSE;
self
}
#[must_use]
pub const fn hidden(mut self) -> Self {
self.style_mask |= STYLE_HIDDEN;
self
}
#[must_use]
pub const fn strikethrough(mut self) -> Self {
self.style_mask |= STYLE_STRIKETHROUGH;
self
}
#[must_use]
pub const fn bold(mut self) -> Self {
self.style_mask |= STYLE_BOLD;
self
}
}
impl<T: fmt::Display> fmt::Display for StyledText<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if !are_colors_enabled() {
return write!(f, "{}", self.text);
}
if self.style_mask & STYLE_BOLD != 0 {
write!(f, "{}", Style::Bold.to_str())?;
}
if self.style_mask & STYLE_DIM != 0 {
write!(f, "{}", Style::Dim.to_str())?;
}
if self.style_mask & STYLE_ITALIC != 0 {
write!(f, "{}", Style::Italic.to_str())?;
}
if self.style_mask & STYLE_UNDERLINE != 0 {
write!(f, "{}", Style::Underline.to_str())?;
}
if self.style_mask & STYLE_BLINK != 0 {
write!(f, "{}", Style::Blink.to_str())?;
}
if self.style_mask & STYLE_REVERSE != 0 {
write!(f, "{}", Style::Reverse.to_str())?;
}
if self.style_mask & STYLE_HIDDEN != 0 {
write!(f, "{}", Style::Hidden.to_str())?;
}
if self.style_mask & STYLE_STRIKETHROUGH != 0 {
write!(f, "{}", Style::Strikethrough.to_str())?;
}
if let Some(fg) = &self.fg {
fg.write_fg(f)?;
}
if let Some(bg) = &self.bg {
bg.write_bg(f)?;
}
write!(f, "{}", self.text)?;
write!(f, "{}", Style::Reset.to_str())
}
}