diff options
| author | Daniel Jankowski <daniel.jankowski@rub.de> | 2023-12-26 13:30:50 +0100 |
|---|---|---|
| committer | Daniel Jankowski <daniel.jankowski@rub.de> | 2023-12-26 13:30:50 +0100 |
| commit | 340a1861dd41fb73715a6417da5adb4ff0b9d851 (patch) | |
| tree | bcb96d9f3c50766601850cc2e0306901f3dbf28d | |
| parent | chore: add conky config to examples (diff) | |
| download | sl0pstatus-340a1861dd41fb73715a6417da5adb4ff0b9d851.tar.gz sl0pstatus-340a1861dd41fb73715a6417da5adb4ff0b9d851.tar.xz sl0pstatus-340a1861dd41fb73715a6417da5adb4ff0b9d851.zip | |
feat: render only widgets that needs an update
| -rw-r--r-- | benches/benches.rs | 5 | ||||
| -rw-r--r-- | plugin-dev-workspace.kdl | 2 | ||||
| -rw-r--r-- | src/bin/zjstatus.rs | 7 | ||||
| -rw-r--r-- | src/config.rs | 65 | ||||
| -rw-r--r-- | src/render.rs | 54 |
5 files changed, 109 insertions, 24 deletions
diff --git a/benches/benches.rs b/benches/benches.rs index 1435b87..971ff36 100644 --- a/benches/benches.rs +++ b/benches/benches.rs @@ -17,7 +17,7 @@ fn bench_moduleconfig_render_bar(c: &mut Criterion) { ("format_space".to_owned(), "#[bg=#181825]".to_owned()), ]); - let module_config = ModuleConfig::new(&config); + let mut module_config = ModuleConfig::new(&config); let mut widgets: BTreeMap<String, Arc<dyn Widget>> = BTreeMap::new(); @@ -58,7 +58,7 @@ fn bench_moduleconfig_render_bar(c: &mut Criterion) { } fn bench_formattedpart_format_string_with_widgets(c: &mut Criterion) { - let format = FormattedPart::from_format_string( + let mut format = FormattedPart::from_format_string( "#[fg=#9399B2,bg=#181825,bold,italic] {mode} {datetime} {session} [] ", ); @@ -92,6 +92,7 @@ fn bench_formattedpart_format_string_with_widgets(c: &mut Criterion) { active: true, ..Default::default() }], + cache_mask: 0b00000011, ..Default::default() }; diff --git a/plugin-dev-workspace.kdl b/plugin-dev-workspace.kdl index c1f6a9f..b438e8c 100644 --- a/plugin-dev-workspace.kdl +++ b/plugin-dev-workspace.kdl @@ -28,7 +28,7 @@ layout { tab_active_sync "#[fg=#9399B2,bg=#181825,bold,italic] {index} {name} <> " - command_1_command "pwd" + command_1_command "date" command_1_format "#[fg=blue,bg=black] {exit_code} {stdout} " command_1_interval "1" diff --git a/src/bin/zjstatus.rs b/src/bin/zjstatus.rs index d08c016..0b12993 100644 --- a/src/bin/zjstatus.rs +++ b/src/bin/zjstatus.rs @@ -15,7 +15,7 @@ use std::{collections::BTreeMap, sync::Arc, usize}; use uuid::Uuid; use zjstatus::{ - config::{self, ZellijState}, + config::{self, ZellijState, UpdateEventMask}, frames, widgets, }; @@ -65,6 +65,7 @@ impl ZellijPlugin for State { tabs: Vec::new(), sessions: Vec::new(), start_time: Local::now(), + cache_mask: 0, }; } @@ -88,6 +89,7 @@ impl ZellijPlugin for State { } self.state.mode = mode_info; + self.state.cache_mask = UpdateEventMask::Mode as u8; should_render = true; } Event::PaneUpdate(pane_info) => { @@ -113,6 +115,7 @@ impl ZellijPlugin for State { if !self.got_permissions { return false; } + self.state.cache_mask = UpdateEventMask::Command as u8; if let Some(name) = context.get("name") { let stdout = match String::from_utf8(stdout) { @@ -153,6 +156,7 @@ impl ZellijPlugin for State { } } + self.state.cache_mask = UpdateEventMask::Session as u8; self.state.sessions = session_info; should_render = true; @@ -162,6 +166,7 @@ impl ZellijPlugin for State { return false; } + self.state.cache_mask = UpdateEventMask::Tab as u8; self.state.tabs = tab_info; should_render = true; } diff --git a/src/config.rs b/src/config.rs index 7184a21..194d0d4 100644 --- a/src/config.rs +++ b/src/config.rs @@ -19,6 +19,28 @@ pub struct ZellijState { pub tabs: Vec<TabInfo>, pub sessions: Vec<SessionInfo>, pub start_time: DateTime<Local>, + pub cache_mask: u8, +} + +pub enum UpdateEventMask { + Always = 0b10000000, + Mode = 0b00000001, + Tab = 0b00000010, + Command = 0b00000100, + Session = 0b00001000, + None = 0b00000000, +} + +pub fn event_mask_from_widget_name(name: &str) -> u8 { + match name { + "command" => UpdateEventMask::Command as u8 | UpdateEventMask::Session as u8, + "datetime" => UpdateEventMask::Always as u8, + "mode" => UpdateEventMask::Mode as u8, + "session" => UpdateEventMask::Session as u8, + "swap_layout" => UpdateEventMask::Tab as u8, + "tabs" => UpdateEventMask::Tab as u8, + _ => UpdateEventMask::None as u8, + } } #[derive(Default)] @@ -71,7 +93,7 @@ impl ModuleConfig { } pub fn handle_mouse_action( - &self, + &mut self, state: ZellijState, mouse: Mouse, widget_map: BTreeMap<String, Arc<dyn Widget>>, @@ -97,13 +119,16 @@ impl ModuleConfig { return; } - let output_right = self.right_parts.iter().fold("".to_owned(), |acc, part| { - format!( - "{}{}", - acc, - part.format_string_with_widgets(&widget_map, &state) - ) - }); + let output_right = self + .right_parts + .iter_mut() + .fold("".to_owned(), |acc, part| { + format!( + "{}{}", + acc, + part.format_string_with_widgets(&widget_map, &state) + ) + }); let widget_spacer = strip_ansi_escapes::strip_str(self.get_spacer( &" ".repeat(left_len), @@ -169,20 +194,27 @@ impl ModuleConfig { rendered_output.len() } - pub fn render_bar(&self, state: ZellijState, widget_map: BTreeMap<String, Arc<dyn Widget>>) { - let output_left = self.left_parts.iter().fold("".to_owned(), |acc, part| { + pub fn render_bar( + &mut self, + state: ZellijState, + widget_map: BTreeMap<String, Arc<dyn Widget>>, + ) { + let output_left = self.left_parts.iter_mut().fold("".to_owned(), |acc, part| { format!( "{acc}{}", part.format_string_with_widgets(&widget_map, &state) ) }); - let output_right = self.right_parts.iter().fold("".to_owned(), |acc, part| { - format!( - "{acc}{}", - part.format_string_with_widgets(&widget_map, &state) - ) - }); + let output_right = self + .right_parts + .iter_mut() + .fold("".to_owned(), |acc, part| { + format!( + "{acc}{}", + part.format_string_with_widgets(&widget_map, &state) + ) + }); if self.border.enabled { let mut border_top = "".to_owned(); @@ -256,6 +288,7 @@ mod test { bold: true, italic: true, content: "foo".to_owned(), + ..Default::default() }, ) } diff --git a/src/render.rs b/src/render.rs index 048b82d..34aaea5 100644 --- a/src/render.rs +++ b/src/render.rs @@ -6,7 +6,10 @@ use anstyle::{Ansi256Color, AnsiColor, Color, RgbColor, Style}; use regex::Regex; use zellij_tile::prelude::bail; -use crate::{config::ZellijState, widgets::widget::Widget}; +use crate::{ + config::{event_mask_from_widget_name, UpdateEventMask, ZellijState}, + widgets::widget::Widget, +}; lazy_static! { static ref WIDGET_REGEX: Regex = Regex::new("(\\{[a-z_0-9]+\\})").unwrap(); @@ -19,6 +22,9 @@ pub struct FormattedPart { pub bold: bool, pub italic: bool, pub content: String, + pub cache_mask: u8, + pub cached_content: String, + pub cache: BTreeMap<String, String>, } #[cached( @@ -53,7 +59,10 @@ impl FormattedPart { false => format, }; - let mut result = FormattedPart::default(); + let mut result = FormattedPart { + cache_mask: cache_mask_from_content(format), + ..Default::default() + }; let mut format_content_split = format.split(']').collect::<Vec<&str>>(); @@ -113,10 +122,15 @@ impl FormattedPart { } pub fn format_string_with_widgets( - &self, + &mut self, widgets: &BTreeMap<String, Arc<dyn Widget>>, state: &ZellijState, ) -> String { + let skip_cache = self.cache_mask & UpdateEventMask::Always as u8 != 0; + if !skip_cache && self.cache_mask & state.cache_mask == 0 { + return self.cached_content.to_owned(); + } + let mut output = self.content.clone(); for widget in WIDGET_REGEX.captures_iter(&self.content) { @@ -128,15 +142,28 @@ impl FormattedPart { widget_key_name = "command"; } + let widget_mask = event_mask_from_widget_name(widget_key_name); + if !skip_cache && widget_mask & state.cache_mask == 0 { + if let Some(res) = self.cache.get(widget_key) { + output = output.replace(match_name, res); + continue; + } + } + let result = match widgets.get(widget_key_name) { Some(widget) => widget.process(widget_key, state), None => "Use of uninitialized widget".to_owned(), }; + self.cache.insert(widget_key.to_owned(), result.to_owned()); + output = output.replace(match_name, &result); } - self.format_string(&output) + let res = self.format_string(&output); + self.cached_content = res.clone(); + + res } } @@ -148,10 +175,29 @@ impl Default for FormattedPart { bold: false, italic: false, content: "".to_owned(), + cache_mask: 0, + cached_content: "".to_owned(), + cache: BTreeMap::new(), } } } +fn cache_mask_from_content(content: &str) -> u8 { + let mut output = 0; + for widget in WIDGET_REGEX.captures_iter(content) { + let match_name = widget.get(0).unwrap().as_str(); + let widget_key = match_name.trim_matches(|c| c == '{' || c == '}'); + let mut widget_key_name = widget_key; + + if widget_key.starts_with("command_") { + widget_key_name = "command"; + } + + output |= event_mask_from_widget_name(widget_key_name); + } + output +} + fn hex_to_rgb(s: &str) -> anyhow::Result<Vec<u8>> { if s.len() != 6 { bail!("wrong hex color length"); |
