diff options
| author | Daniel Jankowski <daniel.jankowski@rub.de> | 2025-01-18 09:32:18 +0100 |
|---|---|---|
| committer | Daniel Jankowski <daniel.jankowski@rub.de> | 2025-01-18 09:34:07 +0100 |
| commit | f73635159598119a67533fda394e49830506cd85 (patch) | |
| tree | 78f3c2b0052af68d4bdcd8b31e548af613d34814 /src | |
| parent | chore: update cargo deps (diff) | |
| download | sl0pstatus-f73635159598119a67533fda394e49830506cd85.tar.gz sl0pstatus-f73635159598119a67533fda394e49830506cd85.tar.xz sl0pstatus-f73635159598119a67533fda394e49830506cd85.zip | |
feat: add pipe widget
Diffstat (limited to 'src')
| -rw-r--r-- | src/bin/zjstatus.rs | 3 | ||||
| -rw-r--r-- | src/config.rs | 6 | ||||
| -rw-r--r-- | src/pipe.rs | 16 | ||||
| -rw-r--r-- | src/render.rs | 13 | ||||
| -rw-r--r-- | src/widgets/mod.rs | 1 | ||||
| -rw-r--r-- | src/widgets/pipe.rs | 97 |
6 files changed, 132 insertions, 4 deletions
diff --git a/src/bin/zjstatus.rs b/src/bin/zjstatus.rs index 30a40b0..c4d5267 100644 --- a/src/bin/zjstatus.rs +++ b/src/bin/zjstatus.rs @@ -12,6 +12,7 @@ use zjstatus::{ datetime::DateTimeWidget, mode::ModeWidget, notification::NotificationWidget, + pipe::PipeWidget, session::SessionWidget, swap_layout::SwapLayoutWidget, tabs::TabsWidget, @@ -90,6 +91,7 @@ impl ZellijPlugin for State { self.state = ZellijState { cols: 0, command_results: BTreeMap::new(), + pipe_results: BTreeMap::new(), mode: ModeInfo::default(), panes: PaneManifest::default(), plugin_uuid: uid.to_string(), @@ -307,6 +309,7 @@ fn register_widgets(configuration: &BTreeMap<String, String>) -> BTreeMap<String "datetime".to_owned(), Arc::new(DateTimeWidget::new(configuration)), ); + widget_map.insert("pipe".to_owned(), Arc::new(PipeWidget::new(configuration))); widget_map.insert( "swap_layout".to_owned(), Arc::new(SwapLayoutWidget::new(configuration)), diff --git a/src/config.rs b/src/config.rs index f0befbb..0bb260d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -15,6 +15,7 @@ use chrono::{DateTime, Local}; pub struct ZellijState { pub cols: usize, pub command_results: BTreeMap<String, CommandResult>, + pub pipe_results: BTreeMap<String, String>, pub mode: ModeInfo, pub panes: PaneManifest, pub plugin_uuid: String, @@ -63,6 +64,7 @@ pub fn event_mask_from_widget_name(name: &str) -> u8 { "session" => UpdateEventMask::Mode as u8, "swap_layout" => UpdateEventMask::Tab as u8, "tabs" => UpdateEventMask::Tab as u8, + "pipe" => UpdateEventMask::Always as u8, _ => UpdateEventMask::None as u8, } } @@ -278,6 +280,10 @@ impl ModuleConfig { widget_key_name = "command"; } + if widget_key.starts_with("pipe_") { + widget_key_name = "pipe"; + } + if !tokens.contains(&widget_key_name.to_owned()) { continue; } diff --git a/src/pipe.rs b/src/pipe.rs index f88db89..38fea5d 100644 --- a/src/pipe.rs +++ b/src/pipe.rs @@ -67,12 +67,28 @@ fn process_line(state: &mut ZellijState, line: &str) -> bool { should_render = true; } + "pipe" => { + if parts.len() < 4 { + return false; + } + + pipe(state, parts[2], parts[3]); + + should_render = true; + } _ => {} } should_render } +fn pipe(state: &mut ZellijState, name: &str, content: &str) { + tracing::debug!("saving pipe result {name} {content}"); + state + .pipe_results + .insert(name.to_owned(), content.to_owned()); +} + fn notify(state: &mut ZellijState, message: &str) { state.incoming_notification = Some(notification::Message { body: message.to_string(), diff --git a/src/render.rs b/src/render.rs index a9f55ef..6ef0005 100644 --- a/src/render.rs +++ b/src/render.rs @@ -205,6 +205,10 @@ impl FormattedPart { widget_key_name = "command"; } + if widget_key.starts_with("pipe_") { + widget_key_name = "pipe"; + } + let widget_mask = event_mask_from_widget_name(widget_key_name); let skip_widget_cache = widget_mask & UpdateEventMask::Always as u8 != 0; if !skip_widget_cache && widget_mask & state.cache_mask == 0 { @@ -278,6 +282,10 @@ fn cache_mask_from_content(content: &str) -> u8 { widget_key_name = "command"; } + if widget_key.starts_with("pipe_") { + widget_key_name = "pipe"; + } + output |= event_mask_from_widget_name(widget_key_name); } output @@ -304,10 +312,7 @@ fn parse_color(color: &str, config: &BTreeMap<String, String>) -> Option<Color> if color.starts_with('$') { let alias_name = color.strip_prefix('$').unwrap(); - color = match config.get(&format!("color_{alias_name}")) { - Some(color_str) => color_str, - None => return None, - }; + color = config.get(&format!("color_{alias_name}"))?; } if color.starts_with('#') { diff --git a/src/widgets/mod.rs b/src/widgets/mod.rs index edbf868..aa60cc3 100644 --- a/src/widgets/mod.rs +++ b/src/widgets/mod.rs @@ -2,6 +2,7 @@ pub mod command; pub mod datetime; pub mod mode; pub mod notification; +pub mod pipe; pub mod session; pub mod swap_layout; pub mod tabs; diff --git a/src/widgets/pipe.rs b/src/widgets/pipe.rs new file mode 100644 index 0000000..f6acf1a --- /dev/null +++ b/src/widgets/pipe.rs @@ -0,0 +1,97 @@ +use lazy_static::lazy_static; +use regex::Regex; +use std::collections::BTreeMap; + +use crate::render::FormattedPart; + +use super::widget::Widget; + +lazy_static! { + static ref PIPE_REGEX: Regex = Regex::new("_[a-zA-Z0-9]+$").unwrap(); +} + +pub struct PipeWidget { + config: BTreeMap<String, PipeConfig>, +} + +#[derive(Clone)] +struct PipeConfig { + format: Vec<FormattedPart>, +} + +impl PipeWidget { + pub fn new(config: &BTreeMap<String, String>) -> Self { + Self { + config: parse_config(config), + } + } +} + +impl Widget for PipeWidget { + fn process(&self, name: &str, state: &crate::config::ZellijState) -> String { + let pipe_config = match self.config.get(name) { + Some(pc) => pc, + None => { + tracing::debug!("pipe no name {name}"); + return "".to_owned(); + } + }; + + let pipe_result = match state.pipe_results.get(name) { + Some(pr) => pr, + None => { + tracing::debug!("pipe no content {name}"); + return "".to_owned(); + } + }; + + pipe_config + .format + .iter() + .map(|f| { + let mut content = f.content.clone(); + + if content.contains("{output}") { + content = content.replace( + "{output}", + pipe_result.strip_suffix('\n').unwrap_or(pipe_result), + ) + } + + (f, content) + }) + .fold("".to_owned(), |acc, (f, content)| { + format!("{acc}{}", f.format_string(&content)) + }) + } + + fn process_click(&self, _name: &str, _state: &crate::config::ZellijState, _pos: usize) {} +} + +fn parse_config(zj_conf: &BTreeMap<String, String>) -> BTreeMap<String, PipeConfig> { + let mut keys: Vec<String> = zj_conf + .keys() + .filter(|k| k.starts_with("pipe_")) + .cloned() + .collect(); + keys.sort(); + + let mut config: BTreeMap<String, PipeConfig> = BTreeMap::new(); + + for key in keys { + let pipe_name = PIPE_REGEX.replace(&key, "").to_string(); + let mut pipe_conf = PipeConfig { format: vec![] }; + + if let Some(existing_conf) = config.get(pipe_name.as_str()) { + pipe_conf = existing_conf.clone(); + } + + if key.ends_with("format") { + pipe_conf.format = + FormattedPart::multiple_from_format_string(zj_conf.get(&key).unwrap(), zj_conf); + } + + config.insert(pipe_name, pipe_conf); + } + config +} |
