From 6bee633c180723d309a143b77f7a2ca6342bb292 Mon Sep 17 00:00:00 2001 From: John Toohey Date: Mon, 1 Jan 2024 19:44:55 +0000 Subject: [PATCH 1/5] Allowed font_style to be an array This allows multiple `font_style`s to be used, allowing, say, for a bold and italic text. Fixes #49 --- src/font_style.rs | 65 +++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 1 + src/theme.rs | 27 +++----------------- 3 files changed, 69 insertions(+), 24 deletions(-) create mode 100644 src/font_style.rs diff --git a/src/font_style.rs b/src/font_style.rs new file mode 100644 index 0000000..ce62699 --- /dev/null +++ b/src/font_style.rs @@ -0,0 +1,65 @@ +use std::{ + collections::HashMap, + fmt::{self, Display, Formatter}, +}; + +use lazy_static::lazy_static; + +use yaml_rust::{yaml::Hash, Yaml}; + +lazy_static! { + static ref ANSI_STYLES: HashMap<&'static str, u8> = { + let mut m = HashMap::new(); + m.insert("regular", 0); + m.insert("bold", 1); + m.insert("faint", 2); + m.insert("italic", 3); + m.insert("underline", 4); + m.insert("blink", 5); + m.insert("rapid-blink", 6); + m.insert("overline", 53); + m + }; +} + +/// A list of font styles +#[derive(Default)] +pub struct FontStyle(Vec); + +impl FontStyle { + /// Creates a FontStyle from the yaml + /// + /// # Panics + /// + /// Panics if the yaml value is neither a string or + /// a yaml array + pub fn from_yaml(map: &Hash) -> Self { + match map.get(&Yaml::String("font-style".into())) { + Some(value) => match value { + Yaml::String(s) => Self(vec![ANSI_STYLES[s.as_str()]]), + Yaml::Array(array) => { + let mut vec = Vec::with_capacity(array.len()); + for item in array { + vec.push( + ANSI_STYLES[item + .as_str() + .expect("font_style should be a string or an array of strings")], + ); + } + Self(vec) + } + _ => panic!("font-style should be a string or an array of strings"), + }, + None => Self::default(), + } + } +} + +impl Display for FontStyle { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + for style in &self.0 { + write!(f, "{};", style)?; + } + Ok(()) + } +} diff --git a/src/main.rs b/src/main.rs index d92f6a4..bd9c721 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ mod color; mod error; mod filetypes; +mod font_style; mod theme; mod types; mod util; diff --git a/src/theme.rs b/src/theme.rs index 42a6988..17a69c4 100644 --- a/src/theme.rs +++ b/src/theme.rs @@ -4,28 +4,12 @@ use std::path::Path; use yaml_rust::yaml::YamlLoader; use yaml_rust::Yaml; -use lazy_static::lazy_static; - use crate::color::{Color, ColorMode, ColorType}; use crate::error::{Result, VividError}; +use crate::font_style::FontStyle; use crate::types::CategoryRef; use crate::util::{load_yaml_file, transpose}; -lazy_static! { - static ref ANSI_STYLES: HashMap<&'static str, u8> = { - let mut m = HashMap::new(); - m.insert("regular", 0); - m.insert("bold", 1); - m.insert("faint", 2); - m.insert("italic", 3); - m.insert("underline", 4); - m.insert("blink", 5); - m.insert("rapid-blink", 6); - m.insert("overline", 53); - m - }; -} - #[derive(Debug)] pub struct Theme { colors: HashMap, @@ -104,12 +88,7 @@ impl Theme { } if let Yaml::Hash(map) = item { - let font_style: &str = map - .get(&Yaml::String("font-style".into())) - .map(|s| s.as_str().expect("Color value should be a string")) - .unwrap_or("regular"); - - let font_style_ansi: &u8 = ANSI_STYLES.get(&font_style).unwrap(); // TODO + let font_style = FontStyle::from_yaml(map); let foreground = map .get(&Yaml::String("foreground".into())) @@ -123,7 +102,7 @@ impl Theme { let background = transpose(background.map(|fg| self.get_color(fg)))?; - let mut style: String = format!("{font_style}", font_style = *font_style_ansi,); + let mut style: String = format!("{font_style}"); if let Some(foreground) = foreground { let foreground_code = foreground.get_style(ColorType::Foreground, self.color_mode); style.push_str(&format!( From 4d2cdb99c40a2833976d81bbdc150ea9f0b4f235 Mon Sep 17 00:00:00 2001 From: John Toohey Date: Mon, 1 Jan 2024 19:51:24 +0000 Subject: [PATCH 2/5] Prevent double `;` in LS_COLORS --- src/theme.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/theme.rs b/src/theme.rs index 17a69c4..126ff12 100644 --- a/src/theme.rs +++ b/src/theme.rs @@ -105,10 +105,7 @@ impl Theme { let mut style: String = format!("{font_style}"); if let Some(foreground) = foreground { let foreground_code = foreground.get_style(ColorType::Foreground, self.color_mode); - style.push_str(&format!( - ";{foreground_code}", - foreground_code = foreground_code - )); + style.push_str(&foreground_code); } if let Some(background) = background { From 2c9d5ca600d631d5125c7b5a7f8d7b35b62e54e3 Mon Sep 17 00:00:00 2001 From: John Toohey Date: Mon, 1 Jan 2024 19:44:55 +0000 Subject: [PATCH 3/5] Allowed font_style to be an array This allows multiple `font_style`s to be used, allowing, say, for a bold and italic text. Fixes #49 --- src/font_style.rs | 65 +++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 1 + src/theme.rs | 27 +++----------------- 3 files changed, 69 insertions(+), 24 deletions(-) create mode 100644 src/font_style.rs diff --git a/src/font_style.rs b/src/font_style.rs new file mode 100644 index 0000000..ce62699 --- /dev/null +++ b/src/font_style.rs @@ -0,0 +1,65 @@ +use std::{ + collections::HashMap, + fmt::{self, Display, Formatter}, +}; + +use lazy_static::lazy_static; + +use yaml_rust::{yaml::Hash, Yaml}; + +lazy_static! { + static ref ANSI_STYLES: HashMap<&'static str, u8> = { + let mut m = HashMap::new(); + m.insert("regular", 0); + m.insert("bold", 1); + m.insert("faint", 2); + m.insert("italic", 3); + m.insert("underline", 4); + m.insert("blink", 5); + m.insert("rapid-blink", 6); + m.insert("overline", 53); + m + }; +} + +/// A list of font styles +#[derive(Default)] +pub struct FontStyle(Vec); + +impl FontStyle { + /// Creates a FontStyle from the yaml + /// + /// # Panics + /// + /// Panics if the yaml value is neither a string or + /// a yaml array + pub fn from_yaml(map: &Hash) -> Self { + match map.get(&Yaml::String("font-style".into())) { + Some(value) => match value { + Yaml::String(s) => Self(vec![ANSI_STYLES[s.as_str()]]), + Yaml::Array(array) => { + let mut vec = Vec::with_capacity(array.len()); + for item in array { + vec.push( + ANSI_STYLES[item + .as_str() + .expect("font_style should be a string or an array of strings")], + ); + } + Self(vec) + } + _ => panic!("font-style should be a string or an array of strings"), + }, + None => Self::default(), + } + } +} + +impl Display for FontStyle { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + for style in &self.0 { + write!(f, "{};", style)?; + } + Ok(()) + } +} diff --git a/src/main.rs b/src/main.rs index d92f6a4..bd9c721 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ mod color; mod error; mod filetypes; +mod font_style; mod theme; mod types; mod util; diff --git a/src/theme.rs b/src/theme.rs index 42a6988..17a69c4 100644 --- a/src/theme.rs +++ b/src/theme.rs @@ -4,28 +4,12 @@ use std::path::Path; use yaml_rust::yaml::YamlLoader; use yaml_rust::Yaml; -use lazy_static::lazy_static; - use crate::color::{Color, ColorMode, ColorType}; use crate::error::{Result, VividError}; +use crate::font_style::FontStyle; use crate::types::CategoryRef; use crate::util::{load_yaml_file, transpose}; -lazy_static! { - static ref ANSI_STYLES: HashMap<&'static str, u8> = { - let mut m = HashMap::new(); - m.insert("regular", 0); - m.insert("bold", 1); - m.insert("faint", 2); - m.insert("italic", 3); - m.insert("underline", 4); - m.insert("blink", 5); - m.insert("rapid-blink", 6); - m.insert("overline", 53); - m - }; -} - #[derive(Debug)] pub struct Theme { colors: HashMap, @@ -104,12 +88,7 @@ impl Theme { } if let Yaml::Hash(map) = item { - let font_style: &str = map - .get(&Yaml::String("font-style".into())) - .map(|s| s.as_str().expect("Color value should be a string")) - .unwrap_or("regular"); - - let font_style_ansi: &u8 = ANSI_STYLES.get(&font_style).unwrap(); // TODO + let font_style = FontStyle::from_yaml(map); let foreground = map .get(&Yaml::String("foreground".into())) @@ -123,7 +102,7 @@ impl Theme { let background = transpose(background.map(|fg| self.get_color(fg)))?; - let mut style: String = format!("{font_style}", font_style = *font_style_ansi,); + let mut style: String = format!("{font_style}"); if let Some(foreground) = foreground { let foreground_code = foreground.get_style(ColorType::Foreground, self.color_mode); style.push_str(&format!( From cd2298e18a4ffeab864f32354aeb022acaef8a81 Mon Sep 17 00:00:00 2001 From: John Toohey Date: Mon, 1 Jan 2024 19:51:24 +0000 Subject: [PATCH 4/5] Prevent double `;` in LS_COLORS --- src/theme.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/theme.rs b/src/theme.rs index 17a69c4..126ff12 100644 --- a/src/theme.rs +++ b/src/theme.rs @@ -105,10 +105,7 @@ impl Theme { let mut style: String = format!("{font_style}"); if let Some(foreground) = foreground { let foreground_code = foreground.get_style(ColorType::Foreground, self.color_mode); - style.push_str(&format!( - ";{foreground_code}", - foreground_code = foreground_code - )); + style.push_str(&foreground_code); } if let Some(background) = background { From 473097e0d908a390cf1c79bdb5f707a3cf1b4fcd Mon Sep 17 00:00:00 2001 From: John Toohey Date: Wed, 3 Jan 2024 19:00:53 +0000 Subject: [PATCH 5/5] Got all the tests working This removes a trailing semicolon that can occur in some positions --- src/font_style.rs | 10 +++++++--- src/theme.rs | 5 ++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/font_style.rs b/src/font_style.rs index ce62699..65d63ed 100644 --- a/src/font_style.rs +++ b/src/font_style.rs @@ -50,15 +50,19 @@ impl FontStyle { } _ => panic!("font-style should be a string or an array of strings"), }, - None => Self::default(), + None => Self(vec![0]), } } } impl Display for FontStyle { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - for style in &self.0 { - write!(f, "{};", style)?; + for (i, style) in self.0.iter().enumerate() { + if i + 1 == self.0.len() { + write!(f, "{}", style)?; + } else { + write!(f, "{};", style)?; + } } Ok(()) } diff --git a/src/theme.rs b/src/theme.rs index 126ff12..17a69c4 100644 --- a/src/theme.rs +++ b/src/theme.rs @@ -105,7 +105,10 @@ impl Theme { let mut style: String = format!("{font_style}"); if let Some(foreground) = foreground { let foreground_code = foreground.get_style(ColorType::Foreground, self.color_mode); - style.push_str(&foreground_code); + style.push_str(&format!( + ";{foreground_code}", + foreground_code = foreground_code + )); } if let Some(background) = background {