summaryrefslogtreecommitdiffstats
path: root/zellij-tile/src
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2023-05-16 12:47:18 +0200
committerGitHub <noreply@github.com>2023-05-16 12:47:18 +0200
commit5fe4d60c220c872c1e77a7ddf24fec6686c28e95 (patch)
treeb6abec3006de7cd2eaecee149005d55ee4671a6b /zellij-tile/src
parent4b7d7c34b72e67168a2ec53b27776047ccddf522 (diff)
feat(plugins): Plugin workers and strider (#2449)
* mvp of strider fuzzy find * improve search ui * various refactoringz * moar refactoring * even more refactoring * tests and more refactoring * refactor: remove unused stuff * style(fmt): rustfmt * debug ci * debug ci * correct path for plugin system tests * fix plugin system ci tests * remove debugging statements from test * fix plugin worker persistence * add test for plugin worker persistence * style(fmt): rustfmt * final cleanups * remove outdated comments
Diffstat (limited to 'zellij-tile/src')
-rw-r--r--zellij-tile/src/lib.rs68
-rw-r--r--zellij-tile/src/shim.rs26
2 files changed, 94 insertions, 0 deletions
diff --git a/zellij-tile/src/lib.rs b/zellij-tile/src/lib.rs
index 800b6d684..685de4afe 100644
--- a/zellij-tile/src/lib.rs
+++ b/zellij-tile/src/lib.rs
@@ -1,6 +1,7 @@
pub mod prelude;
pub mod shim;
+use serde::{Deserialize, Serialize};
use zellij_utils::data::Event;
#[allow(unused_variables)]
@@ -12,6 +13,12 @@ pub trait ZellijPlugin {
fn render(&mut self, rows: usize, cols: usize) {}
}
+#[allow(unused_variables)]
+// TODO: can we get rid of the lifetime? maybe with generics?
+pub trait ZellijWorker<'de>: Default + Serialize + Deserialize<'de> {
+ fn on_message(&mut self, message: String, payload: String) {}
+}
+
pub const PLUGIN_MISMATCH: &str =
"An error occured in a plugin while receiving an Event from zellij. This means
that the plugins aren't compatible with the current zellij version.
@@ -36,7 +43,10 @@ macro_rules! register_plugin {
std::panic::set_hook(Box::new(|info| {
report_panic(info);
}));
+ }
+ #[no_mangle]
+ fn load() {
STATE.with(|state| {
state.borrow_mut().load();
});
@@ -65,3 +75,61 @@ macro_rules! register_plugin {
}
};
}
+
+#[macro_export]
+macro_rules! register_worker {
+ ($worker:ty, $worker_name:ident) => {
+ #[no_mangle]
+ pub fn $worker_name() {
+ use serde_json::*;
+ let worker_display_name = std::stringify!($worker_name);
+
+ // read message from STDIN
+ let (message, payload): (String, String) = $crate::shim::object_from_stdin()
+ .unwrap_or_else(|e| {
+ eprintln!(
+ "Failed to deserialize message to worker \"{}\": {:?}",
+ worker_display_name, e
+ );
+ Default::default()
+ });
+
+ // read previous worker state from HD if it exists
+ let mut worker_instance = match std::fs::read(&format!("/data/{}", worker_display_name))
+ .map_err(|e| format!("Failed to read file: {:?}", e))
+ .and_then(|s| {
+ serde_json::from_str::<$worker>(&String::from_utf8_lossy(&s))
+ .map_err(|e| format!("Failed to deserialize: {:?}", e))
+ }) {
+ Ok(s) => s,
+ Err(e) => {
+ eprintln!(
+ "Failed to read existing state ({:?}), creating new state for worker",
+ e
+ );
+ <$worker>::default()
+ },
+ };
+
+ // invoke worker
+ worker_instance.on_message(message, payload);
+
+ // persist worker state to HD for next run
+ match serde_json::to_string(&worker_instance)
+ .map_err(|e| format!("Failed to serialize worker state"))
+ .and_then(|serialized_state| {
+ std::fs::write(
+ &format!("/data/{}", worker_display_name),
+ serialized_state.as_bytes(),
+ )
+ .map_err(|e| format!("Failed to persist state to HD: {:?}", e))
+ }) {
+ Ok(()) => {},
+ Err(e) => eprintln!(
+ "Failed to serialize and persist worker state to hd: {:?}",
+ e
+ ),
+ }
+ }
+ };
+}
diff --git a/zellij-tile/src/shim.rs b/zellij-tile/src/shim.rs
index 0aa8d3e0e..f1c1fb54d 100644
--- a/zellij-tile/src/shim.rs
+++ b/zellij-tile/src/shim.rs
@@ -39,6 +39,11 @@ pub fn open_file(path: &Path) {
unsafe { host_open_file() };
}
+pub fn open_file_with_line(path: &Path, line: usize) {
+ object_to_stdout(&(path, line));
+ unsafe { host_open_file_with_line() };
+}
+
pub fn switch_tab_to(tab_idx: u32) {
unsafe { host_switch_tab_to(tab_idx) };
}
@@ -74,6 +79,24 @@ pub fn object_to_stdout(object: &impl Serialize) {
println!("{}", serde_json::to_string(object).unwrap());
}
+#[doc(hidden)]
+pub fn post_message_to(worker_name: &str, message: String, payload: String) {
+ match serde_json::to_string(&(worker_name, message, payload)) {
+ Ok(serialized) => println!("{}", serialized),
+ Err(e) => eprintln!("Failed to serialize message: {:?}", e),
+ }
+ unsafe { host_post_message_to() };
+}
+
+#[doc(hidden)]
+pub fn post_message_to_plugin(message: String, payload: String) {
+ match serde_json::to_string(&(message, payload)) {
+ Ok(serialized) => println!("{}", serialized),
+ Err(e) => eprintln!("Failed to serialize message: {:?}", e),
+ }
+ unsafe { host_post_message_to_plugin() };
+}
+
#[link(wasm_import_module = "zellij")]
extern "C" {
fn host_subscribe();
@@ -82,8 +105,11 @@ extern "C" {
fn host_get_plugin_ids();
fn host_get_zellij_version();
fn host_open_file();
+ fn host_open_file_with_line();
fn host_switch_tab_to(tab_idx: u32);
fn host_set_timeout(secs: f64);
fn host_exec_cmd();
fn host_report_panic();
+ fn host_post_message_to();
+ fn host_post_message_to_plugin();
}