summaryrefslogtreecommitdiffstats
path: root/zellij-utils
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2023-08-09 22:26:00 +0200
committerGitHub <noreply@github.com>2023-08-09 22:26:00 +0200
commit1bedfc90021558cb201695444107afe5bddd2c17 (patch)
tree38dd31b5ab112aa9b1c3a54edb07331013bf7d87 /zellij-utils
parentc3e140cb4b3c0897329bf07ee7f51e9fd402b3df (diff)
feat(plugins): use protocol buffers for serializing across the wasm boundary (#2686)
* work * almost done with command protobuffers * done translating command data structures * mid transferring of every command to protobuff command * transferred plugin_command.rs, now moving on to shim.rs * plugin command working with protobufs * protobuffers in update * protobuf event tests * various TODOs and comments * fix zellij-tile * clean up prost deps * remove version mismatch error * fix panic * some cleanups * clean up event protobuffers * clean up command protobuffers * clean up various protobufs * refactor protobufs * update comments * some transformation fixes * use protobufs for workers * style(fmt): rustfmt * style(fmt): rustfmt * chore(build): add protoc * chore(build): authenticate protoc
Diffstat (limited to 'zellij-utils')
-rw-r--r--zellij-utils/Cargo.toml3
-rwxr-xr-xzellij-utils/assets/plugins/compact-bar.wasmbin526958 -> 526730 bytes
-rwxr-xr-xzellij-utils/assets/plugins/tab-bar.wasmbin497627 -> 497583 bytes
-rw-r--r--zellij-utils/build.rs21
-rw-r--r--zellij-utils/src/data.rs145
-rw-r--r--zellij-utils/src/lib.rs3
-rw-r--r--zellij-utils/src/plugin_api/action.proto246
-rw-r--r--zellij-utils/src/plugin_api/action.rs1304
-rw-r--r--zellij-utils/src/plugin_api/command.proto9
-rw-r--r--zellij-utils/src/plugin_api/command.rs26
-rw-r--r--zellij-utils/src/plugin_api/event.proto162
-rw-r--r--zellij-utils/src/plugin_api/event.rs1059
-rw-r--r--zellij-utils/src/plugin_api/file.proto9
-rw-r--r--zellij-utils/src/plugin_api/file.rs30
-rw-r--r--zellij-utils/src/plugin_api/input_mode.proto40
-rw-r--r--zellij-utils/src/plugin_api/input_mode.rs69
-rw-r--r--zellij-utils/src/plugin_api/key.proto83
-rw-r--r--zellij-utils/src/plugin_api/key.rs222
-rw-r--r--zellij-utils/src/plugin_api/message.proto9
-rw-r--r--zellij-utils/src/plugin_api/message.rs29
-rw-r--r--zellij-utils/src/plugin_api/mod.rs14
-rw-r--r--zellij-utils/src/plugin_api/plugin_command.proto175
-rw-r--r--zellij-utils/src/plugin_api/plugin_command.rs825
-rw-r--r--zellij-utils/src/plugin_api/plugin_ids.proto12
-rw-r--r--zellij-utils/src/plugin_api/plugin_ids.rs35
-rw-r--r--zellij-utils/src/plugin_api/resize.proto24
-rw-r--r--zellij-utils/src/plugin_api/resize.rs130
-rw-r--r--zellij-utils/src/plugin_api/style.proto54
-rw-r--r--zellij-utils/src/plugin_api/style.rs213
29 files changed, 4949 insertions, 2 deletions
diff --git a/zellij-utils/Cargo.toml b/zellij-utils/Cargo.toml
index 65398c532..3e5e2dfd8 100644
--- a/zellij-utils/Cargo.toml
+++ b/zellij-utils/Cargo.toml
@@ -42,6 +42,7 @@ shellexpand = "3.0.0"
uuid = { version = "0.8.2", features = ["serde", "v4"] }
async-channel = "1.8.0"
include_dir = "0.7.3"
+prost = "0.11.9"
#[cfg(not(target_family = "wasm"))]
[target.'cfg(not(target_family = "wasm"))'.dependencies]
@@ -55,6 +56,8 @@ notify-debouncer-full = "0.1.0"
[dev-dependencies]
insta = { version = "1.6.0", features = ["backtrace"] }
+[build-dependencies]
+prost-build = "0.11.9"
[features]
# If this feature is NOT set (default):
diff --git a/zellij-utils/assets/plugins/compact-bar.wasm b/zellij-utils/assets/plugins/compact-bar.wasm
index bd878f2a8..f38c500fc 100755
--- a/zellij-utils/assets/plugins/compact-bar.wasm
+++ b/zellij-utils/assets/plugins/compact-bar.wasm
Binary files differ
diff --git a/zellij-utils/assets/plugins/tab-bar.wasm b/zellij-utils/assets/plugins/tab-bar.wasm
index 33bf1a44c..1a2919f6f 100755
--- a/zellij-utils/assets/plugins/tab-bar.wasm
+++ b/zellij-utils/assets/plugins/tab-bar.wasm
Binary files differ
diff --git a/zellij-utils/build.rs b/zellij-utils/build.rs
new file mode 100644
index 000000000..92f89d27c
--- /dev/null
+++ b/zellij-utils/build.rs
@@ -0,0 +1,21 @@
+use prost_build;
+use std::fs;
+
+fn main() {
+ let mut prost_build = prost_build::Config::new();
+ prost_build.include_file("generated_plugin_api.rs");
+ let mut proto_files = vec![];
+ for entry in fs::read_dir("src/plugin_api").unwrap() {
+ let entry_path = entry.unwrap().path();
+ if entry_path.is_file() {
+ if let Some(extension) = entry_path.extension() {
+ if extension == "proto" {
+ proto_files.push(entry_path.display().to_string())
+ }
+ }
+ }
+ }
+ prost_build
+ .compile_protos(&proto_files, &["src/plugin_api"])
+ .unwrap();
+}
diff --git a/zellij-utils/src/data.rs b/zellij-utils/src/data.rs
index a12821c42..9c1c8e2f6 100644
--- a/zellij-utils/src/data.rs
+++ b/zellij-utils/src/data.rs
@@ -2,9 +2,9 @@ use crate::input::actions::Action;
use crate::input::config::ConversionError;
use clap::ArgEnum;
use serde::{Deserialize, Serialize};
-use std::collections::HashMap;
+use std::collections::{HashMap, HashSet};
use std::fmt;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
use std::str::FromStr;
use strum_macros::{EnumDiscriminants, EnumIter, EnumString, ToString};
@@ -810,3 +810,144 @@ pub enum CopyDestination {
Primary,
System,
}
+
+#[derive(Debug, Default, Clone)]
+pub struct FileToOpen {
+ pub path: PathBuf,
+ pub line_number: Option<usize>,
+ pub cwd: Option<PathBuf>,
+}
+
+impl FileToOpen {
+ pub fn new<P: AsRef<Path>>(path: P) -> Self {
+ FileToOpen {
+ path: path.as_ref().to_path_buf(),
+ ..Default::default()
+ }
+ }
+ pub fn with_line_number(mut self, line_number: usize) -> Self {
+ self.line_number = Some(line_number);
+ self
+ }
+ pub fn with_cwd(mut self, cwd: PathBuf) -> Self {
+ self.cwd = Some(cwd);
+ self
+ }
+}
+
+#[derive(Debug, Default, Clone)]
+pub struct CommandToRun {
+ pub path: PathBuf,
+ pub args: Vec<String>,
+ pub cwd: Option<PathBuf>,
+}
+
+impl CommandToRun {
+ pub fn new<P: AsRef<Path>>(path: P) -> Self {
+ CommandToRun {
+ path: path.as_ref().to_path_buf(),
+ ..Default::default()
+ }
+ }
+ pub fn new_with_args<P: AsRef<Path>, A: AsRef<str>>(path: P, args: Vec<A>) -> Self {
+ CommandToRun {
+ path: path.as_ref().to_path_buf(),
+ args: args.into_iter().map(|a| a.as_ref().to_owned()).collect(),
+ ..Default::default()
+ }
+ }
+}
+
+#[derive(Debug, Default, Clone)]
+pub struct PluginMessage {
+ pub name: String,
+ pub payload: String,
+ pub worker_name: Option<String>,
+}
+
+impl PluginMessage {
+ pub fn new_to_worker(worker_name: &str, message: &str, payload: &str) -> Self {
+ PluginMessage {
+ name: message.to_owned(),
+ payload: payload.to_owned(),
+ worker_name: Some(worker_name.to_owned()),
+ }
+ }
+ pub fn new_to_plugin(message: &str, payload: &str) -> Self {
+ PluginMessage {
+ name: message.to_owned(),
+ payload: payload.to_owned(),
+ worker_name: None,
+ }
+ }
+}
+
+#[derive(Debug, Clone)]
+pub enum PluginCommand {
+ Subscribe(HashSet<EventType>),
+ Unsubscribe(HashSet<EventType>),
+ SetSelectable(bool),
+ GetPluginIds,
+ GetZellijVersion,
+ OpenFile(FileToOpen),
+ OpenFileFloating(FileToOpen),
+ OpenTerminal(FileToOpen), // only used for the path as cwd
+ OpenTerminalFloating(FileToOpen), // only used for the path as cwd
+ OpenCommandPane(CommandToRun),
+ OpenCommandPaneFloating(CommandToRun),
+ SwitchTabTo(u32), // tab index
+ SetTimeout(f32), // seconds
+ ExecCmd(Vec<String>),
+ PostMessageTo(PluginMessage),
+ PostMessageToPlugin(PluginMessage),
+ HideSelf,
+ ShowSelf(bool), // bool - should float if hidden
+ SwitchToMode(InputMode),
+ NewTabsWithLayout(String), // raw kdl layout
+ NewTab,
+ GoToNextTab,
+ GoToPreviousTab,
+ Resize(Resize),
+ ResizeWithDirection(ResizeStrategy),
+ FocusNextPane,
+ FocusPreviousPane,
+ MoveFocus(Direction),
+ MoveFocusOrTab(Direction),
+ Detach,
+ EditScrollback,
+ Write(Vec<u8>), // bytes
+ WriteChars(String),
+ ToggleTab,
+ MovePane,
+ MovePaneWithDirection(Direction),
+ ClearScreen,
+ ScrollUp,
+ ScrollDown,
+ ScrollToTop,
+ ScrollToBottom,
+ PageScrollUp,
+ PageScrollDown,
+ ToggleFocusFullscreen,
+ TogglePaneFrames,
+ TogglePaneEmbedOrEject,
+ UndoRenamePane,
+ CloseFocus,
+ ToggleActiveTabSync,
+ CloseFocusedTab,
+ UndoRenameTab,
+ QuitZellij,
+ PreviousSwapLayout,
+ NextSwapLayout,
+ GoToTabName(String),
+ FocusOrCreateTab(String),
+ GoToTab(u32), // tab index
+ StartOrReloadPlugin(String), // plugin url (eg. file:/path/to/plugin.wasm)
+ CloseTerminalPane(u32), // terminal pane id
+ ClosePluginPane(u32), // plugin pane id
+ FocusTerminalPane(u32, bool), // terminal pane id, should_float_if_hidden
+ FocusPluginPane(u32, bool), // plugin pane id, should_float_if_hidden
+ RenameTerminalPane(u32, String), // terminal pane id, new name
+ RenamePluginPane(u32, String), // plugin pane id, new name
+ RenameTab(u32, String), // tab index, new name
+ ReportPanic(String), // stringified panic
+}
diff --git a/zellij-utils/src/lib.rs b/zellij-utils/src/lib.rs
index b07fe8bdc..c9b3581d0 100644
--- a/zellij-utils/src/lib.rs
+++ b/zellij-utils/src/lib.rs
@@ -6,6 +6,7 @@ pub mod errors;
pub mod input;
pub mod kdl;
pub mod pane_size;
+pub mod plugin_api;
pub mod position;
pub mod setup;
pub mod shared;
@@ -23,3 +24,5 @@ pub use ::{
anyhow, async_channel, async_std, clap, interprocess, lazy_static, libc, miette, nix,
notify_debouncer_full, regex, serde, signal_hook, tempfile, termwiz, vte,
};
+
+pub use ::prost;
diff --git a/zellij-utils/src/plugin_api/action.proto b/zellij-utils/src/plugin_api/action.proto
new file mode 100644
index 000000000..05fa5c6ed
--- /dev/null
+++ b/zellij-utils/src/plugin_api/action.proto
@@ -0,0 +1,246 @@
+syntax = "proto3";
+
+import "input_mode.proto";
+import "resize.proto";
+
+package api.action;
+
+message Action {
+ ActionName name = 1;
+ oneof optional_payload {
+ SwitchToModePayload switch_to_mode_payload = 2;
+ WritePayload write_payload = 3;
+ WriteCharsPayload write_chars_payload = 4;
+ SwitchToModePayload switch_mode_for_all_clients_payload = 5;
+ resize.Resize resize_payload = 6;
+ resize.ResizeDirection move_focus_payload = 7;
+ resize.ResizeDirection move_focus_or_tab_payload = 8;
+ MovePanePayload move_pane_payload = 9;
+ DumpScreenPayload dump_screen_payload = 10;
+ ScrollAtPayload scroll_up_at_payload = 11;
+ ScrollAtPayload scroll_down_at_payload = 12;
+ NewPanePayload new_pane_payload = 13;
+ EditFilePayload edit_file_payload = 14;
+ NewFloatingPanePayload new_floating_pane_payload = 15;
+ NewTiledPanePayload new_tiled_pane_payload = 16;
+ bytes pane_name_input_payload = 17;
+ uint32 go_to_tab_payload = 18;
+ GoToTabNamePayload go_to_tab_name_payload = 19;
+ bytes tab_name_input_payload = 20;
+ RunCommandAction run_payload = 21;
+ Position left_click_payload = 22;
+ Position right_click_payload = 23;
+ Position middle_click_payload = 24;
+ LaunchOrFocusPluginPayload launch_or_focus_plugin_payload = 25;
+ Position left_mouse_release_payload = 26;
+ Position right_mouse_release_payload = 27;
+ Position middle_mouse_release_payload = 28;
+ Position mouse_hold_left_payload = 29;
+ Position mouse_hold_right_payload = 30;
+ Position mouse_hold_middle_payload = 31;
+ bytes search_input_payload = 32;
+ SearchDirection search_payload = 33;
+ SearchOption search_toggle_option_payload = 34;
+ NewPluginPanePayload new_tiled_plugin_pane_payload = 35;
+ NewPluginPanePayload new_floating_plugin_pane_payload = 36;
+ string start_or_reload_plugin_payload = 37;
+ uint32 close_terminal_pane_payload = 38;
+ uint32 close_plugin_pane_payload = 39;
+ PaneIdAndShouldFloat focus_terminal_pane_with_id_payload = 40;
+ PaneIdAndShouldFloat focus_plugin_pane_with_id_payload = 41;
+ IdAndName rename_terminal_pane_payload = 42;
+ IdAndName rename_plugin_pane_payload = 43;
+ IdAndName rename_tab_payload = 44;
+ }
+}
+
+message IdAndName {
+ bytes name = 1;
+ uint32 id = 2;
+}
+
+message PaneIdAndShouldFloat {
+ uint32 pane_id = 1;
+ bool should_float_if_hidden = 2;
+}
+
+message NewPluginPanePayload {
+ string plugin_url = 1;
+ optional string pane_name = 2;
+}
+
+enum SearchDirection {
+ Up = 0;
+ Down = 1;
+}
+
+enum SearchOption {
+ CaseSensitivity = 0;
+ WholeWord = 1;
+ Wrap = 2;
+}
+
+message LaunchOrFocusPluginPayload {
+ string plugin_url = 1;
+ bool should_float = 2;
+ optional PluginConfiguration plugin_configuration = 3;
+}
+
+message GoToTabNamePayload {
+ string tab_name = 1;
+ bool create = 2;
+}
+
+message NewFloatingPanePayload {
+ optional RunCommandAction command = 1;
+}
+
+message NewTiledPanePayload {
+ optional RunCommandAction command = 1;
+ optional resize.ResizeDirection direction = 2;
+}
+
+message MovePanePayload {
+ optional resize.ResizeDirection direction = 1;
+}
+
+message EditFilePayload {
+ string file_to_edit = 1;
+ optional uint32 line_number = 2;
+ optional string cwd = 3;
+ optional resize.ResizeDirection direction = 4;
+ bool should_float = 5;
+}
+
+message ScrollAtPayload {
+ Position position = 1;
+}
+
+message NewPanePayload {
+ optional resize.ResizeDirection direction = 1;
+ optional string pane_name = 2;
+}
+
+message SwitchToModePayload {
+ input_mode.InputMode input_mode = 1;
+}
+
+message WritePayload {
+ bytes bytes_to_write = 1;
+}
+
+message WriteCharsPayload {
+ string chars = 1;
+}
+
+message DumpScreenPayload {
+ string file_path = 1;
+ bool include_scrollback = 2;
+}
+
+enum ActionName {
+ Quit = 0;
+ Write = 1;
+ WriteChars = 2;
+ SwitchToMode = 3;
+ SwitchModeForAllClients = 4;
+ Resize = 5;
+ FocusNextPane = 6;
+ FocusPreviousPane = 7;
+ SwitchFocus = 8;
+ MoveFocus = 9;
+ MoveFocusOrTab = 10;
+ MovePane = 11;
+ MovePaneBackwards = 12;
+ ClearScreen = 13;
+ DumpScreen = 14;
+ EditScrollback = 15;
+ ScrollUp = 16;
+ ScrollUpAt = 17;
+ ScrollDown = 18;
+ ScrollDownAt = 19;
+ ScrollToBottom = 20;
+ ScrollToTop = 21;
+ PageScrollUp = 22;
+ PageScrollDown = 23;
+ HalfPageScrollUp = 24;
+ HalfPageScrollDown = 25;
+ ToggleFocusFullscreen = 26;
+ TogglePaneFrames = 27;
+ ToggleActiveSyncTab = 28;
+ NewPane = 29;
+ EditFile = 30;
+ NewFloatingPane = 31;
+ NewTiledPane = 32;
+ TogglePaneEmbedOrFloating = 33;
+ ToggleFloatingPanes = 34;
+ CloseFocus = 35;
+ PaneNameInput = 36;
+ UndoRenamePane = 37;
+ NewTab = 38;
+ NoOp = 39;
+ GoToNextTab = 40;
+ GoToPreviousTab = 41;
+ CloseTab = 42;
+ GoToTab = 43;
+ GoToTabName = 44;
+ ToggleTab = 45;
+ TabNameInput = 46;
+ UndoRenameTab = 47;
+ Run = 48;
+ Detach = 49;
+ LeftClick = 50;
+ RightClick = 51;
+ MiddleClick = 52;
+ LaunchOrFocusPlugin = 53;
+ LeftMouseRelease = 54;
+ RightMouseRelease = 55;
+ MiddleMouseRelease = 56;
+ MouseHoldLeft = 57;
+ MouseHoldRight = 58;
+ MouseHoldMiddle = 59;
+ SearchInput = 60;
+ Search = 61;
+ SearchToggleOption = 62;
+ ToggleMouseMode = 63;
+ PreviousSwapLayout = 64;
+ NextSwapLayout = 65;
+ QueryTabNames = 66;
+ NewTiledPluginPane = 67;
+ NewFloatingPluginPane = 68;
+ StartOrReloadPlugin = 69;
+ CloseTerminalPane = 70;
+ ClosePluginPane = 71;
+ FocusTerminalPaneWithId = 72;
+ FocusPluginPaneWithId = 73;
+ RenameTerminalPane = 74;
+ RenamePluginPane = 75;
+ RenameTab = 76;
+ BreakPane = 77;
+ BreakPaneRight = 78;
+ BreakPaneLeft = 79;
+}
+
+message Position {
+ int64 line = 1;
+ int64 column = 2;
+}
+
+message RunCommandAction {
+ string command = 1;
+ repeated string args = 2;
+ optional string cwd = 3;
+ optional resize.ResizeDirection direction = 4;
+ optional string pane_name = 5;
+ bool hold_on_close = 6;
+ bool hold_on_start = 7;
+}
+
+message PluginConfiguration {
+ repeated NameAndValue name_and_value = 1;
+}
+
+message NameAndValue {
+ string name = 1;
+ string value = 2;
+}
diff --git a/zellij-utils/src/plugin_api/action.rs b/zellij-utils/src/plugin_api/action.rs
new file mode 100644
index 000000000..1a964fa9b
--- /dev/null
+++ b/zellij-utils/src/plugin_api/action.rs
@@ -0,0 +1,1304 @@
+pub use super::generated_api::api::{
+ action::{
+ action::OptionalPayload, Action as ProtobufAction, ActionName as ProtobufActionName,
+ DumpScreenPayload, EditFilePayload, GoToTabNamePayload, IdAndName,
+ LaunchOrFocusPluginPayload, MovePanePayload, NameAndValue as ProtobufNameAndValue,
+ NewFloatingPanePayload, NewPanePayload, NewPluginPanePayload, NewTiledPanePayload,
+ PaneIdAndShouldFloat, PluginConfiguration as ProtobufPluginConfiguration,
+ Position as ProtobufPosition, RunCommandAction as ProtobufRunCommandAction,
+ ScrollAtPayload, SearchDirection as ProtobufSearchDirection,
+ SearchOption as ProtobufSearchOption, SwitchToModePayload, WriteCharsPayload, WritePayload,
+ },
+ input_mode::InputMode as ProtobufInputMode,
+ resize::{Resize as ProtobufResize, ResizeDirection as ProtobufResizeDirection},
+};
+use crate::data::{Direction, InputMode, ResizeStrategy};
+use crate::errors::prelude::*;
+use crate::input::actions::Action;
+use crate::input::actions::{SearchDirection, SearchOption};
+use crate::input::command::RunCommandAction;
+use crate::input::layout::{PluginUserConfiguration, RunPlugin, RunPluginLocation};
+use crate::position::Position;
+use url::Url;
+
+use std::collections::BTreeMap;
+use std::convert::TryFrom;
+use std::path::PathBuf;
+
+impl TryFrom<ProtobufAction> for Action {
+ type Error = &'static str;
+ fn try_from(protobuf_action: ProtobufAction) -> Result<Self, &'static str> {
+ match ProtobufActionName::from_i32(protobuf_action.name) {
+ Some(ProtobufActionName::Quit) => match protobuf_action.optional_payload {
+ Some(_) => Err("The Quit Action should not have a payload"),
+ None => Ok(Action::Quit),
+ },
+ Some(ProtobufActionName::Write) => match protobuf_action.optional_payload {
+ Some(OptionalPayload::WritePayload(write_payload)) => {
+ Ok(Action::Write(write_payload.bytes_to_write))
+ },
+ _ => Err("Wrong payload for Action::Write"),
+ },
+ Some(ProtobufActionName::WriteChars) => match protobuf_action.optional_payload {
+ Some(OptionalPayload::WriteCharsPayload(write_chars_payload)) => {
+ Ok(Action::WriteChars(write_chars_payload.chars))
+ },
+ _ => Err("Wrong payload for Action::WriteChars"),
+ },
+ Some(ProtobufActionName::SwitchToMode) => match protobuf_action.optional_payload {
+ Some(OptionalPayload::SwitchToModePayload(switch_to_mode_payload)) => {
+ let input_mode: InputMode =
+ ProtobufInputMode::from_i32(switch_to_mode_payload.input_mode)
+ .ok_or("Malformed input mode for SwitchToMode Action")?
+ .try_into()?;
+ Ok(Action::SwitchToMode(input_mode))
+ },
+ _ => Err("Wrong payload for Action::SwitchToModePayload"),
+ },
+ Some(ProtobufActionName::SwitchModeForAllClients) => {
+ match protobuf_action.optional_payload {
+ Some(OptionalPayload::SwitchModeForAllClientsPayload(
+ switch_to_mode_payload,
+ )) => {
+ let input_mode: InputMode =
+ ProtobufInputMode::from_i32(switch_to_mode_payload.input_mode)
+ .ok_or("Malformed input mode fo