zellij/zellij-tile/src/lib.rs
Aram Drevekenin bcbd940bf9
feat(plugins): plugin pane state events (#2545)
* feat(plugins): report pane state to plugins

* refactor(plugins): rename some stuff

* tests(plugins): adjust for new behavior

* style(fmt): rustfmt
2023-06-15 17:07:40 +02:00

106 lines
3.3 KiB
Rust

pub mod prelude;
pub mod shim;
use serde::{Deserialize, Serialize};
use zellij_utils::data::Event;
#[allow(unused_variables)]
pub trait ZellijPlugin: Default {
fn load(&mut self) {}
fn update(&mut self, event: Event) -> bool {
false
} // return true if it should render
fn render(&mut self, rows: usize, cols: usize) {}
}
#[allow(unused_variables)]
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.
The most likely explanation for this is that you're running either a
self-compiled zellij or plugin version. Please make sure that, while developing,
you also rebuild the plugins in order to pick up changes to the plugin code.
Please refer to the documentation for further information:
https://github.com/zellij-org/zellij/blob/main/CONTRIBUTING.md#building
";
#[macro_export]
macro_rules! register_plugin {
($t:ty) => {
thread_local! {
static STATE: std::cell::RefCell<$t> = std::cell::RefCell::new(Default::default());
}
fn main() {
// Register custom panic handler
std::panic::set_hook(Box::new(|info| {
report_panic(info);
}));
}
#[no_mangle]
fn load() {
STATE.with(|state| {
state.borrow_mut().load();
});
}
#[no_mangle]
pub fn update() -> bool {
STATE.with(|state| {
let object = $crate::shim::object_from_stdin()
.context($crate::PLUGIN_MISMATCH)
.to_stdout()
.unwrap();
state.borrow_mut().update(object)
})
}
#[no_mangle]
pub fn render(rows: i32, cols: i32) {
STATE.with(|state| {
state.borrow_mut().render(rows as usize, cols as usize);
});
}
#[no_mangle]
pub fn plugin_version() {
println!("{}", $crate::prelude::VERSION);
}
};
}
#[macro_export]
macro_rules! register_worker {
($worker:ty, $worker_name:ident, $worker_static_name:ident) => {
// persist worker state in memory in a static variable
thread_local! {
static $worker_static_name: std::cell::RefCell<$worker> = std::cell::RefCell::new(Default::default());
}
#[no_mangle]
pub fn $worker_name() {
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()
});
$worker_static_name.with(|worker_instance| {
let mut worker_instance = worker_instance.borrow_mut();
worker_instance.on_message(message, payload);
});
}
};
}