#[derive(PartialEq, Clone, Copy, Default, Debug)]
#[cfg_attr(
feature = "derive_serde_style",
derive(serde::Deserialize, serde::Serialize)
)]
pub struct Style {
pub foreground: Option<Colour>,
pub background: Option<Colour>,
pub is_bold: bool,
pub is_dimmed: bool,
pub is_italic: bool,
pub is_underline: bool,
pub is_blink: bool,
pub is_reverse: bool,
pub is_hidden: bool,
pub is_strikethrough: bool,
}
impl Style {
pub fn new() -> Style {
Style::default()
}
pub fn bold(mut self) -> Self {
self.is_bold = true;
self
}
pub fn dimmed(mut self) -> Self {
self.is_dimmed = true;
self
}
pub fn italic(mut self) -> Self {
self.is_italic = true;
self
}
pub fn underline(mut self) -> Self {
self.is_underline = true;
self
}
pub fn blink(mut self) -> Self {
self.is_blink = true;
self
}
pub fn reverse(mut self) -> Self {
self.is_reverse = true;
self
}
pub fn hidden(mut self) -> Self {
self.is_hidden = true;
self
}
pub fn strikethrough(mut self) -> Self {
self.is_strikethrough = true;
self
}
pub fn fg(mut self, foreground: Colour) -> Self {
self.foreground = Some(foreground);
self
}
pub fn on(mut self, background: Colour) -> Self {
self.background = Some(background);
self
}
pub fn is_plain(&self) -> bool {
*self == Style::default()
}
}
#[derive(PartialEq, Clone, Copy, Debug)]
#[cfg_attr(
feature = "derive_serde_style",
derive(serde::Deserialize, serde::Serialize)
)]
pub enum Colour {
Black,
Red,
Green,
Yellow,
Blue,
Purple,
Cyan,
White,
Fixed(u8),
RGB(u8, u8, u8),
}
impl Colour {
pub fn normal(self) -> Style {
Style {
foreground: Some(self),
..Style::default()
}
}
pub fn bold(self) -> Style {
Style {
foreground: Some(self),
is_bold: true,
..Style::default()
}
}
pub fn dimmed(self) -> Style {
Style {
foreground: Some(self),
is_dimmed: true,
..Style::default()
}
}
pub fn italic(self) -> Style {
Style {
foreground: Some(self),
is_italic: true,
..Style::default()
}
}
pub fn underline(self) -> Style {
Style {
foreground: Some(self),
is_underline: true,
..Style::default()
}
}
pub fn blink(self) -> Style {
Style {
foreground: Some(self),
is_blink: true,
..Style::default()
}
}
pub fn reverse(self) -> Style {
Style {
foreground: Some(self),
is_reverse: true,
..Style::default()
}
}
pub fn hidden(self) -> Style {
Style {
foreground: Some(self),
is_hidden: true,
..Style::default()
}
}
pub fn strikethrough(self) -> Style {
Style {
foreground: Some(self),
is_strikethrough: true,
..Style::default()
}
}
pub fn on(self, background: Colour) -> Style {
Style {
foreground: Some(self),
background: Some(background),
..Style::default()
}
}
}
impl From<Colour> for Style {
fn from(colour: Colour) -> Style {
colour.normal()
}
}
#[cfg(test)]
#[cfg(feature = "derive_serde_style")]
mod serde_json_tests {
use super::{Colour, Style};
#[test]
fn colour_serialization() {
let colours = &[
Colour::Red,
Colour::Blue,
Colour::RGB(123, 123, 123),
Colour::Fixed(255),
];
assert_eq!(
serde_json::to_string(&colours).unwrap(),
String::from("[\"Red\",\"Blue\",{\"RGB\":[123,123,123]},{\"Fixed\":255}]")
);
}
#[test]
fn colour_deserialization() {
let colours = &[
Colour::Red,
Colour::Blue,
Colour::RGB(123, 123, 123),
Colour::Fixed(255),
];
for colour in colours {
let serialized = serde_json::to_string(&colour).unwrap();
let deserialized: Colour = serde_json::from_str(&serialized).unwrap();
assert_eq!(colour, &deserialized);
}
}
#[test]
fn style_serialization() {
let style = Style::default();
assert_eq!(serde_json::to_string(&style).unwrap(), "{\"foreground\":null,\"background\":null,\"is_bold\":false,\"is_dimmed\":false,\"is_italic\":false,\"is_underline\":false,\"is_blink\":false,\"is_reverse\":false,\"is_hidden\":false,\"is_strikethrough\":false}".to_string());
}
}