aboutsummaryrefslogtreecommitdiffstats
path: root/zellij-utils/src/plugin_api
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2025-06-23 19:19:37 +0200
committerGitHub <noreply@github.com>2025-06-23 19:19:37 +0200
commitc5ac7968809ddb1033b625562eae22019cccc2f4 (patch)
tree932cf07d898dfbcc6ec6a9d4cf5353c06a47accc /zellij-utils/src/plugin_api
parentfeat(ui): add optional tooltip with key hints to the compact bar (#4225) (diff)
downloadsl0ppij-c5ac7968809ddb1033b625562eae22019cccc2f4.tar.gz
sl0ppij-c5ac7968809ddb1033b625562eae22019cccc2f4.tar.xz
sl0ppij-c5ac7968809ddb1033b625562eae22019cccc2f4.zip
Feature: web-client/server to share your sessions in the browser (#4242)
* work * moar work * notes * work * separate to terminal and control channels * stdin working * serve html web client initial * serve static assets loaded with include_dir * merge * enable_web_server config parameter * compile time flag to disable web server capability * rustfmt * add license to all xterm.js assets * mouse working except copy/paste * helpful comment * web client improvements - move script to js file - add favicon - add nerd font - change title TODO: investigate if font license embedded in otf is sufficient * get mouse to work properly * kitty keyboard support initial * fix wrong type in preload link * wip axum websocket handlers - upgrade axum to v0.8.1, enable ws feature - begin setup of websocket handlers - tidy up imports * replace control listener * handle terminal websocket with axum * cleanup Cargo.toml * kitty fixes and bracketed paste * fix(mouse): pane not found crash * initial session switching infra * add `web_client_font` option * session switching, creation and resurrection working through the session manager * move session module to zellij-utils and share logic with web-client * some cleanups * require restart for enable-web-server * use session name from router * write config to disk and watch for config changes * rename session name to ipc path * add basic panic handler, make render_to_client exit on channel close * use while let instead of loop * handle websocket close * add mouse motions * make clipboard work * add weblink handling and webgl rendering * add todo * fix: use session name instead of patch on session switch * use "default" layout for new sessions * ui indication for session being shared * share this session ui * plugin assets * Fix process crash on mac with notify watcher. Use poll watcher instead of recommended as a workaround. * make url session switching and creation work * start welcome screen on root url * scaffold control messages, set font from config * set dimensions on session start * bring back session name from url * send bytes on terminal websocket instead of json - create web client os input and id before websocket connection * draft ui * work * refactor ui * remove otf font, remove margins to avoid scrollbar * version query endpoint for server status * web session info query endpoint * refactor: move stuff around * add web client info to session metadata * make tests pass * populate real data in session list * remove unnecessary endpoint * add web_client node to config, add font option * remove web_client_font * allow disabling the web session through the config - WIP * formalize sharing/not-sharing configuration * fix tests * allow shutting down web server * display error when web clients are forbidden to attach * only show sessions that allow web clients if this is a web client * style(fmt): rustfmt * fix: query web server from Zellij rather than from each plugin * remove log spam * handle some error paths better in the web client * allow controlling the web server through the cli * allow configuring the web server's ip/port * fix tests and format code * use direct WebServerStatus event instead of piggy-backing on SessionInfo * plugin revamp initial * make plugin responsive * adjust plugin title * refactor: share plugin * refactor: share plugin * add cors middleware * some fixes for running without a compiled web server capability * display error when starting the share plugin without web server support * clarify config * add pipelines to compile zellij without web support * display error when unable to start web server * only query web server when share plugin is running * refactor(web-client): connection table * give zellij_server_listener access to the control channel * fixes and clarifications * refactor: consolidate generate_unique_session_name * give proper error when trying to attach to a forbidden session * change browser URL when switching sessions * add keyboard shortcut * enforce https when bound to non-loopback ip * initial authentication token implementation * background color from theme * initial web client theme config * basic token generation ui * refactor set config message creation * also set body background * allow editing scrollback for plugins too * set scrollback to 0 * properly parse colors in config * generate token from plugin * nice login modals * initial token management screen * implement token authentication * refactor(share): token management screen * style(fmt): rustfmt * fix(plugin): some minor bugs * refactor(share): main screen * refactor(share): token screen * refactor(share): main * refactor(share): ui components * fix(responsiveness): properly send usage_width to the render function * fix cli commands and add some verbosity * add support for settings ansi and selection colors * add cursor and cursor accent * basic web client tests * fix tests * refactor: web client * use session tokens for authentication * improve modals * move shutdown to ipc * refactor: ipc logic * serialize theme config for web client * update tests * refactor: move some stuff around to prepare for config hot reload * config live reloading for the web clients * change remember-me UI wording * improve xterm.js link handling * make sure terminal is focused on mousemove * remove deprecated sharing indication from compact-bar * gate deps and functionality behind the web_server_compatibility feature * feat(build): add --no-web flag in all the places * fix some other build flows * add new assets * update CI for no-web (untested) * make more dependencies optional * update axum-extra * add web client configuration options * gracefully close connections on server exit * tests for graceful connection closing * handle client-side reconnect when server is down * fix: make sure ipc bus folder exists before starting * add commands to manage login tokens from the cli * style(fmt): rustfmt * some cleanups * fix(ux): allow alt-right-click on the web client without opening the context menu * fix: prevent attaching to welcome screen * fix: reload config issues * fix long socket path on macos * normalize config conversion and fix color gap in browser * revoke session_token cookie if it is not valid * fix: visual bug with multiple clients in extremely small screen sizes * fix: only include rusqlite for the web server capability builds * update e2e snapshots * refactor(web): client side js * some cleanups * moar cleanups * fix(tests): wait for server instead of using a fixed timeout * debug CI * fix(tests): use spawn_blocking for running the test web server * fix(tests): wait for http rather than tcp port * fix(tests): properly pass config path - hopefully this is the issue... * success! bring back the rest of the tests * attempt to fix the macos CI issue * docs(changelog): add PR --------- Co-authored-by: Thomas Linford <linford.t@gmail.com>
Diffstat (limited to 'zellij-utils/src/plugin_api')
-rw-r--r--zellij-utils/src/plugin_api/event.proto43
-rw-r--r--zellij-utils/src/plugin_api/event.rs154
-rw-r--r--zellij-utils/src/plugin_api/plugin_command.proto74
-rw-r--r--zellij-utils/src/plugin_api/plugin_command.rs164
-rw-r--r--zellij-utils/src/plugin_api/plugin_permission.proto3
-rw-r--r--zellij-utils/src/plugin_api/plugin_permission.rs2
6 files changed, 414 insertions, 26 deletions
diff --git a/zellij-utils/src/plugin_api/event.proto b/zellij-utils/src/plugin_api/event.proto
index 760aee0b..52c1801c 100644
--- a/zellij-utils/src/plugin_api/event.proto
+++ b/zellij-utils/src/plugin_api/event.proto
@@ -54,8 +54,10 @@ enum EventType {
FailedToChangeHostFolder = 28;
PastedText = 29;
ConfigWasWrittenToDisk = 30;
- BeforeClose = 31;
- InterceptedKeyPress = 32;
+ WebServerStatus = 31;
+ BeforeClose = 32;
+ FailedToStartWebServer = 34;
+ InterceptedKeyPress = 35;
}
message EventNameList {
@@ -90,14 +92,31 @@ message Event {
HostFolderChangedPayload host_folder_changed_payload = 24;
FailedToChangeHostFolderPayload failed_to_change_host_folder_payload = 25;
PastedTextPayload pasted_text_payload = 26;
- key.Key intercepted_key_payload = 27;
+ WebServerStatusPayload web_server_status_payload = 27;
+ FailedToStartWebServerPayload failed_to_start_web_server_payload = 28;
+ key.Key intercepted_key_payload = 29;
}
}
+message FailedToStartWebServerPayload {
+ string error = 1;
+}
+
message PastedTextPayload {
string pasted_text = 1;
}
+enum WebServerStatusIndication {
+ Online = 0;
+ Offline = 1;
+ DifferentVersion = 2;
+}
+
+message WebServerStatusPayload {
+ WebServerStatusIndication web_server_status_indication = 1;
+ optional string payload = 2;
+}
+
message FailedToChangeHostFolderPayload {
optional string error_message = 1;
}
@@ -260,7 +279,9 @@ message SessionManifest {
bool is_current_session = 5;
repeated LayoutInfo available_layouts = 6;
repeated PluginInfo plugins = 7;
- repeated ClientTabHistory tab_history = 8;
+ bool web_clients_allowed = 8;
+ uint32 web_client_count = 9;
+ repeated ClientTabHistory tab_history = 10;
}
message ClientTabHistory {
@@ -343,7 +364,19 @@ message ModeUpdatePayload {
optional input_mode.InputMode base_mode = 6;
optional string editor = 7;
optional string shell = 8;
- optional bool currently_marking_pane_group = 9;
+ optional bool web_clients_allowed = 9;
+ optional WebSharing web_sharing = 10;
+ optional bool currently_marking_pane_group = 11;
+ optional bool is_web_client = 12;
+ optional string web_server_ip = 13;
+ optional uint32 web_server_port = 14;
+ optional bool web_server_capability = 15;
+}
+
+enum WebSharing {
+ On = 0;
+ Off = 1;
+ Disabled = 2;
}
message InputModeKeybinds {
diff --git a/zellij-utils/src/plugin_api/event.rs b/zellij-utils/src/plugin_api/event.rs
index a853e12d..e363b86c 100644
--- a/zellij-utils/src/plugin_api/event.rs
+++ b/zellij-utils/src/plugin_api/event.rs
@@ -10,7 +10,9 @@ pub use super::generated_api::api::{
PaneId as ProtobufPaneId, PaneInfo as ProtobufPaneInfo,
PaneManifest as ProtobufPaneManifest, PaneType as ProtobufPaneType,
PluginInfo as ProtobufPluginInfo, ResurrectableSession as ProtobufResurrectableSession,
- SessionManifest as ProtobufSessionManifest, TabInfo as ProtobufTabInfo, *,
+ SessionManifest as ProtobufSessionManifest, TabInfo as ProtobufTabInfo,
+ WebServerStatusPayload as ProtobufWebServerStatusPayload, WebSharing as ProtobufWebSharing,
+ *,
},
input_mode::InputMode as ProtobufInputMode,
key::Key as ProtobufKey,
@@ -20,7 +22,7 @@ pub use super::generated_api::api::{
use crate::data::{
ClientInfo, CopyDestination, Event, EventType, FileMetadata, InputMode, KeyWithModifier,
LayoutInfo, ModeInfo, Mouse, PaneId, PaneInfo, PaneManifest, PermissionStatus,
- PluginCapabilities, PluginInfo, SessionInfo, Style, TabInfo,
+ PluginCapabilities, PluginInfo, SessionInfo, Style, TabInfo, WebServerStatus, WebSharing,
};
use crate::errors::prelude::*;
@@ -28,7 +30,9 @@ use crate::input::actions::Action;
use std::collections::{BTreeMap, HashMap, HashSet};
use std::convert::TryFrom;
+use std::net::IpAddr;
use std::path::PathBuf;
+use std::str::FromStr;
use std::time::Duration;
impl TryFrom<ProtobufEvent> for Event {
@@ -359,10 +363,24 @@ impl TryFrom<ProtobufEvent> for Event {
None => Ok(Event::ConfigWasWrittenToDisk),
_ => Err("Malformed payload for the ConfigWasWrittenToDisk Event"),
},
+ Some(ProtobufEventType::WebServerStatus) => match protobuf_event.payload {
+ Some(ProtobufEventPayload::WebServerStatusPayload(web_server_status)) => {
+ Ok(Event::WebServerStatus(web_server_status.try_into()?))
+ },
+ _ => Err("Malformed payload for the WebServerStatus Event"),
+ },
Some(ProtobufEventType::BeforeClose) => match protobuf_event.payload {
None => Ok(Event::BeforeClose),
_ => Err("Malformed payload for the BeforeClose Event"),
},
+ Some(ProtobufEventType::FailedToStartWebServer) => match protobuf_event.payload {
+ Some(ProtobufEventPayload::FailedToStartWebServerPayload(
+ failed_to_start_web_server_payload,
+ )) => Ok(Event::FailedToStartWebServer(
+ failed_to_start_web_server_payload.error,
+ )),
+ _ => Err("Malformed payload for the FailedToStartWebServer Event"),
+ },
Some(ProtobufEventType::InterceptedKeyPress) => match protobuf_event.payload {
Some(ProtobufEventPayload::KeyPayload(protobuf_key)) => {
Ok(Event::InterceptedKeyPress(protobuf_key.try_into()?))
@@ -743,10 +761,22 @@ impl TryFrom<Event> for ProtobufEvent {
name: ProtobufEventType::ConfigWasWrittenToDisk as i32,
payload: None,
}),
+ Event::WebServerStatus(web_server_status) => Ok(ProtobufEvent {
+ name: ProtobufEventType::WebServerStatus as i32,
+ payload: Some(event::Payload::WebServerStatusPayload(
+ ProtobufWebServerStatusPayload::try_from(web_server_status)?,
+ )),
+ }),
Event::BeforeClose => Ok(ProtobufEvent {
name: ProtobufEventType::BeforeClose as i32,
payload: None,
}),
+ Event::FailedToStartWebServer(error) => Ok(ProtobufEvent {
+ name: ProtobufEventType::FailedToStartWebServer as i32,
+ payload: Some(event::Payload::FailedToStartWebServerPayload(
+ FailedToStartWebServerPayload { error },
+ )),
+ }),
Event::InterceptedKeyPress(key) => Ok(ProtobufEvent {
name: ProtobufEventType::InterceptedKeyPress as i32,
payload: Some(event::Payload::KeyPayload(key.try_into()?)),
@@ -789,6 +819,8 @@ impl TryFrom<SessionInfo> for ProtobufSessionManifest {
.into_iter()
.map(|p| ProtobufPluginInfo::from(p))
.collect(),
+ web_clients_allowed: session_info.web_clients_allowed,
+ web_client_count: session_info.web_client_count as u32,
tab_history: session_info
.tab_history
.into_iter()
@@ -878,6 +910,8 @@ impl TryFrom<ProtobufSessionManifest> for SessionInfo {
.filter_map(|l| LayoutInfo::try_from(l).ok())
.collect(),
plugins,
+ web_clients_allowed: protobuf_session_manifest.web_clients_allowed,
+ web_client_count: protobuf_session_manifest.web_client_count as usize,
tab_history,
})
}
@@ -1249,11 +1283,29 @@ impl TryFrom<ProtobufModeUpdatePayload> for ModeInfo {
.editor
.map(|e| PathBuf::from(e));
let shell = protobuf_mode_update_payload.shell.map(|s| PathBuf::from(s));
+ let web_clients_allowed = protobuf_mode_update_payload.web_clients_allowed;
+ let web_sharing = protobuf_mode_update_payload
+ .web_sharing
+ .and_then(|w| ProtobufWebSharing::from_i32(w))
+ .map(|w| w.into());
let capabilities = PluginCapabilities {
arrow_fonts: protobuf_mode_update_payload.arrow_fonts_support,
};
let currently_marking_pane_group =
protobuf_mode_update_payload.currently_marking_pane_group;
+ let is_web_client = protobuf_mode_update_payload.is_web_client;
+
+ let web_server_ip = protobuf_mode_update_payload
+ .web_server_ip
+ .as_ref()
+ .and_then(|web_server_ip| IpAddr::from_str(web_server_ip).ok());
+
+ let web_server_port = protobuf_mode_update_payload
+ .web_server_port
+ .map(|w| w as u16);
+
+ let web_server_capability = protobuf_mode_update_payload.web_server_capability;
+
let mode_info = ModeInfo {
mode: current_mode,
keybinds,
@@ -1263,7 +1315,13 @@ impl TryFrom<ProtobufModeUpdatePayload> for ModeInfo {
base_mode,
editor,
shell,
+ web_clients_allowed,
+ web_sharing,
currently_marking_pane_group,
+ is_web_client,
+ web_server_ip,
+ web_server_port,
+ web_server_capability,
};
Ok(mode_info)
}
@@ -1281,7 +1339,13 @@ impl TryFrom<ModeInfo> for ProtobufModeUpdatePayload {
let session_name = mode_info.session_name;
let editor = mode_info.editor.map(|e| e.display().to_string());
let shell = mode_info.shell.map(|s| s.display().to_string());
+ let web_clients_allowed = mode_info.web_clients_allowed;
+ let web_sharing = mode_info.web_sharing.map(|w| w as i32);
let currently_marking_pane_group = mode_info.currently_marking_pane_group;
+ let is_web_client = mode_info.is_web_client;
+ let web_server_ip = mode_info.web_server_ip.map(|i| format!("{}", i));
+ let web_server_port = mode_info.web_server_port.map(|p| p as u32);
+ let web_server_capability = mode_info.web_server_capability;
let mut protobuf_input_mode_keybinds: Vec<ProtobufInputModeKeybinds> = vec![];
for (input_mode, input_mode_keybinds) in mode_info.keybinds {
let mode: ProtobufInputMode = input_mode.try_into()?;
@@ -1315,7 +1379,13 @@ impl TryFrom<ModeInfo> for ProtobufModeUpdatePayload {
base_mode: base_mode.map(|b_m| b_m as i32),
editor,
shell,
+ web_clients_allowed,
+ web_sharing,
currently_marking_pane_group,
+ is_web_client,
+ web_server_ip,
+ web_server_port,
+ web_server_capability,
})
}
}
@@ -1385,7 +1455,9 @@ impl TryFrom<ProtobufEventType> for EventType {
ProtobufEventType::FailedToChangeHostFolder => EventType::FailedToChangeHostFolder,
ProtobufEventType::PastedText => EventType::PastedText,
ProtobufEventType::ConfigWasWrittenToDisk => EventType::ConfigWasWrittenToDisk,
+ ProtobufEventType::WebServerStatus => EventType::WebServerStatus,
ProtobufEventType::BeforeClose => EventType::BeforeClose,
+ ProtobufEventType::FailedToStartWebServer => EventType::FailedToStartWebServer,
ProtobufEventType::InterceptedKeyPress => EventType::InterceptedKeyPress,
})
}
@@ -1426,7 +1498,9 @@ impl TryFrom<EventType> for ProtobufEventType {
EventType::FailedToChangeHostFolder => ProtobufEventType::FailedToChangeHostFolder,
EventType::PastedText => ProtobufEventType::PastedText,
EventType::ConfigWasWrittenToDisk => ProtobufEventType::ConfigWasWrittenToDisk,
+ EventType::WebServerStatus => ProtobufEventType::WebServerStatus,
EventType::BeforeClose => ProtobufEventType::BeforeClose,
+ EventType::FailedToStartWebServer => ProtobufEventType::FailedToStartWebServer,
EventType::InterceptedKeyPress => ProtobufEventType::InterceptedKeyPress,
})
}
@@ -1568,7 +1642,13 @@ fn serialize_mode_update_event_with_non_default_values() {
base_mode: Some(InputMode::Locked),
editor: Some(PathBuf::from("my_awesome_editor")),
shell: Some(PathBuf::from("my_awesome_shell")),
+ web_clients_allowed: Some(true),
+ web_sharing: Some(WebSharing::default()),
currently_marking_pane_group: Some(false),
+ is_web_client: Some(false),
+ web_server_ip: IpAddr::from_str("127.0.0.1").ok(),
+ web_server_port: Some(8082),
+ web_server_capability: Some(true),
});
let protobuf_event: ProtobufEvent = mode_update_event.clone().try_into().unwrap();
let serialized_protobuf_event = protobuf_event.encode_to_vec();
@@ -2016,6 +2096,8 @@ fn serialize_session_update_event_with_non_default_values() {
LayoutInfo::File("layout3".to_owned()),
],
plugins,
+ web_clients_allowed: false,
+ web_client_count: 1,
tab_history,
};
let session_info_2 = SessionInfo {
@@ -2032,6 +2114,8 @@ fn serialize_session_update_event_with_non_default_values() {
LayoutInfo::File("layout3".to_owned()),
],
plugins: Default::default(),
+ web_clients_allowed: false,
+ web_client_count: 0,
tab_history: Default::default(),
};
let session_infos = vec![session_info_1, session_info_2];
@@ -2081,3 +2165,69 @@ impl TryFrom<PaneId> for ProtobufPaneId {
}
}
}
+
+impl Into<ProtobufWebSharing> for WebSharing {
+ fn into(self) -> ProtobufWebSharing {
+ match self {
+ WebSharing::On => ProtobufWebSharing::On,
+ WebSharing::Off => ProtobufWebSharing::Off,
+ WebSharing::Disabled => ProtobufWebSharing::Disabled,
+ }
+ }
+}
+
+impl Into<WebSharing> for ProtobufWebSharing {
+ fn into(self) -> WebSharing {
+ match self {
+ ProtobufWebSharing::On => WebSharing::On,
+ ProtobufWebSharing::Off => WebSharing::Off,
+ ProtobufWebSharing::Disabled => WebSharing::Disabled,
+ }
+ }
+}
+
+impl TryFrom<WebServerStatus> for ProtobufWebServerStatusPayload {
+ type Error = &'static str;
+ fn try_from(web_server_status: WebServerStatus) -> Result<Self, &'static str> {
+ match web_server_status {
+ WebServerStatus::Online(url) => Ok(ProtobufWebServerStatusPayload {
+ web_server_status_indication: WebServerStatusIndication::Online as i32,
+ payload: Some(url),
+ }),
+ WebServerStatus::DifferentVersion(version) => Ok(ProtobufWebServerStatusPayload {
+ web_server_status_indication: WebServerStatusIndication::DifferentVersion as i32,
+ payload: Some(format!("{}", version)),
+ }),
+ WebServerStatus::Offline => Ok(ProtobufWebServerStatusPayload {
+ web_server_status_indication: WebServerStatusIndication::Offline as i32,
+ payload: None,
+ }),
+ }
+ }
+}
+
+impl TryFrom<ProtobufWebServerStatusPayload> for WebServerStatus {
+ type Error = &'static str;
+ fn try_from(
+ protobuf_web_server_status: ProtobufWebServerStatusPayload,
+ ) -> Result<Self, &'static str> {
+ match WebServerStatusIndication::from_i32(
+ protobuf_web_server_status.web_server_status_indication,
+ ) {
+ Some(WebServerStatusIndication::Online) => {
+ let payload = protobuf_web_server_status
+ .payload
+ .ok_or("payload_not_found")?;
+ Ok(WebServerStatus::Online(payload))
+ },
+ Some(WebServerStatusIndication::DifferentVersion) => {
+ let payload = protobuf_web_server_status
+ .payload
+ .ok_or("payload_not_found")?;
+ Ok(WebServerStatus::DifferentVersion(payload))
+ },
+ Some(WebServerStatusIndication::Offline) => Ok(WebServerStatus::Offline),
+ None => Err("Unknown status"),
+ }
+ }
+}
diff --git a/zellij-utils/src/plugin_api/plugin_command.proto b/zellij-utils/src/plugin_api/plugin_command.proto
index b8b6bad1..4c1db71f 100644
--- a/zellij-utils/src/plugin_api/plugin_command.proto
+++ b/zellij-utils/src/plugin_api/plugin_command.proto
@@ -140,13 +140,24 @@ enum CommandName {
OpenFileNearPlugin = 124;
OpenFileFloatingNearPlugin = 125;
OpenFileInPlaceOfPlugin = 126;
- GroupAndUngroupPanes = 127;
- HighlightAndUnhighlightPanes = 128;
- CloseMultiplePanes = 129;
- FloatMultiplePanes = 130;
- EmbedMultiplePanes = 131;
- InterceptKeyPresses = 132;
- ClearKeyPressesIntercepts = 133;
+ StartWebServer = 127;
+ GroupAndUngroupPanes = 128;
+ HighlightAndUnhighlightPanes = 129;
+ CloseMultiplePanes = 130;
+ FloatMultiplePanes = 131;
+ EmbedMultiplePanes = 132;
+ ShareCurrentSession = 133;
+ StopSharingCurrentSession = 134;
+ StopWebServer = 135;
+ QueryWebServerStatus = 136;
+ SetSelfMouseSelectionSupport = 137;
+ GenerateWebLoginToken = 138;
+ RevokeWebLoginToken = 139;
+ ListWebLoginTokens = 140;
+ RevokeAllWebLoginTokens = 141;
+ RenameWebLoginToken = 142;
+ InterceptKeyPresses = 143;
+ ClearKeyPressesIntercepts = 144;
}
message PluginCommand {
@@ -248,9 +259,30 @@ message PluginCommand {
CloseMultiplePanesPayload close_multiple_panes_payload = 104;
FloatMultiplePanesPayload float_multiple_panes_payload = 105;
EmbedMultiplePanesPayload embed_multiple_panes_payload = 106;
+ SetSelfMouseSelectionSupportPayload set_self_mouse_selection_support_payload = 107;
+ GenerateWebLoginTokenPayload generate_web_login_token_payload = 108;
+ RevokeWebLoginTokenPayload revoke_web_login_token_payload = 109;
+ RenameWebLoginTokenPayload rename_web_login_token_payload = 110;
}
}
+message RenameWebLoginTokenPayload {
+ string old_name = 1;
+ string new_name = 2;
+}
+
+message RevokeWebLoginTokenPayload {
+ string token_label = 1;
+}
+
+message GenerateWebLoginTokenPayload {
+ optional string token_label = 1;
+}
+
+message SetSelfMouseSelectionSupportPayload {
+ bool support_mouse_selection = 1;
+}
+
message EmbedMultiplePanesPayload {
repeated PaneId pane_ids = 1;
}
@@ -628,3 +660,31 @@ enum FixedOrPercent {
Fixed = 0;
Percent = 1;
}
+
+message CreateTokenResponse {
+ optional string token = 1;
+ optional string token_label = 2;
+ optional string error = 3;
+}
+
+message RevokeTokenResponse {
+ bool successfully_revoked = 1;
+ optional string error = 2;
+}
+
+message ListTokensResponse {
+ // tokens/creation_times should be synchronized
+ repeated string tokens = 1;
+ repeated string creation_times = 2;
+ optional string error = 3;
+}
+
+message RevokeAllWebTokensResponse {
+ bool successfully_revoked = 1;
+ optional string error = 2;
+}
+
+message RenameWebTokenResponse {
+ bool successfully_renamed = 1;
+ optional string error = 2;
+}
diff --git a/zellij-utils/src/plugin_api/plugin_command.rs b/zellij-utils/src/plugin_api/plugin_command.rs
index 30a6a03d..7fb583b7 100644
--- a/zellij-utils/src/plugin_api/plugin_command.rs
+++ b/zellij-utils/src/plugin_api/plugin_command.rs
@@ -6,15 +6,17 @@ pub use super::generated_api::api::{
plugin_command::Payload, BreakPanesToNewTabPayload, BreakPanesToTabWithIndexPayload,
ChangeFloatingPanesCoordinatesPayload, ChangeHostFolderPayload,
ClearScreenForPaneIdPayload, CliPipeOutputPayload, CloseMultiplePanesPayload,
- CloseTabWithIndexPayload, CommandName, ContextItem, EditScrollbackForPaneWithIdPayload,
- EmbedMultiplePanesPayload, EnvVariable, ExecCmdPayload,
+ CloseTabWithIndexPayload, CommandName, ContextItem,
+ CreateTokenResponse as ProtobufCreateTokenResponse, CreateTokenResponse,
+ EditScrollbackForPaneWithIdPayload, EmbedMultiplePanesPayload, EnvVariable, ExecCmdPayload,
FixedOrPercent as ProtobufFixedOrPercent,
FixedOrPercentValue as ProtobufFixedOrPercentValue, FloatMultiplePanesPayload,
- FloatingPaneCoordinates as ProtobufFloatingPaneCoordinates, GroupAndUngroupPanesPayload,
- HidePaneWithIdPayload, HighlightAndUnhighlightPanesPayload, HttpVerb as ProtobufHttpVerb,
- IdAndNewName, KeyToRebind, KeyToUnbind, KillSessionsPayload, LoadNewPluginPayload,
- MessageToPluginPayload, MovePaneWithPaneIdInDirectionPayload, MovePaneWithPaneIdPayload,
- MovePayload, NewPluginArgs as ProtobufNewPluginArgs, NewTabsWithLayoutInfoPayload,
+ FloatingPaneCoordinates as ProtobufFloatingPaneCoordinates, GenerateWebLoginTokenPayload,
+ GroupAndUngroupPanesPayload, HidePaneWithIdPayload, HighlightAndUnhighlightPanesPayload,
+ HttpVerb as ProtobufHttpVerb, IdAndNewName, KeyToRebind, KeyToUnbind, KillSessionsPayload,
+ ListTokensResponse, LoadNewPluginPayload, MessageToPluginPayload,
+ MovePaneWithPaneIdInDirectionPayload, MovePaneWithPaneIdPayload, MovePayload,
+ NewPluginArgs as ProtobufNewPluginArgs, NewTabsWithLayoutInfoPayload,
OpenCommandPaneFloatingNearPluginPayload, OpenCommandPaneInPlaceOfPluginPayload,
OpenCommandPaneNearPluginPayload, OpenCommandPanePayload,
OpenFileFloatingNearPluginPayload, OpenFileInPlaceOfPluginPayload,
@@ -23,10 +25,12 @@ pub use super::generated_api::api::{
PageScrollDownInPaneIdPayload, PageScrollUpInPaneIdPayload, PaneId as ProtobufPaneId,
PaneIdAndFloatingPaneCoordinates, PaneType as ProtobufPaneType,
PluginCommand as ProtobufPluginCommand, PluginMessagePayload, RebindKeysPayload,
- ReconfigurePayload, ReloadPluginPayload, RequestPluginPermissionPayload,
- RerunCommandPanePayload, ResizePaneIdWithDirectionPayload, ResizePayload,
- RunCommandPayload, ScrollDownInPaneIdPayload, ScrollToBottomInPaneIdPayload,
- ScrollToTopInPaneIdPayload, ScrollUpInPaneIdPayload, SetFloatingPanePinnedPayload,
+ ReconfigurePayload, ReloadPluginPayload, RenameWebLoginTokenPayload,
+ RenameWebTokenResponse, RequestPluginPermissionPayload, RerunCommandPanePayload,
+ ResizePaneIdWithDirectionPayload, ResizePayload, RevokeAllWebTokensResponse,
+ RevokeTokenResponse, RevokeWebLoginTokenPayload, RunCommandPayload,
+ ScrollDownInPaneIdPayload, ScrollToBottomInPaneIdPayload, ScrollToTopInPaneIdPayload,
+ ScrollUpInPaneIdPayload, SetFloatingPanePinnedPayload, SetSelfMouseSelectionSupportPayload,
SetTimeoutPayload, ShowPaneWithIdPayload, StackPanesPayload, SubscribePayload,
SwitchSessionPayload, SwitchTabToPayload, TogglePaneEmbedOrEjectForPaneIdPayload,
TogglePaneIdFullscreenPayload, UnsubscribePayload, WebRequestPayload,
@@ -1545,6 +1549,27 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand {
},
_ => Err("Mismatched payload for OpenFileInPlaceOfPlugin"),
},
+ Some(CommandName::StartWebServer) => {
+ if protobuf_plugin_command.payload.is_some() {
+ Err("StartWebServer should not have a payload")
+ } else {
+ Ok(PluginCommand::StartWebServer)
+ }
+ },
+ Some(CommandName::StopWebServer) => {
+ if protobuf_plugin_command.payload.is_some() {
+ Err("StopWebServer should not have a payload")
+ } else {
+ Ok(PluginCommand::StopWebServer)
+ }
+ },
+ Some(CommandName::QueryWebServerStatus) => {
+ if protobuf_plugin_command.payload.is_some() {
+ Err("QueryWebServerStatus should not have a payload")
+ } else {
+ Ok(PluginCommand::QueryWebServerStatus)
+ }
+ },
Some(CommandName::GroupAndUngroupPanes) => match protobuf_plugin_command.payload {
Some(Payload::GroupAndUngroupPanesPayload(group_and_ungroup_panes_payload)) => {
Ok(PluginCommand::GroupAndUngroupPanes(
@@ -1617,6 +1642,67 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand {
},
_ => Err("Mismatched payload for EmbedMultiplePanes"),
},
+ Some(CommandName::ShareCurrentSession) => {
+ if protobuf_plugin_command.payload.is_some() {
+ Err("ShareCurrentSession should not have a payload")
+ } else {
+ Ok(PluginCommand::ShareCurrentSession)
+ }
+ },
+ Some(CommandName::StopSharingCurrentSession) => {
+ if protobuf_plugin_command.payload.is_some() {
+ Err("StopSharingCurrentSession should not have a payload")
+ } else {
+ Ok(PluginCommand::StopSharingCurrentSession)
+ }
+ },
+ Some(CommandName::SetSelfMouseSelectionSupport) => {
+ match protobuf_plugin_command.payload {
+ Some(Payload::SetSelfMouseSelectionSupportPayload(
+ set_self_mouse_selection_support_payload,
+ )) => Ok(PluginCommand::SetSelfMouseSelectionSupport(
+ set_self_mouse_selection_support_payload.support_mouse_selection,
+ )),
+ _ => Err("SetSelfMouseSelectionSupport requires a payload"),
+ }
+ },
+ Some(CommandName::GenerateWebLoginToken) => match protobuf_plugin_command.payload {
+ Some(Payload::GenerateWebLoginTokenPayload(generate_web_login_token_payload)) => {
+ Ok(PluginCommand::GenerateWebLoginToken(
+ generate_web_login_token_payload.token_label,
+ ))
+ },
+ _ => Err("GenerateWebLoginToken requires a payload"),
+ },
+ Some(CommandName::RevokeWebLoginToken) => match protobuf_plugin_command.payload {
+ Some(Payload::RevokeWebLoginTokenPayload(revoke_web_login_token_payload)) => Ok(
+ PluginCommand::RevokeWebLoginToken(revoke_web_login_token_payload.token_label),
+ ),
+ _ => Err("RevokeWebLoginToken requires a payload"),
+ },
+ Some(CommandName::ListWebLoginTokens) => {
+ if protobuf_plugin_command.payload.is_some() {
+ Err("ListWebLoginTokens should not have a payload")
+ } else {
+ Ok(PluginCommand::ListWebLoginTokens)
+ }
+ },
+ Some(CommandName::RevokeAllWebLoginTokens) => {
+ if protobuf_plugin_command.payload.is_some() {
+ Err("RevokeAllWebLoginTokens should not have a payload")
+ } else {
+ Ok(PluginCommand::RevokeAllWebLoginTokens)
+ }
+ },
+ Some(CommandName::RenameWebLoginToken) => match protobuf_plugin_command.payload {
+ Some(Payload::RenameWebLoginTokenPayload(rename_web_login_token_payload)) => {
+ Ok(PluginCommand::RenameWebLoginToken(
+ rename_web_login_token_payload.old_name,
+ rename_web_login_token_payload.new_name,
+ ))
+ },
+ _ => Err("RenameWebLoginToken requires a payload"),
+ },
Some(CommandName::InterceptKeyPresses) => match protobuf_plugin_command.payload {
Some(_) => Err("InterceptKeyPresses should have no payload, found a payload"),
None => Ok(PluginCommand::InterceptKeyPresses),
@@ -2656,6 +2742,18 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand {
)),
})
},
+ PluginCommand::StartWebServer => Ok(ProtobufPluginCommand {
+ name: CommandName::StartWebServer as i32,
+ payload: None,
+ }),
+ PluginCommand::StopWebServer => Ok(ProtobufPluginCommand {
+ name: CommandName::StopWebServer as i32,
+ payload: None,
+ }),
+ PluginCommand::QueryWebServerStatus => Ok(ProtobufPluginCommand {
+ name: CommandName::QueryWebServerStatus as i32,
+ payload: None,
+ }),
PluginCommand::HighlightAndUnhighlightPanes(
panes_to_highlight,
panes_to_unhighlight,
@@ -2698,6 +2796,50 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand {
},
)),
}),
+ PluginCommand::ShareCurrentSession => Ok(ProtobufPluginCommand {
+ name: CommandName::ShareCurrentSession as i32,
+ payload: None,
+ }),
+ PluginCommand::StopSharingCurrentSession => Ok(ProtobufPluginCommand {
+ name: CommandName::StopSharingCurrentSession as i32,
+ payload: None,
+ }),
+ PluginCommand::SetSelfMouseSelectionSupport(support_mouse_selection) => {
+ Ok(ProtobufPluginCommand {
+ name: CommandName::SetSelfMouseSelectionSupport as i32,
+ payload: Some(Payload::SetSelfMouseSelectionSupportPayload(
+ SetSelfMouseSelectionSupportPayload {
+ support_mouse_selection,
+ },
+ )),
+ })
+ },
+ PluginCommand::GenerateWebLoginToken(token_label) => Ok(ProtobufPluginCommand {
+ name: CommandName::GenerateWebLoginToken as i32,
+ payload: Some(Payload::GenerateWebLoginTokenPayload(
+ GenerateWebLoginTokenPayload { token_label },
+ )),
+ }),
+ PluginCommand::RevokeWebLoginToken(token_label) => Ok(ProtobufPluginCommand {
+ name: CommandName::RevokeWebLoginToken as i32,
+ payload: Some(Payload::RevokeWebLoginTokenPayload(
+ RevokeWebLoginTokenPayload { token_label },
+ )),
+ }),
+ PluginCommand::ListWebLoginTokens => Ok(ProtobufPluginCommand {
+ name: CommandName::ListWebLoginTokens as i32,
+ payload: None,
+ }),
+ PluginCommand::RevokeAllWebLoginTokens => Ok(ProtobufPluginCommand {
+ name: CommandName::RevokeAllWebLoginTokens as i32,
+ payload: None,
+ }),
+ PluginCommand::RenameWebLoginToken(old_name, new_name) => Ok(ProtobufPluginCommand {
+ name: CommandName::RenameWebLoginToken as i32,
+ payload: Some(Payload::RenameWebLoginTokenPayload(
+ RenameWebLoginTokenPayload { old_name, new_name },
+ )),
+ }),
PluginCommand::InterceptKeyPresses => Ok(ProtobufPluginCommand {
name: CommandName::InterceptKeyPresses as i32,
payload: None,
diff --git a/zellij-utils/src/plugin_api/plugin_permission.proto b/zellij-utils/src/plugin_api/plugin_permission.proto
index 72c5b0f9..0f53bb55 100644
--- a/zellij-utils/src/plugin_api/plugin_permission.proto
+++ b/zellij-utils/src/plugin_api/plugin_permission.proto
@@ -14,5 +14,6 @@ enum PermissionType {
MessageAndLaunchOtherPlugins = 8;
Reconfigure = 9;
FullHdAccess = 10;
- InterceptInput = 11;
+ StartWebServer = 11;
+ InterceptInput = 12;
}
diff --git a/zellij-utils/src/plugin_api/plugin_permission.rs b/zellij-utils/src/plugin_api/plugin_permission.rs
index ad64b499..926f993f 100644
--- a/zellij-utils/src/plugin_api/plugin_permission.rs
+++ b/zellij-utils/src/plugin_api/plugin_permission.rs
@@ -26,6 +26,7 @@ impl TryFrom<ProtobufPermissionType> for PermissionType {
},
ProtobufPermissionType::Reconfigure => Ok(PermissionType::Reconfigure),
ProtobufPermissionType::FullHdAccess => Ok(PermissionType::FullHdAccess),
+ ProtobufPermissionType::StartWebServer => Ok(PermissionType::StartWebServer),
ProtobufPermissionType::InterceptInput => Ok(PermissionType::InterceptInput),
}
}
@@ -54,6 +55,7 @@ impl TryFrom<PermissionType> for ProtobufPermissionType {
},
PermissionType::Reconfigure => Ok(ProtobufPermissionType::Reconfigure),
PermissionType::FullHdAccess => Ok(ProtobufPermissionType::FullHdAccess),
+ PermissionType::StartWebServer => Ok(ProtobufPermissionType::StartWebServer),
PermissionType::InterceptInput => Ok(ProtobufPermissionType::InterceptInput),
}
}