feat(cli): ✨ /stylize: change TrueColor to Rgb and improve docs
This commit is contained in:
parent
baef445169
commit
917b763b45
@ -47,5 +47,17 @@ fn main() -> Result<()> {
|
||||
println!("pre {} post", "[.dim()]".dim());
|
||||
println!("pre {} post", "[.blue().dim()]".blue().dim());
|
||||
|
||||
println!("pre {} post", "[.rgb(\"#af7cbf\")]".rgb("#af7cbf"));
|
||||
println!(
|
||||
"pre {} post",
|
||||
"[.rgb(\"#af7cbf\").bold()]".rgb("#af7cbf").bold()
|
||||
);
|
||||
|
||||
println!("pre {} post", "[.on_rgb(\"#af7cbf\")".on_rgb("#af7cbf"));
|
||||
println!(
|
||||
"pre {} post",
|
||||
"[.on_rgb(\"#af7cbf\").bold()]".on_rgb("#af7cbf").bold()
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use {bitflags::bitflags, eyre::Context, std::borrow::Cow};
|
||||
|
||||
/// The 8 standard colors.
|
||||
/// Standard terminal colors + RGB
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum Color {
|
||||
Black,
|
||||
@ -19,12 +19,13 @@ pub enum Color {
|
||||
BrightMagenta,
|
||||
BrightCyan,
|
||||
BrightWhite,
|
||||
TrueColor { r: u8, g: u8, b: u8 },
|
||||
Rgb { r: u8, g: u8, b: u8 },
|
||||
}
|
||||
|
||||
impl Color {
|
||||
pub fn to_fg_str(&self) -> Cow<'static, str> {
|
||||
match *self {
|
||||
/// converts a color to a string that can be used in an ANSI foreground escape sequence
|
||||
pub fn to_fg_str(self) -> Cow<'static, str> {
|
||||
match self {
|
||||
Color::Black => "30".into(),
|
||||
Color::Red => "31".into(),
|
||||
Color::Green => "32".into(),
|
||||
@ -41,12 +42,13 @@ impl Color {
|
||||
Color::BrightMagenta => "95".into(),
|
||||
Color::BrightCyan => "96".into(),
|
||||
Color::BrightWhite => "97".into(),
|
||||
Color::TrueColor { r, g, b } => format!("38;2;{};{};{}", r, g, b).into(),
|
||||
Color::Rgb { r, g, b } => format!("38;2;{};{};{}", r, g, b).into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_bg_str(&self) -> Cow<'static, str> {
|
||||
match *self {
|
||||
/// converts a color to a string that can be used in an ANSI background escape sequence
|
||||
pub fn to_bg_str(self) -> Cow<'static, str> {
|
||||
match self {
|
||||
Color::Black => "40".into(),
|
||||
Color::Red => "41".into(),
|
||||
Color::Green => "42".into(),
|
||||
@ -63,10 +65,11 @@ impl Color {
|
||||
Color::BrightMagenta => "105".into(),
|
||||
Color::BrightCyan => "106".into(),
|
||||
Color::BrightWhite => "107".into(),
|
||||
Color::TrueColor { r, g, b } => format!("48;2;{};{};{}", r, g, b).into(),
|
||||
Color::Rgb { r, g, b } => format!("48;2;{};{};{}", r, g, b).into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// creates a `Color` from a string
|
||||
pub fn from_str(s: &str) -> eyre::Result<Color> {
|
||||
let color = match s {
|
||||
"" => None,
|
||||
@ -91,7 +94,7 @@ impl Color {
|
||||
let r = u8::from_str_radix(&s[0..2], 16).context("Error parsing RGB color")?;
|
||||
let g = u8::from_str_radix(&s[2..4], 16).context("Error parsing RGB color")?;
|
||||
let b = u8::from_str_radix(&s[4..6], 16).context("Error parsing RGB color")?;
|
||||
Some(Color::TrueColor { r, g, b })
|
||||
Some(Color::Rgb { r, g, b })
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
@ -102,6 +105,7 @@ impl Color {
|
||||
|
||||
bitflags! {
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
/// style attributes bitflags
|
||||
pub struct StyleAttributes: u8 {
|
||||
const BOLD = 0b00000001;
|
||||
const DIM = 0b00000010;
|
||||
@ -115,6 +119,7 @@ bitflags! {
|
||||
}
|
||||
|
||||
impl StyleAttributes {
|
||||
/// converts the style attributes to ANSI codes
|
||||
pub fn to_ansi_codes(&self) -> Vec<&'static str> {
|
||||
let mut v = Vec::new();
|
||||
if self.contains(StyleAttributes::BOLD) {
|
||||
|
||||
@ -9,6 +9,7 @@ pub mod instructions {
|
||||
bitflags::parser::{from_str, ParseError},
|
||||
};
|
||||
|
||||
/// struct that holds the style information
|
||||
pub struct StyledString {
|
||||
pub fg: Option<Color>,
|
||||
pub bg: Option<Color>,
|
||||
@ -25,7 +26,7 @@ pub mod instructions {
|
||||
}
|
||||
}
|
||||
|
||||
/// parses the instruction into a StyledString
|
||||
/// parses the instruction into a `StyledString`
|
||||
pub fn parse(instructions: &str) -> Result<StyledString> {
|
||||
let mut styled_string = StyledString::default();
|
||||
|
||||
@ -61,11 +62,10 @@ pub mod instructions {
|
||||
Ok(styled_string)
|
||||
}
|
||||
|
||||
/// Parses the color instruction into a tuple of fg and bg colors.
|
||||
/// parses the color part of an instruction into a tuple of fg and bg colors.
|
||||
pub fn parse_color_instruction(instruction: &str) -> Result<(Option<Color>, Option<Color>)> {
|
||||
if instruction.starts_with("on ") {
|
||||
// If instruction starts with "on ", bg color is provided
|
||||
return Ok((None, Some(Color::from_str(&instruction[3..])?)));
|
||||
if let Some(prefix) = instruction.strip_prefix("on ") {
|
||||
return Ok((None, Some(Color::from_str(prefix)?)));
|
||||
}
|
||||
|
||||
let colors: Vec<&str> = instruction.split(" on ").collect();
|
||||
@ -100,47 +100,89 @@ pub trait Stylize {
|
||||
/// Basic styling method, receives a styling instruction
|
||||
/// see the `stylize` function for more information
|
||||
fn stl(&self, instruction: &str) -> String;
|
||||
/// 🧉 » makes the text **black**
|
||||
fn black(&self) -> String { self.stl("black") }
|
||||
/// 🧉 » makes the text **red**
|
||||
fn red(&self) -> String { self.stl("red") }
|
||||
/// 🧉 » makes the text **green**
|
||||
fn green(&self) -> String { self.stl("green") }
|
||||
/// 🧉 » makes the text **yellow**
|
||||
fn yellow(&self) -> String { self.stl("yellow") }
|
||||
/// 🧉 » makes the text **blue**
|
||||
fn blue(&self) -> String { self.stl("blue") }
|
||||
/// 🧉 » makes the text **magenta**
|
||||
fn magenta(&self) -> String { self.stl("magenta") }
|
||||
/// 🧉 » makes the text **cyan**
|
||||
fn cyan(&self) -> String { self.stl("cyan") }
|
||||
/// 🧉 » makes the text **white**
|
||||
fn white(&self) -> String { self.stl("white") }
|
||||
/// 🧉 » makes the text **bright black**
|
||||
fn bright_black(&self) -> String { self.stl("bright-black") }
|
||||
/// 🧉 » makes the text **bright red**
|
||||
fn bright_red(&self) -> String { self.stl("bright-red") }
|
||||
/// 🧉 » makes the text **bright green**
|
||||
fn bright_green(&self) -> String { self.stl("bright-green") }
|
||||
/// 🧉 » makes the text **bright yellow**
|
||||
fn bright_yellow(&self) -> String { self.stl("bright-yellow") }
|
||||
/// 🧉 » makes the text **bright blue**
|
||||
fn bright_blue(&self) -> String { self.stl("bright-blue") }
|
||||
/// 🧉 » makes the text **bright magenta**
|
||||
fn bright_magenta(&self) -> String { self.stl("bright-magenta") }
|
||||
/// 🧉 » makes the text **bright cyan**
|
||||
fn bright_cyan(&self) -> String { self.stl("bright-cyan") }
|
||||
/// 🧉 » makes the text **bright white**
|
||||
fn bright_white(&self) -> String { self.stl("bright-white") }
|
||||
fn rgb(&self, r: u8, g: u8, b: u8) -> String { self.stl(&format!("#{:02X}{:02X}{:02X}", r, g, b)) }
|
||||
/// 🧉 » makes the text colored after the **`rgb`** param (`#RRGGBB` format)
|
||||
fn rgb(&self, rgb: &str) -> String { self.stl(rgb) }
|
||||
/// 🧉 » makes the background of the text **black**
|
||||
fn on_black(&self) -> String { self.stl("on black") }
|
||||
/// 🧉 » makes the background of the text **red**
|
||||
fn on_red(&self) -> String { self.stl("on red") }
|
||||
/// 🧉 » makes the background of the text **green**
|
||||
fn on_green(&self) -> String { self.stl("on green") }
|
||||
/// 🧉 » makes the background of the text **yellow**
|
||||
fn on_yellow(&self) -> String { self.stl("on yellow") }
|
||||
/// 🧉 » makes the background of the text **blue**
|
||||
fn on_blue(&self) -> String { self.stl("on blue") }
|
||||
/// 🧉 » makes the background of the text **magenta**
|
||||
fn on_magenta(&self) -> String { self.stl("on magenta") }
|
||||
/// 🧉 » makes the background of the text **cyan**
|
||||
fn on_cyan(&self) -> String { self.stl("on cyan") }
|
||||
/// 🧉 » makes the background of the text **white**
|
||||
fn on_white(&self) -> String { self.stl("on white") }
|
||||
/// 🧉 » makes the background of the text **bright black**
|
||||
fn on_bright_black(&self) -> String { self.stl("on bright-black") }
|
||||
/// 🧉 » makes the background of the text **bright red**
|
||||
fn on_bright_red(&self) -> String { self.stl("on bright-red") }
|
||||
/// 🧉 » makes the background of the text **bright green**
|
||||
fn on_bright_green(&self) -> String { self.stl("on bright-green") }
|
||||
/// 🧉 » makes the background of the text **bright yellow**
|
||||
fn on_bright_yellow(&self) -> String { self.stl("on bright-yellow") }
|
||||
/// 🧉 » makes the background of the text **bright blue**
|
||||
fn on_bright_blue(&self) -> String { self.stl("on bright-blue") }
|
||||
/// 🧉 » makes the background of the text **bright magenta**
|
||||
fn on_bright_magenta(&self) -> String { self.stl("on bright-magenta") }
|
||||
/// 🧉 » makes the background of the text **bright cyan**
|
||||
fn on_bright_cyan(&self) -> String { self.stl("on bright-cyan") }
|
||||
/// 🧉 » makes the background of the text **bright white**
|
||||
fn on_bright_white(&self) -> String { self.stl("on bright-white") }
|
||||
fn on_rgb(&self, r: u8, g: u8, b: u8) -> String { self.stl(&format!("on #{:02X}{:02X}{:02X}", r, g, b)) }
|
||||
/// 🧉 » makes the background color = **`rgb`** param (`#RRGGBB` format)
|
||||
fn on_rgb(&self, rgb: &str) -> String { self.stl(&format!("on {}", rgb)) }
|
||||
/// 🧉 » makes the text **bold**
|
||||
fn bold(&self) -> String { self.stl("+bold") }
|
||||
/// 🧉 » makes the text **dim**
|
||||
fn dim(&self) -> String { self.stl("+dim") }
|
||||
/// 🧉 » makes the text **italic**
|
||||
fn italic(&self) -> String { self.stl("+italic") }
|
||||
/// 🧉 » makes the text **underline**
|
||||
fn underline(&self) -> String { self.stl("+underline") }
|
||||
/// 🧉 » makes the text **blink**
|
||||
fn blink(&self) -> String { self.stl("+blink") }
|
||||
/// 🧉 » makes the text **reverse**
|
||||
fn reverse(&self) -> String { self.stl("+reverse") }
|
||||
/// 🧉 » makes the text **hidden**
|
||||
fn hidden(&self) -> String { self.stl("+hidden") }
|
||||
/// 🧉 » makes the text **strikethrough**
|
||||
fn strikethrough(&self) -> String { self.stl("+strikethrough") }
|
||||
}
|
||||
|
||||
@ -160,7 +202,6 @@ impl Stylize for String {
|
||||
/// --
|
||||
///
|
||||
/// Stylizes a string with optional ANSI color and attributes.
|
||||
///
|
||||
pub fn stylize<S: AsRef<str>>(s: S, instructions: &str) -> String {
|
||||
let styled_string = instructions::parse(instructions);
|
||||
|
||||
|
||||
@ -1 +1 @@
|
||||
mod stylizo;
|
||||
mod stylize;
|
||||
|
||||
@ -19,7 +19,7 @@ mod parse_instruction {
|
||||
assert_eq!(parse_color_instruction("red")?, (Some(Color::Red), None));
|
||||
assert_eq!(
|
||||
parse_color_instruction("#FF0000")?,
|
||||
(Some(Color::TrueColor { r: 255, g: 0, b: 0 }), None)
|
||||
(Some(Color::Rgb { r: 255, g: 0, b: 0 }), None)
|
||||
);
|
||||
assert_eq!(
|
||||
parse_color_instruction("on blue")?,
|
||||
@ -27,7 +27,7 @@ mod parse_instruction {
|
||||
);
|
||||
assert_eq!(
|
||||
parse_color_instruction("on #0000FF")?,
|
||||
(None, Some(Color::TrueColor { r: 0, g: 0, b: 255 }))
|
||||
(None, Some(Color::Rgb { r: 0, g: 0, b: 255 }))
|
||||
);
|
||||
assert_eq!(
|
||||
parse_color_instruction("red on blue")?,
|
||||
@ -36,8 +36,8 @@ mod parse_instruction {
|
||||
assert_eq!(
|
||||
parse_color_instruction("#FF0000 on #0000FF")?,
|
||||
(
|
||||
Some(Color::TrueColor { r: 255, g: 0, b: 0 }),
|
||||
Some(Color::TrueColor { r: 0, g: 0, b: 255 })
|
||||
Some(Color::Rgb { r: 255, g: 0, b: 0 }),
|
||||
Some(Color::Rgb { r: 0, g: 0, b: 255 })
|
||||
)
|
||||
);
|
||||
assert!(parse_color_instruction("red on blue on green").is_err());
|
||||
@ -72,14 +72,8 @@ mod parse_instruction {
|
||||
|
||||
// ##RRGGBB
|
||||
let styled_string = parse("#FF0000 on #0000FF")?;
|
||||
assert_eq!(
|
||||
styled_string.fg,
|
||||
Some(Color::TrueColor { r: 255, g: 0, b: 0 })
|
||||
);
|
||||
assert_eq!(
|
||||
styled_string.bg,
|
||||
Some(Color::TrueColor { r: 0, g: 0, b: 255 })
|
||||
);
|
||||
assert_eq!(styled_string.fg, Some(Color::Rgb { r: 255, g: 0, b: 0 }));
|
||||
assert_eq!(styled_string.bg, Some(Color::Rgb { r: 0, g: 0, b: 255 }));
|
||||
assert_eq!(styled_string.attrs, StyleAttributes::empty());
|
||||
|
||||
let styled_string = parse("red on blue+bold")?;
|
||||
@ -89,14 +83,8 @@ mod parse_instruction {
|
||||
|
||||
// ##RRGGBB
|
||||
let styled_string = parse("#FF0000 on #0000FF+bold")?;
|
||||
assert_eq!(
|
||||
styled_string.fg,
|
||||
Some(Color::TrueColor { r: 255, g: 0, b: 0 })
|
||||
);
|
||||
assert_eq!(
|
||||
styled_string.bg,
|
||||
Some(Color::TrueColor { r: 0, g: 0, b: 255 })
|
||||
);
|
||||
assert_eq!(styled_string.fg, Some(Color::Rgb { r: 255, g: 0, b: 0 }));
|
||||
assert_eq!(styled_string.bg, Some(Color::Rgb { r: 0, g: 0, b: 255 }));
|
||||
assert_eq!(styled_string.attrs, StyleAttributes::BOLD);
|
||||
|
||||
let styled_string = parse("red on blue+bold|underline")?;
|
||||
@ -109,10 +97,7 @@ mod parse_instruction {
|
||||
|
||||
let styled_string = parse("red on #0000FF+bold|underline|italic")?;
|
||||
assert_eq!(styled_string.fg, Some(Color::Red));
|
||||
assert_eq!(
|
||||
styled_string.bg,
|
||||
Some(Color::TrueColor { r: 0, g: 0, b: 255 })
|
||||
);
|
||||
assert_eq!(styled_string.bg, Some(Color::Rgb { r: 0, g: 0, b: 255 }));
|
||||
assert_eq!(
|
||||
styled_string.attrs,
|
||||
StyleAttributes::BOLD | StyleAttributes::UNDERLINE | StyleAttributes::ITALIC
|
||||
Loading…
x
Reference in New Issue
Block a user