From 68d8d4998547e859527ad7aa7112d09ee74f0fbb Mon Sep 17 00:00:00 2001 From: Daniel Jankowski Date: Mon, 15 Jul 2024 16:16:46 +0200 Subject: [PATCH] feat: add color aliases closes #75 --- benches/benches.rs | 5 +++ plugin-dev-workspace.kdl | 38 +++++++++++++---------- src/border.rs | 4 +-- src/config.rs | 19 +++++++----- src/render.rs | 62 +++++++++++++++++++++++++++---------- src/widgets/command.rs | 10 +++--- src/widgets/datetime.rs | 2 +- src/widgets/mode.rs | 28 ++++++++--------- src/widgets/notification.rs | 8 ++--- src/widgets/swap_layout.rs | 2 +- src/widgets/tabs.rs | 20 ++++++------ 11 files changed, 120 insertions(+), 78 deletions(-) diff --git a/benches/benches.rs b/benches/benches.rs index 891a972..2eabb75 100644 --- a/benches/benches.rs +++ b/benches/benches.rs @@ -60,6 +60,7 @@ fn bench_moduleconfig_render_bar(c: &mut Criterion) { fn bench_formattedpart_format_string_with_widgets(c: &mut Criterion) { let mut format = FormattedPart::from_format_string( "#[fg=#9399B2,bg=#181825,bold,italic] {mode} {datetime} {session} [] ", + &BTreeMap::new(), ); let mut widgets: BTreeMap> = BTreeMap::new(); @@ -106,6 +107,7 @@ fn bench_formattedpart_from_format_string(c: &mut Criterion) { b.iter(|| { FormattedPart::from_format_string( "#[fg=#9399B2,bg=#181825,bold,italic] {index} {name} [] ", + &BTreeMap::new(), ) }) }); @@ -116,6 +118,7 @@ fn bench_formattedpart_from_format_string_cached(c: &mut Criterion) { b.iter(|| { formatted_part_from_string_cached( "#[fg=#9399B2,bg=#181825,bold,italic] {index} {name} [] ", + &BTreeMap::new(), ) }) }); @@ -126,6 +129,7 @@ fn bench_formattedpart_multiple_from_format_string(c: &mut Criterion) { b.iter(|| { FormattedPart::multiple_from_format_string( "#[fg=#9399B2,bg=#181825,bold,italic] {index} {name} [] #[fg=#9399B2,bg=#181825,bold,italic] {index} {name} [] ", + &BTreeMap::new(), ) }) }); @@ -136,6 +140,7 @@ fn bench_formattedparts_from_format_string_cached(c: &mut Criterion) { b.iter(|| { formatted_parts_from_string_cached( "#[fg=#9399B2,bg=#181825,bold,italic] {index} {name} [] #[fg=#9399B2,bg=#181825,bold,italic] {index} {name} [] ", + &BTreeMap::new(), ) }) }); diff --git a/plugin-dev-workspace.kdl b/plugin-dev-workspace.kdl index ff08575..0da48e4 100644 --- a/plugin-dev-workspace.kdl +++ b/plugin-dev-workspace.kdl @@ -5,15 +5,19 @@ layout { pane size=2 borderless=true { plugin location="file:target/wasm32-wasi/debug/zjstatus.wasm" { - format_left "{mode}#[fg=#89B4FA,bg=#181825,bold] {session}" - format_center "{tabs}" + color_blue "#89B4FA" + color_yellow "yellow" + color_bg "#181825" + + format_left "{mode}#[fg={blue},bg={bg},bold] {session}" + format_center "{tabs} {command_3}" format_right "{datetime}" - format_space "#[bg=#181825]" + format_space "#[bg={bg}]" format_precedence "lrc" format_hide_on_overlength "false" - notification_format_unread "#[fg=#89B4FA,bg=#181825,blink]  #[fg=#89B4FA,bg=#181825] {message} " - notification_format_no_notifications "#[fg=#89B4FA,bg=#181825,dim]  " + notification_format_unread "#[fg={blue},bg={bg},blink]  #[fg={blue},bg={bg}] {message} " + notification_format_no_notifications "#[fg={blue},bg={bg},dim]  " notification_show_interval "10" border_enabled "true" @@ -26,22 +30,22 @@ layout { hide_frame_for_single_pane "true" - mode_normal "#[bg=blue] #[bg=yellow] " - mode_tmux "#[bg=yellow] " + mode_normal "#[bg={blue}] #[bg={yellow}] " + mode_tmux "#[bg={yellow}] " mode_default_to_mode "tmux" - tab_normal "#[fg=#6C7086,bg=#181825] {index} {name} {floating_indicator} " - tab_rename "#[fg=#eba0ac,bg=#181825] {index} {name} {floating_indicator} " - tab_normal_fullscreen "#[fg=#6C7086,bg=#181825] {index} {name} [] " - tab_normal_sync "#[fg=#6C7086,bg=#181825] {index} {name} <> " - tab_active "#[fg=#9399B2,bg=#181825,bold,italic] {index} {name} {floating_total_count}{floating_indicator}{sync_indicator}{fullscreen_indicator}" - tab_separator "#[fg=#6C7086,bg=#181825] | " + tab_normal "#[fg=#6C7086,bg={bg}] {index} {name} {floating_indicator} " + tab_rename "#[fg=#eba0ac,bg={bg}] {index} {name} {floating_indicator} " + tab_normal_fullscreen "#[fg=#6C7086,bg={bg}] {index} {name} [] " + tab_normal_sync "#[fg=#6C7086,bg={bg}] {index} {name} <> " + tab_active "#[fg=#9399B2,bg={bg},bold,italic] {index} {name} {floating_total_count}{floating_indicator}{sync_indicator}{fullscreen_indicator}" + tab_separator "#[fg=#6C7086,bg={bg}] | " tab_floating_indicator "F" tab_sync_indicator "S" tab_fullscreen_indicator "FS" tab_display_count "3" - tab_truncate_start_format "#[fg=red,bg=#181825] < +{count} ..." - tab_truncate_end_format "#[fg=red,bg=#181825] ... +{count} >" + tab_truncate_start_format "#[fg=red,bg={bg}] < +{count} ..." + tab_truncate_end_format "#[fg=red,bg={bg}] ... +{count} >" command_0_command "echo \"平仮名, ひらがな 📦\"" command_0_clickaction "bash -c \"zellij --session zjstatus-dev pipe 'zjstatus::notify::hello world!' -n zjstatus\"" @@ -61,12 +65,12 @@ layout { command_git_branch_format "#[fg=red] {stdout} " command_git_branch_interval "2" - command_3_command "echo -e \"#[italic,bold] foo #[dim,bold,italic] bar \"" + command_3_command "echo -e \"#[fg={yellow},italic,bold] foo #[dim,bold,italic] bar \"" command_3_format "{stdout}" command_3_interval "10" command_3_rendermode "dynamic" - datetime "#[fg=#6C7086,bg=#181825,bold] {format} #[bg=#6C7086,fg=#181825,bold] {time}" + datetime "#[fg=#6C7086,bg={bg},bold] {format} #[bg=#6C7086,fg={bg},bold] {time}" datetime_time_format "%H:%M:%S" datetime_format "%A, %d %b %Y %H:%M" datetime_timezone "Europe/Berlin" diff --git a/src/border.rs b/src/border.rs index f1720db..c0c06d5 100644 --- a/src/border.rs +++ b/src/border.rs @@ -36,7 +36,7 @@ impl BorderConfig { } } -pub fn parse_border_config(config: BTreeMap) -> Option { +pub fn parse_border_config(config: &BTreeMap) -> Option { let enabled = match config.get("border_enabled") { Some(e) => matches!(e.as_str(), "true"), None => { @@ -65,7 +65,7 @@ pub fn parse_border_config(config: BTreeMap) -> Option false, }; - let border_config = parse_border_config(config.clone()).unwrap_or_default(); + let border_config = parse_border_config(config).unwrap_or_default(); Ok(Self { left_parts_config: left_parts_config.to_owned(), - left_parts: parts_from_config(Some(&left_parts_config.to_owned())), + left_parts: parts_from_config(Some(&left_parts_config.to_owned()), config), center_parts_config: center_parts_config.to_owned(), - center_parts: parts_from_config(Some(¢er_parts_config.to_owned())), + center_parts: parts_from_config(Some(¢er_parts_config.to_owned()), config), right_parts_config: right_parts_config.to_owned(), - right_parts: parts_from_config(Some(&right_parts_config.to_owned())), - format_space: FormattedPart::from_format_string(format_space_config), + right_parts: parts_from_config(Some(&right_parts_config.to_owned()), config), + format_space: FormattedPart::from_format_string(format_space_config, config), hide_frame_for_single_pane, border: border_config, format_precedence, @@ -478,11 +478,14 @@ impl ModuleConfig { } } -fn parts_from_config(format: Option<&String>) -> Vec { +fn parts_from_config( + format: Option<&String>, + config: &BTreeMap, +) -> Vec { match format { Some(format) => format .split("#[") - .map(FormattedPart::from_format_string) + .map(|s| FormattedPart::from_format_string(s, config)) .collect(), None => vec![], } @@ -497,7 +500,7 @@ mod test { fn test_formatted_part_from_string() { let input = "#[fg=#ff0000,bg=#00ff00,bold,italic]foo"; - let part = FormattedPart::from_format_string(input); + let part = FormattedPart::from_format_string(input, &BTreeMap::new()); assert_eq!( part, diff --git a/src/render.rs b/src/render.rs index d8a1756..352cdbb 100644 --- a/src/render.rs +++ b/src/render.rs @@ -44,28 +44,37 @@ pub struct FormattedPart { create = "{ SizedCache::with_size(100) }", convert = r#"{ (format.to_owned()) }"# )] -pub fn formatted_part_from_string_cached(format: &str) -> FormattedPart { - FormattedPart::from_format_string(format) +pub fn formatted_part_from_string_cached( + format: &str, + config: &BTreeMap, +) -> FormattedPart { + FormattedPart::from_format_string(format, config) } #[cached( ty = "SizedCache>", create = "{ SizedCache::with_size(100) }", - convert = r#"{ (config.to_owned()) }"# + convert = r#"{ (config_string.to_owned()) }"# )] -pub fn formatted_parts_from_string_cached(config: &str) -> Vec { - FormattedPart::multiple_from_format_string(config) +pub fn formatted_parts_from_string_cached( + config_string: &str, + config: &BTreeMap, +) -> Vec { + FormattedPart::multiple_from_format_string(config_string, config) } impl FormattedPart { - pub fn multiple_from_format_string(config: &str) -> Vec { - config + pub fn multiple_from_format_string( + config_string: &str, + config: &BTreeMap, + ) -> Vec { + config_string .split("#[") - .map(FormattedPart::from_format_string) + .map(|s| FormattedPart::from_format_string(s, config)) .collect() } - pub fn from_format_string(format: &str) -> Self { + pub fn from_format_string(format: &str, config: &BTreeMap) -> Self { let format = match format.starts_with("#[") { true => format.strip_prefix("#[").unwrap(), false => format, @@ -91,15 +100,15 @@ impl FormattedPart { for part in parts { if part.starts_with("fg=") { - result.fg = parse_color(part.strip_prefix("fg=").unwrap()); + result.fg = parse_color(part.strip_prefix("fg=").unwrap(), config); } if part.starts_with("bg=") { - result.bg = parse_color(part.strip_prefix("bg=").unwrap()); + result.bg = parse_color(part.strip_prefix("bg=").unwrap(), config); } if part.starts_with("us=") { - result.us = parse_color(part.strip_prefix("us=").unwrap()); + result.us = parse_color(part.strip_prefix("us=").unwrap(), config); } if part.eq("reverse") { @@ -290,8 +299,17 @@ fn hex_to_rgb(s: &str) -> anyhow::Result> { create = "{ SizedCache::with_size(100) }", convert = r#"{ (color.to_owned()) }"# )] -fn parse_color(color: &str) -> Option { +fn parse_color(color: &str, config: &BTreeMap) -> Option { let mut color = color; + if color.starts_with('{') { + let alias_name = &color[1..color.len() - 1]; + + color = match config.get(&format!("color_{alias_name}")) { + Some(color_str) => color_str, + None => return None, + }; + } + if color.starts_with('#') { let rgb = match hex_to_rgb(color.strip_prefix('#').unwrap()) { Ok(rgb) => rgb, @@ -376,18 +394,28 @@ mod test { #[test] fn test_parse_color() { - let result = parse_color("#010203"); + let mut config: BTreeMap = BTreeMap::new(); + config.insert("color_green".to_owned(), "#00ff00".to_owned()); + + let result = parse_color("#010203", &config); let expected = RgbColor(1, 2, 3); assert_eq!(result, Some(expected.into())); - let result = parse_color("255"); + let result = parse_color("255", &config); let expected = Ansi256Color(255); assert_eq!(result, Some(expected.into())); - let result = parse_color("365"); + let result = parse_color("365", &config); assert_eq!(result, None); - let result = parse_color("#365"); + let result = parse_color("#365", &config); + assert_eq!(result, None); + + let result = parse_color("{green}", &config); + let expected = RgbColor(0, 255, 0); + assert_eq!(result, Some(expected.into())); + + let result = parse_color("{blue}", &config); assert_eq!(result, None); } } diff --git a/src/widgets/command.rs b/src/widgets/command.rs index 91ff991..c5a902f 100644 --- a/src/widgets/command.rs +++ b/src/widgets/command.rs @@ -50,12 +50,14 @@ pub struct CommandResult { pub struct CommandWidget { config: BTreeMap, + zj_conf: BTreeMap, } impl CommandWidget { pub fn new(config: &BTreeMap) -> Self { Self { config: parse_config(config), + zj_conf: config.clone(), } } } @@ -123,7 +125,7 @@ impl Widget for CommandWidget { match command_config.render_mode { RenderMode::Static => content, - RenderMode::Dynamic => render_dynamic_formatted_content(&content), + RenderMode::Dynamic => render_dynamic_formatted_content(&content, &self.zj_conf), RenderMode::Raw => content, } } @@ -153,8 +155,8 @@ impl Widget for CommandWidget { } } -fn render_dynamic_formatted_content(content: &str) -> String { - formatted_parts_from_string_cached(content) +fn render_dynamic_formatted_content(content: &str, config: &BTreeMap) -> String { + formatted_parts_from_string_cached(content, config) .iter() .map(|fp| fp.format_string(&fp.content)) .collect::>() @@ -263,7 +265,7 @@ fn parse_config(zj_conf: &BTreeMap) -> BTreeMap) -> Self { let normal_format = match config.get("mode_normal") { - Some(form) => FormattedPart::multiple_from_format_string(form), + Some(form) => FormattedPart::multiple_from_format_string(form, config), None => vec![], }; let locked_format = match config.get("mode_locked") { - Some(form) => FormattedPart::multiple_from_format_string(form), + Some(form) => FormattedPart::multiple_from_format_string(form, config), None => vec![], }; let resize_format = match config.get("mode_resize") { - Some(form) => FormattedPart::multiple_from_format_string(form), + Some(form) => FormattedPart::multiple_from_format_string(form, config), None => vec![], }; let pane_format = match config.get("mode_pane") { - Some(form) => FormattedPart::multiple_from_format_string(form), + Some(form) => FormattedPart::multiple_from_format_string(form, config), None => vec![], }; let tab_format = match config.get("mode_tab") { - Some(form) => FormattedPart::multiple_from_format_string(form), + Some(form) => FormattedPart::multiple_from_format_string(form, config), None => vec![], }; let scroll_format = match config.get("mode_scroll") { - Some(form) => FormattedPart::multiple_from_format_string(form), + Some(form) => FormattedPart::multiple_from_format_string(form, config), None => vec![], }; let enter_search_format = match config.get("mode_enter_search") { - Some(form) => FormattedPart::multiple_from_format_string(form), + Some(form) => FormattedPart::multiple_from_format_string(form, config), None => vec![], }; let search_format = match config.get("mode_search") { - Some(form) => FormattedPart::multiple_from_format_string(form), + Some(form) => FormattedPart::multiple_from_format_string(form, config), None => vec![], }; let rename_tab_format = match config.get("mode_rename_tab") { - Some(form) => FormattedPart::multiple_from_format_string(form), + Some(form) => FormattedPart::multiple_from_format_string(form, config), None => vec![], }; let rename_pane_format = match config.get("mode_rename_pane") { - Some(form) => FormattedPart::multiple_from_format_string(form), + Some(form) => FormattedPart::multiple_from_format_string(form, config), None => vec![], }; let session_format = match config.get("mode_session") { - Some(form) => FormattedPart::multiple_from_format_string(form), + Some(form) => FormattedPart::multiple_from_format_string(form, config), None => vec![], }; let move_format = match config.get("mode_move") { - Some(form) => FormattedPart::multiple_from_format_string(form), + Some(form) => FormattedPart::multiple_from_format_string(form, config), None => vec![], }; let prompt_format = match config.get("mode_prompt") { - Some(form) => FormattedPart::multiple_from_format_string(form), + Some(form) => FormattedPart::multiple_from_format_string(form, config), None => vec![], }; let tmux_format = match config.get("mode_tmux") { - Some(form) => FormattedPart::multiple_from_format_string(form), + Some(form) => FormattedPart::multiple_from_format_string(form, config), None => vec![], }; diff --git a/src/widgets/notification.rs b/src/widgets/notification.rs index 1b8cfcd..458d12a 100644 --- a/src/widgets/notification.rs +++ b/src/widgets/notification.rs @@ -20,13 +20,13 @@ pub struct NotificationWidget { impl NotificationWidget { pub fn new(config: &BTreeMap) -> Self { let format_unread = match config.get("notification_format_unread") { - Some(f) => FormattedPart::multiple_from_format_string(f), - None => FormattedPart::multiple_from_format_string(""), + Some(f) => FormattedPart::multiple_from_format_string(f, config), + None => FormattedPart::multiple_from_format_string("", config), }; let format_no_notifications = match config.get("notification_format_no_notifications") { - Some(f) => FormattedPart::multiple_from_format_string(f), - None => FormattedPart::multiple_from_format_string(""), + Some(f) => FormattedPart::multiple_from_format_string(f, config), + None => FormattedPart::multiple_from_format_string("", config), }; let show_interval = match config.get("notification_show_interval") { diff --git a/src/widgets/swap_layout.rs b/src/widgets/swap_layout.rs index d8f9ffb..8c9e036 100644 --- a/src/widgets/swap_layout.rs +++ b/src/widgets/swap_layout.rs @@ -13,7 +13,7 @@ impl SwapLayoutWidget { pub fn new(config: &BTreeMap) -> Self { let mut format: Vec = Vec::new(); if let Some(form) = config.get("swap_layout_format") { - format = FormattedPart::multiple_from_format_string(form); + format = FormattedPart::multiple_from_format_string(form, config); } let hide_if_empty = match config.get("swap_layout_hide_if_empty") { diff --git a/src/widgets/tabs.rs b/src/widgets/tabs.rs index ee88769..46753bf 100644 --- a/src/widgets/tabs.rs +++ b/src/widgets/tabs.rs @@ -30,36 +30,36 @@ impl TabsWidget { pub fn new(config: &BTreeMap) -> Self { let mut normal_tab_format: Vec = Vec::new(); if let Some(form) = config.get("tab_normal") { - normal_tab_format = FormattedPart::multiple_from_format_string(form); + normal_tab_format = FormattedPart::multiple_from_format_string(form, config); } let normal_tab_fullscreen_format = match config.get("tab_normal_fullscreen") { - Some(form) => FormattedPart::multiple_from_format_string(form), + Some(form) => FormattedPart::multiple_from_format_string(form, config), None => normal_tab_format.clone(), }; let normal_tab_sync_format = match config.get("tab_normal_sync") { - Some(form) => FormattedPart::multiple_from_format_string(form), + Some(form) => FormattedPart::multiple_from_format_string(form, config), None => normal_tab_format.clone(), }; let mut active_tab_format = normal_tab_format.clone(); if let Some(form) = config.get("tab_active") { - active_tab_format = FormattedPart::multiple_from_format_string(form); + active_tab_format = FormattedPart::multiple_from_format_string(form, config); } let active_tab_fullscreen_format = match config.get("tab_active_fullscreen") { - Some(form) => FormattedPart::multiple_from_format_string(form), + Some(form) => FormattedPart::multiple_from_format_string(form, config), None => active_tab_format.clone(), }; let active_tab_sync_format = match config.get("tab_active_sync") { - Some(form) => FormattedPart::multiple_from_format_string(form), + Some(form) => FormattedPart::multiple_from_format_string(form, config), None => active_tab_format.clone(), }; let rename_tab_format = match config.get("tab_rename") { - Some(form) => FormattedPart::multiple_from_format_string(form), + Some(form) => FormattedPart::multiple_from_format_string(form, config), None => active_tab_format.clone(), }; @@ -73,15 +73,15 @@ impl TabsWidget { let tab_truncate_start_format = config .get("tab_truncate_start_format") - .map(|form| FormattedPart::from_format_string(form)); + .map(|form| FormattedPart::from_format_string(form, config)); let tab_truncate_end_format = config .get("tab_truncate_end_format") - .map(|form| FormattedPart::from_format_string(form)); + .map(|form| FormattedPart::from_format_string(form, config)); let separator = config .get("tab_separator") - .map(|s| FormattedPart::from_format_string(s)); + .map(|s| FormattedPart::from_format_string(s, config)); Self { normal_tab_format,