aboutsummaryrefslogtreecommitdiffstats
path: root/zellij-server/src/plugins/mod.rs
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2025-12-11 14:25:42 +0100
committerGitHub <noreply@github.com>2025-12-11 14:25:42 +0100
commit693fa082def5ef0fe030cd7fdc3b1df051b35dc6 (patch)
treeb3f651462bbc1cd2fa5b2d79207343413ef6b83c /zellij-server/src/plugins/mod.rs
parentfix(zellij-server): unblock building on 32bit targets (#4484) (diff)
downloadsl0ppij-693fa082def5ef0fe030cd7fdc3b1df051b35dc6.tar.gz
sl0ppij-693fa082def5ef0fe030cd7fdc3b1df051b35dc6.tar.xz
sl0ppij-693fa082def5ef0fe030cd7fdc3b1df051b35dc6.zip
Command Sequences, Blocking CLI Commands, New Plugin APIs (#4546)
* fix deadlocks * initial logging to plugin implementation * only log actions, include keys as Action::Write * send actions to plugins as a new Event::UserAction * add Action::Write metadata to plugin API * run_action plugin command and permission * block-until-exit/success/failure in the cli * fix tests * add NewBlockingPane to the plugin API * run actions in a different thread so as not to block plugin execution * add custom context to run_action flow * fixes for floating pane z_index sorting and unknown protobuf events not crashing plugins * always render the frame of pinned panes * macros module * add macros to config * KDL macro parsing * thread macros to the plugin thread * get/update/delete macros from plugins * add macros updated event * add ability to rename macros * fix deadlock * fix z_indices with pinned unselectable panes bug * allow plugins to opt-in to show_cursor * change show_cursor(bool) to show_cursor(Option<coordinates>) * test * upgrade strum to allow proper enum iteration and case insensitive fromstr implementation for Actions * better cwd tracking for exited command panes * add initial panes to NewTab Action (no-op for now) * add initial panes to cli newtab action * make initial panes work * add close_on_exit and start_suspended to the cli * properly convert newtab action (potentially breaking for plugins) * allow first pane in tab to block * make distinction between opening panes with the last active client and the current pane in the cli * improve some apis * fix fixed size closing pane bug * fix plugin cursor coordinates * fix issues with launch-or-focus-plugin having to do with in-place and suppressed panes * fix: set affected pane in replace pane * allow setting a pane in place when it is suppressed and being focused (tests failing) * fix tests * some fixes for unsuppression of panes * some fixes for completion_tx in new tab action * allow replace/suppressed rather than replace/close only * fixes for inserting suppressed panes without conflicts * pane focus history and explicit unsuppress plugin api * fix: prefer explicitly provided pane id in placement in actions that provide it * fix floating pane coordinate change and z_index * fix plugin cache dir to persist between sessions * fix some stack focusing issues when adding panes without a client id * make sure pinned panes are always above non-pinned floating panes * allow plugins to copy to clipboard * initial text styling additions implementations - buggy * fix dimming issues * remove extras, stay with just dim and unbold * unbold and dim as indices * allow ui components to render success/error colors * allow plugins to send sigint/sigkill to processes, as well as receive their pid * ui component fixes and send originating plugin context with run_action * originating plugin for new tab too * make plugn show pane command also expand stacked panes * add sequence plugin * remove macros * remove snapshots * add shortcut for sequence plugin * fix plugin tests * plugin tests for new apis * update snapshots for sequence shortcut * cleanups and formatting * Event::CwdChanged * moar cleanups * remove some warnings * remove mroe warnings * remove dead code * remove more dead code * fix minor bugs in sequence plugin * update sequence help and format codebase * fix conditional blocking cli commands * fix initial-command new-tab cli flag * add client_ids to CwdChanged Event * last fixes * add pr
Diffstat (limited to 'zellij-server/src/plugins/mod.rs')
-rw-r--r--zellij-server/src/plugins/mod.rs70
1 files changed, 60 insertions, 10 deletions
diff --git a/zellij-server/src/plugins/mod.rs b/zellij-server/src/plugins/mod.rs
index cede7901..24a1e811 100644
--- a/zellij-server/src/plugins/mod.rs
+++ b/zellij-server/src/plugins/mod.rs
@@ -30,12 +30,13 @@ use wasm_bridge::WasmBridge;
use async_std::{channel, future::timeout, task};
use zellij_utils::{
data::{
- ClientInfo, Event, EventType, FloatingPaneCoordinates, InputMode, MessageToPlugin,
- PermissionStatus, PermissionType, PipeMessage, PipeSource, PluginCapabilities,
- WebServerStatus,
+ ClientInfo, CommandOrPlugin, Event, EventType, FloatingPaneCoordinates, InputMode,
+ MessageToPlugin, PermissionStatus, PermissionType, PipeMessage, PipeSource,
+ PluginCapabilities, WebServerStatus,
},
errors::{prelude::*, ContextType, PluginContext},
input::{
+ actions::Action,
command::TerminalAction,
keybinds::Keybinds,
layout::{FloatingPaneLayout, Layout, Run, RunPlugin, RunPluginOrAlias, TiledPaneLayout},
@@ -86,10 +87,12 @@ pub enum PluginInstruction {
Option<TerminalAction>,
Option<TiledPaneLayout>,
Vec<FloatingPaneLayout>,
- usize, // tab_index
- bool, // should change focus to new tab
- (ClientId, bool), // bool -> is_web_client
- Option<NotificationEnd>, // completion signal
+ usize, // tab_index
+ Option<Vec<CommandOrPlugin>>, // initial_panes
+ bool, // block_on_first_terminal
+ bool, // should change focus to new tab
+ (ClientId, bool), // bool -> is_web_client
+ Option<NotificationEnd>, // completion signal
),
ApplyCachedEvents {
plugin_ids: Vec<PluginId>,
@@ -175,6 +178,12 @@ pub enum PluginInstruction {
WebServerStarted(String), // String -> the base url of the web server
FailedToStartWebServer(String),
PaneRenderReport(PaneRenderReport),
+ UserInput {
+ client_id: ClientId,
+ action: Action,
+ terminal_id: Option<u32>,
+ cli_client_id: Option<ClientId>,
+ },
Exit,
}
@@ -225,6 +234,7 @@ impl From<&PluginInstruction> for PluginContext {
PluginInstruction::WebServerStarted(..) => PluginContext::WebServerStarted,
PluginInstruction::FailedToStartWebServer(..) => PluginContext::FailedToStartWebServer,
PluginInstruction::PaneRenderReport(..) => PluginContext::PaneRenderReport,
+ PluginInstruction::UserInput { .. } => PluginContext::UserInput,
}
}
}
@@ -453,6 +463,8 @@ pub(crate) fn plugin_thread_main(
mut tab_layout,
mut floating_panes_layout,
tab_index,
+ initial_panes,
+ block_on_first_terminal,
should_change_focus_to_new_tab,
(client_id, is_web_client),
completion_tx,
@@ -469,6 +481,26 @@ pub(crate) fn plugin_thread_main(
let mut plugin_ids: HashMap<RunPluginOrAlias, Vec<PluginId>> = HashMap::new();
tab_layout = tab_layout.or_else(|| Some(layout.new_tab().0));
+
+ // Match initial_panes plugins to empty slots in the layout
+ if let Some(ref initial_panes_vec) = initial_panes {
+ if let Some(ref mut tiled_layout) = tab_layout {
+ for initial_pane in initial_panes_vec.iter() {
+ if let CommandOrPlugin::Plugin(run_plugin_or_alias) = initial_pane {
+ if !tiled_layout.replace_next_empty_slot_with_run(Run::Plugin(
+ run_plugin_or_alias.clone(),
+ )) {
+ log::warn!(
+ "More initial_panes provided than empty slots available"
+ );
+ break;
+ }
+ }
+ // Skip CommandOrPlugin::Command entries (handled by pty thread)
+ }
+ }
+ }
+
tab_layout.as_mut().map(|t| {
t.populate_plugin_aliases_in_layout(&plugin_aliases);
if let Some(cwd) = cwd.as_ref() {
@@ -481,7 +513,7 @@ pub(crate) fn plugin_thread_main(
.as_mut()
.map(|f| f.populate_run_plugin_if_needed(&plugin_aliases));
});
- let mut extracted_run_instructions = tab_layout
+ let extracted_run_instructions = tab_layout
.clone()
.unwrap_or_else(|| layout.new_tab().0)
.extract_run_instructions();
@@ -496,8 +528,10 @@ pub(crate) fn plugin_thread_main(
.filter(|f| !f.already_running)
.map(|f| f.run.clone())
.collect();
- extracted_run_instructions.append(&mut extracted_floating_plugins);
- for run_instruction in extracted_run_instructions {
+ let mut all_run_instructions = extracted_run_instructions;
+ all_run_instructions.append(&mut extracted_floating_plugins);
+
+ for run_instruction in all_run_instructions {
if let Some(Run::Plugin(run_plugin_or_alias)) = run_instruction {
let run_plugin = run_plugin_or_alias.get_run_plugin();
let cwd = run_plugin_or_alias
@@ -525,6 +559,8 @@ pub(crate) fn plugin_thread_main(
floating_panes_layout,
tab_index,
plugin_ids,
+ initial_panes,
+ block_on_first_terminal,
should_change_focus_to_new_tab,
(client_id, is_web_client),
completion_tx,
@@ -989,6 +1025,20 @@ pub(crate) fn plugin_thread_main(
.handle_pane_render_report(pane_render_report, shutdown_send.clone())
.non_fatal();
},
+ PluginInstruction::UserInput {
+ client_id,
+ action,
+ terminal_id,
+ cli_client_id,
+ } => {
+ // Fire Event::UserAction to all subscribed plugins with InterceptInput permission
+ let updates = vec![(
+ None,
+ None,
+ Event::UserAction(action, client_id, terminal_id, cli_client_id),
+ )];
+ wasm_bridge.update_plugins(updates, shutdown_send.clone())?;
+ },
PluginInstruction::Exit => {
break;
},