aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Jankowski <daniel.jankowski@rub.de>2023-12-26 13:30:50 +0100
committerDaniel Jankowski <daniel.jankowski@rub.de>2023-12-26 13:30:50 +0100
commit340a1861dd41fb73715a6417da5adb4ff0b9d851 (patch)
treebcb96d9f3c50766601850cc2e0306901f3dbf28d
parentchore: add conky config to examples (diff)
downloadsl0pstatus-340a1861dd41fb73715a6417da5adb4ff0b9d851.tar.gz
sl0pstatus-340a1861dd41fb73715a6417da5adb4ff0b9d851.tar.xz
sl0pstatus-340a1861dd41fb73715a6417da5adb4ff0b9d851.zip
feat: render only widgets that needs an update
-rw-r--r--benches/benches.rs5
-rw-r--r--plugin-dev-workspace.kdl2
-rw-r--r--src/bin/zjstatus.rs7
-rw-r--r--src/config.rs65
-rw-r--r--src/render.rs54
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");