diff options
| author | Aram Drevekenin <aram@poor.dev> | 2025-12-11 14:25:42 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-12-11 14:25:42 +0100 |
| commit | 693fa082def5ef0fe030cd7fdc3b1df051b35dc6 (patch) | |
| tree | b3f651462bbc1cd2fa5b2d79207343413ef6b83c /zellij-server/src/plugins | |
| parent | fix(zellij-server): unblock building on 32bit targets (#4484) (diff) | |
| download | sl0ppij-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')
73 files changed, 1290 insertions, 90 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; }, diff --git a/zellij-server/src/plugins/unit/plugin_tests.rs b/zellij-server/src/plugins/unit/plugin_tests.rs index 5f90ebbe..c0368fbc 100644 --- a/zellij-server/src/plugins/unit/plugin_tests.rs +++ b/zellij-server/src/plugins/unit/plugin_tests.rs @@ -9137,3 +9137,670 @@ pub fn before_close_plugin_event() { .unwrap(); assert_snapshot!(format!("{:#?}", sent_instruction)); } + +#[test] +#[ignore] +pub fn show_cursor_plugin_command() { + let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its + // destructor removes the directory + let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + let (plugin_thread_sender, screen_receiver, teardown) = + create_plugin_thread(Some(plugin_host_folder)); + let plugin_should_float = Some(false); + let plugin_title = Some("test_plugin".to_owned()); + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { + _allow_exec_host_cmd: false, + location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), + ..Default::default() + }); + let tab_index = 1; + let client_id = 1; + let size = Size { + cols: 121, + rows: 20, + }; + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let screen_thread = grant_permissions_and_log_actions_in_thread!( + received_screen_instructions, + ScreenInstruction::ShowPluginCursor, + screen_receiver, + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id + ); + + let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); + let _ = plugin_thread_sender.send(PluginInstruction::Load( + plugin_should_float, + false, + plugin_title, + run_plugin, + Some(tab_index), + None, + client_id, + size, + None, + None, + false, + None, + None, + None, + )); + + std::thread::sleep(std::time::Duration::from_millis(500)); + + let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![( + None, + Some(client_id), + Event::Key(KeyWithModifier::new(BareKey::Char('a')).with_super_modifier()), + )])); + + screen_thread.join().unwrap(); + teardown(); + + let show_cursor_instruction = received_screen_instructions + .lock() + .unwrap() + .iter() + .find_map(|i| { + if let ScreenInstruction::ShowPluginCursor(plugin_id, client_id, cursor_position) = i { + Some((*plugin_id, *client_id, *cursor_position)) + } else { + None + } + }); + + assert_snapshot!(format!("{:#?}", show_cursor_instruction)); +} + +#[test] +#[ignore] +pub fn hide_cursor_plugin_command() { + let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its + // destructor removes the directory + let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + let (plugin_thread_sender, screen_receiver, teardown) = + create_plugin_thread(Some(plugin_host_folder)); + let plugin_should_float = Some(false); + let plugin_title = Some("test_plugin".to_owned()); + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { + _allow_exec_host_cmd: false, + location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), + ..Default::default() + }); + let tab_index = 1; + let client_id = 1; + let size = Size { + cols: 121, + rows: 20, + }; + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let screen_thread = grant_permissions_and_log_actions_in_thread!( + received_screen_instructions, + ScreenInstruction::ShowPluginCursor, + screen_receiver, + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id + ); + + let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); + + let _ = plugin_thread_sender.send(PluginInstruction::Load( + plugin_should_float, + false, + plugin_title, + run_plugin, + Some(tab_index), + None, + client_id, + size, + None, + None, + false, + None, + None, + None, + )); + + std::thread::sleep(std::time::Duration::from_millis(500)); + + let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![( + None, + Some(client_id), + Event::Key(KeyWithModifier::new(BareKey::Char('b')).with_super_modifier()), + )])); + + screen_thread.join().unwrap(); + teardown(); + + let hide_cursor_instruction = received_screen_instructions + .lock() + .unwrap() + .iter() + .find_map(|i| { + if let ScreenInstruction::ShowPluginCursor(plugin_id, client_id, cursor_position) = i { + Some((*plugin_id, *client_id, *cursor_position)) + } else { + None + } + }); + + assert_snapshot!(format!("{:#?}", hide_cursor_instruction)); +} + +#[test] +#[ignore] +pub fn copy_to_clipboard_plugin_command() { + let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its + // destructor removes the directory + let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + let (plugin_thread_sender, screen_receiver, teardown) = + create_plugin_thread(Some(plugin_host_folder)); + let plugin_should_float = Some(false); + let plugin_title = Some("test_plugin".to_owned()); + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { + _allow_exec_host_cmd: false, + location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), + ..Default::default() + }); + let tab_index = 1; + let client_id = 1; + let size = Size { + cols: 121, + rows: 20, + }; + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let screen_thread = grant_permissions_and_log_actions_in_thread!( + received_screen_instructions, + ScreenInstruction::CopyTextToClipboard, + screen_receiver, + 1, + &PermissionType::WriteToClipboard, + cache_path, + plugin_thread_sender, + client_id + ); + + let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); + let _ = plugin_thread_sender.send(PluginInstruction::Load( + plugin_should_float, + false, + plugin_title, + run_plugin, + Some(tab_index), + None, + client_id, + size, + None, + None, + false, + None, + None, + None, + )); + + std::thread::sleep(std::time::Duration::from_millis(500)); + + let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![( + None, + Some(client_id), + Event::Key(KeyWithModifier::new(BareKey::Char('c')).with_super_modifier()), + )])); + + screen_thread.join().unwrap(); + teardown(); + + let copy_instruction = received_screen_instructions + .lock() + .unwrap() + .iter() + .find_map(|i| { + if let ScreenInstruction::CopyTextToClipboard(text, plugin_id) = i { + Some((text.clone(), *plugin_id)) + } else { + None + } + }); + + assert_snapshot!(format!("{:#?}", copy_instruction)); +} + +#[test] +#[ignore] +pub fn run_action_plugin_command() { + let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its + // destructor removes the directory + let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + let (plugin_thread_sender, screen_receiver, teardown) = + create_plugin_thread(Some(plugin_host_folder)); + let plugin_should_float = Some(false); + let plugin_title = Some("test_plugin".to_owned()); + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { + _allow_exec_host_cmd: false, + location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), + ..Default::default() + }); + let tab_index = 1; + let client_id = 1; + let size = Size { + cols: 121, + rows: 20, + }; + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let screen_thread = grant_permissions_and_log_actions_in_thread!( + received_screen_instructions, + ScreenInstruction::MoveFocusLeft, + screen_receiver, + 1, + &PermissionType::RunActionsAsUser, + cache_path, + plugin_thread_sender, + client_id + ); + + let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); + let _ = plugin_thread_sender.send(PluginInstruction::Load( + plugin_should_float, + false, + plugin_title, + run_plugin, + Some(tab_index), + None, + client_id, + size, + None, + None, + false, + None, + None, + None, + )); + + std::thread::sleep(std::time::Duration::from_millis(500)); + + let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![( + None, + Some(client_id), + Event::Key(KeyWithModifier::new(BareKey::Char('d')).with_super_modifier()), + )])); + + screen_thread.join().unwrap(); + teardown(); + + let move_focus_instruction = received_screen_instructions + .lock() + .unwrap() + .iter() + .find_map(|i| { + if let ScreenInstruction::MoveFocusLeft(client_id, notification_end) = i { + Some((*client_id, notification_end.clone())) + } else { + None + } + }); + + assert_snapshot!(format!("{:#?}", move_focus_instruction)); +} + +#[test] +#[ignore] +pub fn send_sigint_to_pane_id_plugin_command() { + let temp_folder = tempdir().unwrap(); + let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + let (plugin_thread_sender, pty_receiver, screen_receiver, teardown) = + create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); + + let received_pty_instructions = Arc::new(Mutex::new(vec![])); + let client_id = 1; + + let pty_thread = log_actions_in_thread!( + received_pty_instructions, + PtyInstruction::SendSigintToPaneId, + pty_receiver, + 1 + ); + + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let _screen_thread = grant_permissions_and_log_actions_in_thread_naked_variant!( + received_screen_instructions, + ScreenInstruction::Exit, + screen_receiver, + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id + ); + + let plugin_should_float = Some(false); + let plugin_title = Some("test_plugin".to_owned()); + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { + _allow_exec_host_cmd: false, + location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), + ..Default::default() + }); + let tab_index = 1; + let size = Size { + cols: 121, + rows: 20, + }; + + let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); + let _ = plugin_thread_sender.send(PluginInstruction::Load( + plugin_should_float, + false, + plugin_title, + run_plugin, + Some(tab_index), + None, + client_id, + size, + None, + None, + false, + None, + None, + None, + )); + + std::thread::sleep(std::time::Duration::from_millis(500)); + + let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![( + None, + Some(client_id), + Event::Key(KeyWithModifier::new(BareKey::Char('e')).with_super_modifier()), + )])); + + pty_thread.join().unwrap(); + teardown(); + + let sigint_instruction = received_pty_instructions + .lock() + .unwrap() + .iter() + .find_map(|i| { + if let PtyInstruction::SendSigintToPaneId(pane_id) = i { + Some(*pane_id) + } else { + None + } + }); + + assert_snapshot!(format!("{:#?}", sigint_instruction)); +} + +#[test] +#[ignore] +pub fn send_sigkill_to_pane_id_plugin_command() { + let temp_folder = tempdir().unwrap(); + let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + let (plugin_thread_sender, pty_receiver, screen_receiver, teardown) = + create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); + + let received_pty_instructions = Arc::new(Mutex::new(vec![])); + let client_id = 1; + + let pty_thread = log_actions_in_thread!( + received_pty_instructions, + PtyInstruction::SendSigkillToPaneId, + pty_receiver, + 1 + ); + + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let _screen_thread = grant_permissions_and_log_actions_in_thread_naked_variant!( + received_screen_instructions, + ScreenInstruction::Exit, + screen_receiver, + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id + ); + + let plugin_should_float = Some(false); + let plugin_title = Some("test_plugin".to_owned()); + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { + _allow_exec_host_cmd: false, + location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), + ..Default::default() + }); + let tab_index = 1; + let size = Size { + cols: 121, + rows: 20, + }; + + let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); + let _ = plugin_thread_sender.send(PluginInstruction::Load( + plugin_should_float, + false, + plugin_title, + run_plugin, + Some(tab_index), + None, + client_id, + size, + None, + None, + false, + None, + None, + None, + )); + + std::thread::sleep(std::time::Duration::from_millis(500)); + + let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![( + None, + Some(client_id), + Event::Key(KeyWithModifier::new(BareKey::Char('f')).with_super_modifier()), + )])); + + pty_thread.join().unwrap(); + teardown(); + + let sigkill_instruction = received_pty_instructions + .lock() + .unwrap() + .iter() + .find_map(|i| { + if let PtyInstruction::SendSigkillToPaneId(pane_id) = i { + Some(*pane_id) + } else { + None + } + }); + + assert_snapshot!(format!("{:#?}", sigkill_instruction)); +} + +#[test] +#[ignore] +pub fn copy_to_clipboard_without_permission() { + let temp_folder = tempdir().unwrap(); + let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + let (plugin_thread_sender, screen_receiver, teardown) = + create_plugin_thread(Some(plugin_host_folder)); + + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let client_id = 1; + + // This test denies the permission and expects no CopyTextToClipboard instruction + let screen_thread = deny_permissions_and_log_actions_in_thread!( + received_screen_instructions, + ScreenInstruction::CopyTextToClipboard, + screen_receiver, + 1, + &PermissionType::WriteToClipboard, + cache_path, + plugin_thread_sender, + client_id + ); + + let plugin_should_float = Some(false); + let plugin_title = Some("test_plugin".to_owned()); + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { + _allow_exec_host_cmd: false, + location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), + ..Default::default() + }); + let tab_index = 1; + let size = Size { + cols: 121, + rows: 20, + }; + + let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); + let _ = plugin_thread_sender.send(PluginInstruction::Load( + plugin_should_float, + false, + plugin_title, + run_plugin, + Some(tab_index), + None, + client_id, + size, + None, + None, + false, + None, + None, + None, + )); + + std::thread::sleep(std::time::Duration::from_millis(500)); + + let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![( + None, + Some(client_id), + Event::Key(KeyWithModifier::new(BareKey::Char('c')).with_super_modifier()), + )])); + + // Give it time to potentially (incorrectly) send the instruction + std::thread::sleep(std::time::Duration::from_millis(1000)); + + let _ = plugin_thread_sender.send(PluginInstruction::Exit); + screen_thread.join().unwrap(); + teardown(); + + let copy_instruction = received_screen_instructions + .lock() + .unwrap() + .iter() + .find_map(|i| { + if let ScreenInstruction::CopyTextToClipboard(text, plugin_id) = i { + Some((text.clone(), *plugin_id)) + } else { + None + } + }); + + // Should be None because permission was denied + assert_snapshot!(format!("{:#?}", copy_instruction)); +} + +#[test] +#[ignore] +pub fn run_action_without_permission() { + let temp_folder = tempdir().unwrap(); + let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + let (plugin_thread_sender, screen_receiver, teardown) = + create_plugin_thread(Some(plugin_host_folder)); + + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let client_id = 1; + + let screen_thread = deny_permissions_and_log_actions_in_thread!( + received_screen_instructions, + ScreenInstruction::MoveFocusLeft, + screen_receiver, + 1, + &PermissionType::RunActionsAsUser, + cache_path, + plugin_thread_sender, + client_id + ); + + let plugin_should_float = Some(false); + let plugin_title = Some("test_plugin".to_owned()); + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { + _allow_exec_host_cmd: false, + location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), + ..Default::default() + }); + let tab_index = 1; + let size = Size { + cols: 121, + rows: 20, + }; + + let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); + let _ = plugin_thread_sender.send(PluginInstruction::Load( + plugin_should_float, + false, + plugin_title, + run_plugin, + Some(tab_index), + None, + client_id, + size, + None, + None, + false, + None, + None, + None, + )); + + std::thread::sleep(std::time::Duration::from_millis(500)); + + let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![( + None, + Some(client_id), + Event::Key(KeyWithModifier::new(BareKey::Char('d')).with_super_modifier()), + )])); + + std::thread::sleep(std::time::Duration::from_millis(1000)); + + let _ = plugin_thread_sender.send(PluginInstruction::Exit); + screen_thread.join().unwrap(); + teardown(); + + let move_focus_instruction = received_screen_instructions + .lock() + .unwrap() + .iter() + .find_map(|i| { + if let ScreenInstruction::MoveFocusLeft(client_id, notification_end) = i { + Some((*client_id, notification_end.clone())) + } else { + None + } + }); + + // Should be None because permission was denied + assert_snapshot!(format!("{:#?}", move_focus_instruction)); +} diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__clear_screen_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__clear_screen_plugin_command.snap index 975e20a3..88023c4b 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__clear_screen_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__clear_screen_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_focus_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_focus_plugin_command.snap index 133b23ff..38179b85 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_focus_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_focus_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_focused_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_focused_tab_plugin_command.snap index cdaa2362..d0312218 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_focused_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_focused_tab_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_plugin_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_plugin_pane_plugin_command.snap index cbf3c8c2..b795da46 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_plugin_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_plugin_pane_plugin_command.snap @@ -12,6 +12,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), None, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_terminal_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_terminal_pane_plugin_command.snap index 1041e20f..97e61a45 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_terminal_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__close_terminal_pane_plugin_command.snap @@ -12,6 +12,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), None, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__copy_to_clipboard_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__copy_to_clipboard_plugin_command.snap new file mode 100644 index 00000000..cc4717e3 --- /dev/null +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__copy_to_clipboard_plugin_command.snap @@ -0,0 +1,10 @@ +--- +source: zellij-server/src/plugins/./unit/plugin_tests.rs +expression: "format!(\"{:#?}\", copy_instruction)" +--- +Some( + ( + "test clipboard text", + 0, + ), +) diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__copy_to_clipboard_without_permission.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__copy_to_clipboard_without_permission.snap new file mode 100644 index 00000000..333c0389 --- /dev/null +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__copy_to_clipboard_without_permission.snap @@ -0,0 +1,5 @@ +--- +source: zellij-server/src/plugins/./unit/plugin_tests.rs +expression: "format!(\"{:#?}\", copy_instruction)" +--- +None diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__detach_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__detach_plugin_command.snap index ea71beac..1de9477d 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__detach_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__detach_plugin_command.snap @@ -11,6 +11,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__edit_scrollback_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__edit_scrollback_plugin_command.snap index cc572e0c..370a7bbf 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__edit_scrollback_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__edit_scrollback_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_next_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_next_pane_plugin_command.snap index f8cf4623..3ef17f9d 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_next_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_next_pane_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_or_create_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_or_create_tab_plugin_command.snap index 305eb5a5..fbd45fd0 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_or_create_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_or_create_tab_plugin_command.snap @@ -18,6 +18,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_plugin_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_plugin_pane_plugin_command.snap index 6b98856a..31a63f73 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_plugin_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_plugin_pane_plugin_command.snap @@ -8,11 +8,14 @@ Some( 1, ), false, + false, 1, Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_previous_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_previous_pane_plugin_command.snap index 0b37d318..8073ceb8 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_previous_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_previous_pane_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_terminal_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_terminal_pane_plugin_command.snap index 345f0479..0a3a1d23 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_terminal_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__focus_terminal_pane_plugin_command.snap @@ -8,11 +8,14 @@ Some( 1, ), false, + false, 1, Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_next_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_next_tab_plugin_command.snap index ca2edc5f..c76a5ecc 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_next_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_next_tab_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_previous_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_previous_tab_plugin_command.snap index 1451fa50..f4653b62 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_previous_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_previous_tab_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_tab.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_tab.snap index 13bbdb4a..48cf0870 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_tab.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_tab.snap @@ -12,6 +12,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_tab_name_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_tab_name_plugin_command.snap index 3fd2e40f..7e45c1fc 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_tab_name_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__go_to_tab_name_plugin_command.snap @@ -18,6 +18,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__granted_permission_request_result.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__granted_permission_request_result.snap index 28c7dedc..91ec8a9b 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__granted_permission_request_result.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__granted_permission_request_result.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 5505 expression: "format!(\"{:#?}\", permissions)" --- Some( @@ -15,5 +14,7 @@ Some( ReadCliPipes, MessageAndLaunchOtherPlugins, Reconfigure, + RunActionsAsUser, + WriteToClipboard, ], ) diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__hide_cursor_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__hide_cursor_plugin_command.snap new file mode 100644 index 00000000..31880c73 --- /dev/null +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__hide_cursor_plugin_command.snap @@ -0,0 +1,11 @@ +--- +source: zellij-server/src/plugins/./unit/plugin_tests.rs +expression: "format!(\"{:#?}\", hide_cursor_instruction)" +--- +Some( + ( + 0, + 1, + None, + ), +) diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_focus_or_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_focus_or_tab_plugin_command.snap index c3b1d5f2..94419199 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_focus_or_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_focus_or_tab_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_focus_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_focus_plugin_command.snap index 72b7dc15..f901ba75 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_focus_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_focus_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_pane_plugin_command.snap index b9306571..1c2a8fc6 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_pane_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_pane_with_direction_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_pane_with_direction_plugin_command.snap index 9da82855..51f2cc15 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_pane_with_direction_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__move_pane_with_direction_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tab_plugin_command.snap index 1213308e..128c7abe 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tab_plugin_command.snap @@ -17,6 +17,8 @@ Some( [], [], ), + None, + false, true, ( 1, @@ -26,6 +28,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tabs_with_layout_plugin_command-2.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tabs_with_layout_plugin_command-2.snap index bc4faa99..1c74a94b 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tabs_with_layout_plugin_command-2.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tabs_with_layout_plugin_command-2.snap @@ -63,6 +63,8 @@ Some( [], [], ), + None, + false, false, ( 1, @@ -72,6 +74,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tabs_with_layout_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tabs_with_layout_plugin_command.snap index 2ba4de2a..889a6e9d 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tabs_with_layout_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_tabs_with_layout_plugin_command.snap @@ -63,6 +63,8 @@ Some( [], [], ), + None, + false, true, ( 1, @@ -72,6 +74,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__next_swap_layout_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__next_swap_layout_plugin_command.snap index 21c4257c..87c3264c 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__next_swap_layout_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__next_swap_layout_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_floating_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_floating_plugin_command.snap index ac0838cc..3afcead6 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_floating_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_floating_plugin_command.snap @@ -38,6 +38,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_plugin_command.snap index ca751a22..596700c5 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_plugin_command.snap @@ -38,6 +38,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_floating_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_floating_plugin_command.snap index eb598cf0..be8503de 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_floating_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_floating_plugin_command.snap @@ -36,6 +36,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_plugin_command.snap index d235c416..b899e596 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_plugin_command.snap @@ -36,6 +36,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_floating_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_floating_plugin_command.snap index cde191a5..fc2087d6 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_floating_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_floating_plugin_command.snap @@ -38,6 +38,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_plugin_command.snap index 89986fd2..4d2689db 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_plugin_command.snap @@ -38,6 +38,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_floating_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_floating_plugin_command.snap index b2f0f9ae..b42943fc 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_floating_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_floating_plugin_command.snap @@ -31,6 +31,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_plugin_command.snap index 5cc2ce7c..dd197b76 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_plugin_command.snap @@ -31,6 +31,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), false, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__page_scroll_down_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__page_scroll_down_plugin_command.snap index d85ffc61..5292281b 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__page_scroll_down_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__page_scroll_down_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__page_scroll_up_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__page_scroll_up_plugin_command.snap index 014ac3d3..5709731c 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__page_scroll_up_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__page_scroll_up_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__previous_swap_layout_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__previous_swap_layout_plugin_command.snap index b35b3b0b..523e76fd 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__previous_swap_layout_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__previous_swap_layout_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__quit_zellij_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__quit_zellij_plugin_command.snap index d00a7663..5057701a 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__quit_zellij_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__quit_zellij_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_plugin_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_plugin_pane_plugin_command.snap index 5816c283..119444e2 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_plugin_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_plugin_pane_plugin_command.snap @@ -33,6 +33,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_tab_plugin_command.snap index 9450f7c0..4846cd65 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_tab_plugin_command.snap @@ -23,6 +23,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_terminal_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_terminal_pane_plugin_command.snap index f23a792c..53b81db8 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_terminal_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__rename_terminal_pane_plugin_command.snap @@ -35,6 +35,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__request_plugin_permissions.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__request_plugin_permissions.snap index 75f47da7..1400f081 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__request_plugin_permissions.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__request_plugin_permissions.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 5414 expression: "format!(\"{:#?}\", new_tab_event)" --- Some( @@ -17,5 +16,7 @@ Some( ReadCliPipes, MessageAndLaunchOtherPlugins, Reconfigure, + WriteToClipboard, + RunActionsAsUser, ], ) diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__resize_focused_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__resize_focused_pane_plugin_command.snap index 37275f43..0184c9a6 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__resize_focused_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__resize_focused_pane_plugin_command.snap @@ -14,6 +14,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__resize_focused_pane_with_direction_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__resize_focused_pane_with_direction_plugin_command.snap index d9fa542d..71766b1e 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__resize_focused_pane_with_direction_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__resize_focused_pane_with_direction_plugin_command.snap @@ -16,6 +16,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__run_action_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__run_action_plugin_command.snap new file mode 100644 index 00000000..dcbf7004 --- /dev/null +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__run_action_plugin_command.snap @@ -0,0 +1,17 @@ +--- +source: zellij-server/src/plugins/./unit/plugin_tests.rs +expression: "format!(\"{:#?}\", move_focus_instruction)" +--- +Some( + ( + 1, + Some( + NotificationEnd { + channel: None, + exit_status: None, + unblock_condition: None, + affected_pane_id: None, + }, + ), + ), +) diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__run_action_without_permission.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__run_action_without_permission.snap new file mode 100644 index 00000000..102abab0 --- /dev/null +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__run_action_without_permission.snap @@ -0,0 +1,5 @@ +--- +source: zellij-server/src/plugins/./unit/plugin_tests.rs +expression: "format!(\"{:#?}\", move_focus_instruction)" +--- +None diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_down_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_down_plugin_command.snap index c8605a1c..738a7625 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_down_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_down_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_to_bottom_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_to_bottom_plugin_command.snap index 410902d5..339ea8c4 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_to_bottom_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_to_bottom_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_to_top_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_to_top_plugin_command.snap index 9f2effac..5c0b9088 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_to_top_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_to_top_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_up_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_up_plugin_command.snap index acc0d6a6..d0250b34 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_up_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__scroll_up_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_configuration_to_plugins.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_configuration_to_plugins.snap index aa9592c2..14438cf8 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_configuration_to_plugins.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_configuration_to_plugins.snap @@ -18,6 +18,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_sigint_to_pane_id_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_sigint_to_pane_id_plugin_command.snap new file mode 100644 index 00000000..a7558487 --- /dev/null +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_sigint_to_pane_id_plugin_command.snap @@ -0,0 +1,9 @@ +--- +source: zellij-server/src/plugins/./unit/plugin_tests.rs +expression: "format!(\"{:#?}\", sigint_instruction)" +--- +Some( + Terminal( + 1, + ), +) diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_sigkill_to_pane_id_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_sigkill_to_pane_id_plugin_command.snap new file mode 100644 index 00000000..fb7dc0a1 --- /dev/null +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_sigkill_to_pane_id_plugin_command.snap @@ -0,0 +1,9 @@ +--- +source: zellij-server/src/plugins/./unit/plugin_tests.rs +expression: "format!(\"{:#?}\", sigkill_instruction)" +--- +Some( + Terminal( + 1, + ), +) diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_cursor_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_cursor_plugin_command.snap new file mode 100644 index 00000000..5b53f360 --- /dev/null +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_cursor_plugin_command.snap @@ -0,0 +1,16 @@ +--- +source: zellij-server/src/plugins/./unit/plugin_tests.rs +expression: "format!(\"{:#?}\", show_cursor_instruction)" +--- +Some( + ( + 0, + 1, + Some( + ( + 5, + 10, + ), + ), + ), +) diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_pane_with_id_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_pane_with_id_plugin_command.snap index 24f6c12f..457bebdc 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_pane_with_id_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_pane_with_id_plugin_command.snap @@ -8,6 +8,7 @@ Some( 1, ), true, + false, 1, None, ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_self_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_self_plugin_command.snap index a99b0230..41396ddb 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_self_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__show_self_plugin_command.snap @@ -8,11 +8,14 @@ Some( 0, ), false, + false, 1, Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__start_or_reload_plugin.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__start_or_reload_plugin.snap index 290247c0..845f37ba 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__start_or_reload_plugin.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__start_or_reload_plugin.snap @@ -21,6 +21,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_to_mode_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_to_mode_plugin_command.snap index 6df0b5df..b4ff3c00 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_to_mode_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_to_mode_plugin_command.snap @@ -330,6 +330,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_active_tab_sync_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_active_tab_sync_plugin_command.snap index f8959104..06cde256 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_active_tab_sync_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_active_tab_sync_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_focus_fullscreen_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_focus_fullscreen_plugin_command.snap index 34e96dae..44747b66 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_focus_fullscreen_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_focus_fullscreen_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_pane_embed_or_eject_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_pane_embed_or_eject_plugin_command.snap index 8f375b9c..8e24bff8 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_pane_embed_or_eject_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_pane_embed_or_eject_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_pane_frames_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_pane_frames_plugin_command.snap index e1bded4d..c91f66aa 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_pane_frames_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_pane_frames_plugin_command.snap @@ -8,6 +8,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_tab_plugin_command.snap index e088770b..32965d58 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_tab_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__undo_rename_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__undo_rename_pane_plugin_command.snap index 6c500286..99df8475 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__undo_rename_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__undo_rename_pane_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__undo_rename_tab_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__undo_rename_tab_plugin_command.snap index 54566d68..7836e7d2 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__undo_rename_tab_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__undo_rename_tab_plugin_command.snap @@ -9,6 +9,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_chars_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_chars_plugin_command.snap index 8bb05ce1..abf3d1a2 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_chars_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_chars_plugin_command.snap @@ -16,6 +16,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_plugin_command.snap index 8bb05ce1..abf3d1a2 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__write_plugin_command.snap @@ -16,6 +16,8 @@ Some( NotificationEnd { channel: None, exit_status: None, + unblock_condition: None, + affected_pane_id: None, }, ), ), diff --git a/zellij-server/src/plugins/wasm_bridge.rs b/zellij-server/src/plugins/wasm_bridge.rs index 5dd78d13..2453a0a1 100644 --- a/zellij-server/src/plugins/wasm_bridge.rs +++ b/zellij-server/src/plugins/wasm_bridge.rs @@ -113,7 +113,7 @@ impl LoadingContext { let plugin_own_data_dir = ZELLIJ_SESSION_CACHE_DIR .join(Url::from(&plugin_config.location).to_string()) .join(format!("{}-{}", plugin_id, client_id)); - let plugin_own_cache_dir = ZELLIJ_SESSION_CACHE_DIR + let plugin_own_cache_dir = ZELLIJ_CACHE_DIR .join(Url::from(&plugin_config.location).to_string()) .join(format!("plugin_cache")); let default_mode = wasm_bridge @@ -1901,9 +1901,11 @@ fn check_event_permission( | Event::EditPaneExited(..) | Event::FailedToWriteConfigToDisk(..) | Event::CommandPaneReRun(..) + | Event::CwdChanged(..) | Event::InputReceived => PermissionType::ReadApplicationState, Event::WebServerStatus(..) => PermissionType::StartWebServer, Event::PaneRenderReport(..) => PermissionType::ReadPaneContents, + Event::UserAction(..) => PermissionType::InterceptInput, _ => return (PermissionStatus::Granted, None), }; @@ -1943,54 +1945,63 @@ pub fn apply_event_to_plugin( mode_info.keybinds = running_plugin.store.data().keybinds.to_keybinds_vec(); mode_info.base_mode = Some(running_plugin.store.data().default_mode); } - let protobuf_event: ProtobufEvent = event - .clone() - .try_into() - .map_err(|e| anyhow!("Failed to convert to protobuf: {:?}", e))?; - let update = instance - .get_typed_func::<(), i32>(&mut running_plugin.store, "update") - .with_context(err_context)?; - wasi_write_object(running_plugin.store.data(), &protobuf_event.encode_to_vec()) - .with_context(err_context)?; - let should_render = update - .call(&mut running_plugin.store, ()) - .with_context(err_context)?; - let mut should_render = should_render == 1; - if let Event::PermissionRequestResult(..) = event { - // we always render in this case, otherwise the request permission screen stays on - // screen - should_render = true; - } - if rows > 0 && columns > 0 && should_render { - let rendered_bytes = instance - .get_typed_func::<(i32, i32), ()>(&mut running_plugin.store, "render") - .and_then(|render| { - render.call(&mut running_plugin.store, (rows as i32, columns as i32)) - }) - .map_err(|e| anyhow!(e)) - .and_then(|_| { - wasi_read_string(running_plugin.store.data()).map_err(|e| anyhow!(e)) - }) - .with_context(err_context)?; - let pipes_to_block_or_unblock = pipes_to_block_or_unblock(running_plugin, None); - let plugin_render_asset = PluginRenderAsset::new( - plugin_id, - client_id, - rendered_bytes.as_bytes().to_vec(), - ) - .with_pipes(pipes_to_block_or_unblock); - plugin_render_assets.push(plugin_render_asset); - } else { - // This is a bit of a hack to get around the fact that plugins are allowed not to - // render and still unblock CLI pipes - let pipes_to_block_or_unblock = pipes_to_block_or_unblock(running_plugin, None); - let plugin_render_asset = PluginRenderAsset::new(plugin_id, client_id, vec![]) - .with_pipes(pipes_to_block_or_unblock); - let _ = senders - .send_to_plugin(PluginInstruction::UnblockCliPipes(vec![ - plugin_render_asset, - ])) - .context("failed to unblock input pipe"); + let protobuf_event: Result<ProtobufEvent, _> = event.clone().try_into(); + match protobuf_event { + Ok(protobuf_event) => { + let update = instance + .get_typed_func::<(), i32>(&mut running_plugin.store, "update") + .with_context(err_context)?; + wasi_write_object(running_plugin.store.data(), &protobuf_event.encode_to_vec()) + .with_context(err_context)?; + let should_render = update + .call(&mut running_plugin.store, ()) + .with_context(err_context)?; + let mut should_render = should_render == 1; + if let Event::PermissionRequestResult(..) = event { + // we always render in this case, otherwise the request permission screen stays on + // screen + should_render = true; + } + if rows > 0 && columns > 0 && should_render { + let rendered_bytes = instance + .get_typed_func::<(i32, i32), ()>(&mut running_plugin.store, "render") + .and_then(|render| { + render + .call(&mut running_plugin.store, (rows as i32, columns as i32)) + }) + .map_err(|e| anyhow!(e)) + .and_then(|_| { + wasi_read_string(running_plugin.store.data()) + .map_err(|e| anyhow!(e)) + }) + .with_context(err_context)?; + let pipes_to_block_or_unblock = + pipes_to_block_or_unblock(running_plugin, None); + let plugin_render_asset = PluginRenderAsset::new( + plugin_id, + client_id, + rendered_bytes.as_bytes().to_vec(), + ) + .with_pipes(pipes_to_block_or_unblock); + plugin_render_assets.push(plugin_render_asset); + } else { + // This is a bit of a hack to get around the fact that plugins are allowed not to + // render and still unblock CLI pipes + let pipes_to_block_or_unblock = + pipes_to_block_or_unblock(running_plugin, None); + let plugin_render_asset = + PluginRenderAsset::new(plugin_id, client_id, vec![]) + .with_pipes(pipes_to_block_or_unblock); + let _ = senders + .send_to_plugin(PluginInstruction::UnblockCliPipes(vec![ + plugin_render_asset, + ])) + .context("failed to unblock input pipe"); + } + }, + Err(e) => { + log::error!("Failed to convert to protobuf: {:?}", e); + }, } }, (PermissionStatus::Denied, permission) => { diff --git a/zellij-server/src/plugins/zellij_exports.rs b/zellij-server/src/plugins/zellij_exports.rs index 526b4bcb..f64a9e18 100644 --- a/zellij-server/src/plugins/zellij_exports.rs +++ b/zellij-server/src/plugins/zellij_exports.rs @@ -20,9 +20,9 @@ use std::{ }; use wasmi::{Caller, Linker}; use zellij_utils::data::{ - CommandType, ConnectToSession, FloatingPaneCoordinates, HttpVerb, KeyWithModifier, LayoutInfo, - MessageToPlugin, NewPanePlacement, OriginatingPlugin, PaneScrollbackResponse, PermissionStatus, - PermissionType, PluginPermission, + CommandType, ConnectToSession, Event, FloatingPaneCoordinates, GetPanePidResponse, HttpVerb, + KeyWithModifier, LayoutInfo, MessageToPlugin, NewPanePlacement, OriginatingPlugin, + PaneScrollbackResponse, PermissionStatus, PermissionType, PluginPermission, }; use zellij_utils::input::permission::PermissionCache; use zellij_utils::ipc::{ClientToServerMsg, IpcSenderWithContext}; @@ -39,7 +39,7 @@ use prost::Message; use zellij_utils::{ consts::{VERSION, ZELLIJ_SESSION_INFO_CACHE_DIR, ZELLIJ_SOCK_DIR}, data::{ - CommandToRun, Direction, Event, EventType, FileToOpen, InputMode, PluginCommand, PluginIds, + CommandToRun, Direction, EventType, FileToOpen, InputMode, PluginCommand, PluginIds, PluginMessage, Resize, ResizeStrategy, }, errors::prelude::*, @@ -50,7 +50,7 @@ use zellij_utils::{ }, plugin_api::{ event::ProtobufPaneScrollbackResponse, - plugin_command::ProtobufPluginCommand, + plugin_command::{ProtobufGetPanePidResponse, ProtobufPluginCommand}, plugin_ids::{ProtobufPluginIds, ProtobufZellijVersion}, }, }; @@ -104,6 +104,7 @@ fn host_run_plugin_command(mut caller: Caller<'_, PluginEnv>) { PluginCommand::Subscribe(event_list) => subscribe(env, event_list)?, PluginCommand::Unsubscribe(event_list) => unsubscribe(env, event_list)?, PluginCommand::SetSelectable(selectable) => set_selectable(env, selectable), + PluginCommand::ShowCursor(cursor_position) => show_cursor(env, cursor_position), PluginCommand::GetPluginIds => get_plugin_ids(env), PluginCommand::GetZellijVersion => get_zellij_version(env), PluginCommand::OpenFile(file_to_open, context) => { @@ -198,6 +199,7 @@ fn host_run_plugin_command(mut caller: Caller<'_, PluginEnv>) { PluginCommand::EditScrollback => edit_scrollback(env), PluginCommand::Write(bytes) => write(env, bytes), PluginCommand::WriteChars(chars) => write_chars(env, chars), + PluginCommand::CopyToClipboard(text) => copy_to_clipboard(env, text)?, PluginCommand::ToggleTab => toggle_tab(env), PluginCommand::MovePane => move_pane(env), PluginCommand::MovePaneWithDirection(direction) => { @@ -233,12 +235,26 @@ fn host_run_plugin_command(mut caller: Caller<'_, PluginEnv>) { PluginCommand::ClosePluginPane(plugin_pane_id) => { close_plugin_pane(env, plugin_pane_id) }, - PluginCommand::FocusTerminalPane(terminal_pane_id, should_float_if_hidden) => { - focus_terminal_pane(env, terminal_pane_id, should_float_if_hidden) - }, - PluginCommand::FocusPluginPane(plugin_pane_id, should_float_if_hidden) => { - focus_plugin_pane(env, plugin_pane_id, should_float_if_hidden) - }, + PluginCommand::FocusTerminalPane( + terminal_pane_id, + should_float_if_hidden, + should_be_in_place_if_hidden, + ) => focus_terminal_pane( + env, + terminal_pane_id, + should_float_if_hidden, + should_be_in_place_if_hidden, + ), + PluginCommand::FocusPluginPane( + plugin_pane_id, + should_float_if_hidden, + should_be_in_place_if_hidden, + ) => focus_plugin_pane( + env, + plugin_pane_id, + should_float_if_hidden, + should_be_in_place_if_hidden, + ), PluginCommand::RenameTerminalPane(terminal_pane_id, new_name) => { rename_terminal_pane(env, terminal_pane_id, &new_name) }, @@ -317,9 +333,16 @@ fn host_run_plugin_command(mut caller: Caller<'_, PluginEnv>) { PluginCommand::HidePaneWithId(pane_id) => { hide_pane_with_id(env, pane_id.into())? }, - PluginCommand::ShowPaneWithId(pane_id, should_float_if_hidden) => { - show_pane_with_id(env, pane_id.into(), should_float_if_hidden) - }, + PluginCommand::ShowPaneWithId( + pane_id, + should_float_if_hidden, + should_focus_pane, + ) => show_pane_with_id( + env, + pane_id.into(), + should_float_if_hidden, + should_focus_pane, + ), PluginCommand::OpenCommandPaneBackground(command_to_run, context) => { open_command_pane_background(env, command_to_run, context) }, @@ -342,6 +365,13 @@ fn host_run_plugin_command(mut caller: Caller<'_, PluginEnv>) { PluginCommand::WriteCharsToPaneId(chars, pane_id) => { write_chars_to_pane_id(env, chars, pane_id.into()) }, + PluginCommand::SendSigintToPaneId(pane_id) => { + send_sigint_to_pane_id(env, pane_id.into()) + }, + PluginCommand::SendSigkillToPaneId(pane_id) => { + send_sigkill_to_pane_id(env, pane_id.into()) + }, + PluginCommand::GetPanePid { pane_id } => get_pane_pid(env, pane_id.into()), PluginCommand::MovePaneWithPaneId(pane_id) => { move_pane_with_pane_id(env, pane_id.into()) }, @@ -509,11 +539,14 @@ fn host_run_plugin_command(mut caller: Caller<'_, PluginEnv>) { PluginCommand::ReplacePaneWithExistingPane( pane_id_to_replace, existing_pane_id, + suppress_replaced_pane, ) => replace_pane_with_existing_pane( &mut env, pane_id_to_replace.into(), existing_pane_id.into(), + suppress_replaced_pane, ), + PluginCommand::RunAction(action, context) => run_action(&env, action, context), }, (PermissionStatus::Denied, permission) => { log::error!( @@ -595,6 +628,27 @@ fn set_selectable(env: &PluginEnv, selectable: bool) { .non_fatal(); } +fn show_cursor(env: &PluginEnv, cursor_position: Option<(usize, usize)>) { + env.senders + .send_to_screen(ScreenInstruction::ShowPluginCursor( + env.plugin_id, + env.client_id, + cursor_position, + )) + .with_context(|| { + format!( + "failed to {} plugin cursor from plugin {}", + if cursor_position.is_some() { + "show" + } else { + "hide" + }, + env.name() + ) + }) + .non_fatal(); +} + fn request_permission(env: &PluginEnv, permissions: Vec<PermissionType>) -> Result<()> { if PermissionCache::from_path_or_default(None) .check_permissions(env.plugin.location.to_string(), &permissions) @@ -680,10 +734,74 @@ fn open_file(env: &PluginEnv, file_to_open: FileToOpen, context: BTreeMap<String in_place, start_suppressed, coordinates: None, + near_current_pane: false, }; apply_action!(action, error_msg, env); } +fn run_action(env: &PluginEnv, mut action: Action, context: BTreeMap<String, String>) { + // Clone the necessary data to move into the thread + action.populate_originating_plugin(OriginatingPlugin::new( + env.plugin_id, + env.client_id, + context.clone(), + )); + let action_clone = action.clone(); + let client_id = env.client_id; + let plugin_id = env.plugin_id; + let senders = env.senders.clone(); + let capabilities = env.capabilities.clone(); + let client_attributes = env.client_attributes.clone(); + let default_shell = env.default_shell.clone(); + let default_layout = env.default_layout.clone(); + let keybinds = env.keybinds.clone(); + let default_mode = env.default_mode.clone(); + let plugin_name = env.name().to_string(); + + // Spawn a new thread to execute the action + thread::spawn(move || { + // Execute the action and capture the result + let pane_id = match route_action( + action, + client_id, + None, + Some(PaneId::Plugin(plugin_id)), + senders.clone(), + capabilities, + client_attributes, + default_shell, + default_layout, + None, + keybinds, + default_mode, + None, + ) { + Ok((_should_break, result)) => { + // Extract pane_id from ActionCompletionResult + result.and_then(|r| r.affected_pane_id) + }, + Err(e) => { + log::error!("failed to run action in plugin {}: {:?}", plugin_name, e); + None + }, + }; + + // After action completes, send ActionComplete event with context + // Convert server PaneId to zellij_utils PaneId + let pane_id_for_event = pane_id.map(|p| p.into()); + let updates = vec![( + Some(plugin_id), + Some(client_id), + Event::ActionComplete(action_clone, pane_id_for_event, context), + )]; + + // Send the ActionComplete event back to the plugin + if let Err(e) = senders.send_to_plugin(PluginInstruction::Update(updates)) { + log::error!("Failed to send ActionComplete event: {:?}", e); + } + }); +} + fn open_file_floating( env: &PluginEnv, file_to_open: FileToOpen, @@ -708,6 +826,7 @@ fn open_file_floating( in_place, start_suppressed, coordinates: floating_pane_coordinates, + near_current_pane: false, }; apply_action!(action, error_msg, env); } @@ -736,6 +855,7 @@ fn open_file_in_place( in_place, start_suppressed, coordinates: None, + near_current_pane: false, }; apply_action!(action, error_msg, env); } @@ -845,6 +965,7 @@ fn open_terminal(env: &PluginEnv, cwd: PathBuf) { direction: None, command: run_command_action, pane_name: None, + near_current_pane: false, }; apply_action!(action, error_msg, env); } @@ -894,6 +1015,7 @@ fn open_terminal_floating( command: run_command_action, pane_name: None, coordinates: floating_pane_coordinates, + near_current_pane: false, }; apply_action!(action, error_msg, env); } @@ -942,6 +1064,9 @@ fn open_terminal_in_place(env: &PluginEnv, cwd: PathBuf) { let action = Action::NewInPlacePane { command: run_command_action, pane_name: None, + near_current_pane: false, + pane_id_to_replace: None, + close_replace_pane: false, }; apply_action!(action, error_msg, env); } @@ -1044,6 +1169,7 @@ fn open_command_pane( direction, command: Some(run_command_action), pane_name: name, + near_current_pane: false, }; apply_action!(action, error_msg, env); } @@ -1120,6 +1246,7 @@ fn open_command_pane_floating( command: Some(run_command_action), pane_name: name, coordinates: floating_pane_coordinates, + near_current_pane: false, }; apply_action!(action, error_msg, env); } @@ -1195,6 +1322,9 @@ fn open_command_pane_in_place( let action = Action::NewInPlacePane { command: Some(run_command_action), pane_name: name, + near_current_pane: false, + pane_id_to_replace: None, + close_replace_pane: false, }; apply_action!(action, error_msg, env); } @@ -1418,20 +1548,36 @@ fn show_self(env: &PluginEnv, should_float_if_hidden: bool) { let action = Action::FocusPluginPaneWithId { pane_id: env.plugin_id, should_float_if_hidden, + should_be_in_place_if_hidden: false, }; let error_msg = || format!("Failed to show self for plugin"); apply_action!(action, error_msg, env); } -fn show_pane_with_id(env: &PluginEnv, pane_id: PaneId, should_float_if_hidden: bool) { - let _ = env - .senders - .send_to_screen(ScreenInstruction::FocusPaneWithId( - pane_id, - should_float_if_hidden, - env.client_id, - None, - )); +fn show_pane_with_id( + env: &PluginEnv, + pane_id: PaneId, + should_float_if_hidden: bool, + should_focus_pane: bool, +) { + if should_focus_pane { + let _ = env + .senders + .send_to_screen(ScreenInstruction::FocusPaneWithId( + pane_id, + should_float_if_hidden, + false, + env.client_id, + None, + )); + } else { + let _ = env + .senders + .send_to_screen(ScreenInstruction::UnsuppressOrExpandPane( + pane_id, + should_float_if_hidden, + )); + } } fn close_self(env: &PluginEnv) { @@ -1524,6 +1670,8 @@ fn apply_layout(env: &PluginEnv, layout: Layout) { tab_name: None, should_change_focus_to_new_tab: true, cwd, + initial_panes: None, + first_pane_unblock_condition: None, }; tabs_to_open.push(action); } else { @@ -1542,6 +1690,8 @@ fn apply_layout(env: &PluginEnv, layout: Layout) { tab_name, should_change_focus_to_new_tab: should_focus_tab, cwd: cwd.clone(), + initial_panes: None, + first_pane_unblock_condition: None, }; tabs_to_open.push(action); } @@ -1562,6 +1712,8 @@ fn new_tab(env: &PluginEnv, name: Option<String>, cwd: Option<String>) { tab_name: name, should_change_focus_to_new_tab: true, cwd, + initial_panes: None, + first_pane_unblock_condition: None, }; let error_msg = || format!("Failed to open new tab"); apply_action!(action, error_msg, env); @@ -1741,6 +1893,12 @@ fn write_chars(env: &PluginEnv, chars_to_write: String) { apply_action!(action, error_msg, env); } +fn copy_to_clipboard(env: &PluginEnv, text: String) -> Result<()> { + env.senders + .send_to_screen(ScreenInstruction::CopyTextToClipboard(text, env.plugin_id)) + .with_context(|| format!("failed to copy to clipboard in plugin {}", env.name())) +} + fn toggle_tab(env: &PluginEnv) { let error_msg = || format!("Failed to toggle tab"); let action = Action::ToggleTab; @@ -1938,19 +2096,31 @@ fn close_plugin_pane(env: &PluginEnv, plugin_pane_id: u32) { .non_fatal(); } -fn focus_terminal_pane(env: &PluginEnv, terminal_pane_id: u32, should_float_if_hidden: bool) { +fn focus_terminal_pane( + env: &PluginEnv, + terminal_pane_id: u32, + should_float_if_hidden: bool, + should_be_in_place_if_hidden: bool, +) { let action = Action::FocusTerminalPaneWithId { pane_id: terminal_pane_id, should_float_if_hidden, + should_be_in_place_if_hidden, }; let error_msg = || format!("Failed to focus terminal pane"); apply_action!(action, error_msg, env); } -fn focus_plugin_pane(env: &PluginEnv, plugin_pane_id: u32, should_float_if_hidden: bool) { +fn focus_plugin_pane( + env: &PluginEnv, + plugin_pane_id: u32, + should_float_if_hidden: bool, + should_be_in_place_if_hidden: bool, +) { let action = Action::FocusPluginPaneWithId { pane_id: plugin_pane_id, should_float_if_hidden, + should_be_in_place_if_hidden, }; let error_msg = || format!("Failed to focus plugin pane"); apply_action!(action, error_msg, env); @@ -2237,6 +2407,92 @@ fn write_chars_to_pane_id(env: &PluginEnv, chars: String, pane_id: PaneId) { .send_to_screen(ScreenInstruction::WriteToPaneId(bytes, pane_id)); } +fn send_sigint_to_pane_id(env: &PluginEnv, pane_id: PaneId) { + let err_context = || { + format!( + "failed to send SIGINT to pane {:?} from plugin {}", + pane_id, + env.name() + ) + }; + + env.senders + .send_to_pty(PtyInstruction::SendSigintToPaneId(pane_id)) + .with_context(err_context) + .non_fatal(); +} + +fn send_sigkill_to_pane_id(env: &PluginEnv, pane_id: PaneId) { + let err_context = || { + format!( + "failed to send SIGKILL to pane {:?} from plugin {}", + pane_id, + env.name() + ) + }; + + env.senders + .send_to_pty(PtyInstruction::SendSigkillToPaneId(pane_id)) + .with_context(err_context) + .non_fatal(); +} + +fn get_pane_pid(env: &PluginEnv, pane_id: PaneId) { + use crossbeam::channel::RecvTimeoutError; + use std::time::Duration; + + let err_context = || { + format!( + "failed to get PID for pane {:?} from plugin {}", + pane_id, + env.name() + ) + }; + + // Create oneshot channel for response + let (response_sender, response_receiver) = crossbeam::channel::bounded(1); + + // Send request directly to PTY thread + env.senders + .send_to_pty(PtyInstruction::GetPanePid { + pane_id, + response_channel: response_sender, + }) + .with_context(err_context) + .non_fatal(); + + // Block waiting for response with 100ms timeout + let response = match response_receiver.recv_timeout(Duration::from_millis(100)) { + Ok(response) => response, + Err(RecvTimeoutError::Timeout) => { + log::error!( + "GetPanePid timed out after 5s for plugin {} requesting pane {:?}", + env.plugin_id, + pane_id + ); + GetPanePidResponse::Err(format!("Timeout retrieving PID for pane {:?}", pane_id)) + }, + Err(RecvTimeoutError::Disconnected) => { + log::error!( + "GetPanePid channel disconnected for plugin {} requesting pane {:?}", + env.plugin_id, + pane_id + ); + GetPanePidResponse::Err(format!( + "Channel disconnected while retrieving PID for pane {:?}", + pane_id + )) + }, + }; + + // Encode response and write to plugin's stdin + let protobuf_response = ProtobufGetPanePidResponse::from(response); + let serialized = protobuf_response.encode_to_vec(); + wasi_write_object(env, &serialized) + .with_context(err_context) + .non_fatal(); +} + fn move_pane_with_pane_id(env: &PluginEnv, pane_id: PaneId) { let _ = env .senders @@ -2666,12 +2922,14 @@ fn replace_pane_with_existing_pane( env: &mut PluginEnv, pane_to_replace: PaneId, existing_pane: PaneId, + suppress_replaced_pane: bool, ) { let _ = env .senders .send_to_screen(ScreenInstruction::ReplacePaneWithExistingPane( pane_to_replace, existing_pane, + suppress_replaced_pane, )); } @@ -2762,6 +3020,7 @@ fn check_command_permission( | PluginCommand::WriteChars(..) | PluginCommand::WriteToPaneId(..) | PluginCommand::WriteCharsToPaneId(..) => PermissionType::WriteToStdin, + PluginCommand::CopyToClipboard(..) => PermissionType::WriteToClipboard, PluginCommand::SwitchTabTo(..) | PluginCommand::SwitchToMode(..) | PluginCommand::NewTabsWithLayout(..) @@ -2842,14 +3101,16 @@ fn check_command_permission( | PluginCommand::FloatMultiplePanes(..) | PluginCommand::EmbedMultiplePanes(..) | PluginCommand::ReplacePaneWithExistingPane(..) - | PluginCommand::KillSessions(..) => PermissionType::ChangeApplicationState, + | PluginCommand::KillSessions(..) + | PluginCommand::SendSigintToPaneId(..) + | PluginCommand::SendSigkillToPaneId(..) => PermissionType::ChangeApplicationState, PluginCommand::UnblockCliPipeInput(..) | PluginCommand::BlockCliPipeInput(..) | PluginCommand::CliPipeOutput(..) => PermissionType::ReadCliPipes, PluginCommand::MessageToPlugin(..) => PermissionType::MessageAndLaunchOtherPlugins, - PluginCommand::ListClients | PluginCommand::DumpSessionLayout => { - PermissionType::ReadApplicationState - }, + PluginCommand::ListClients + | PluginCommand::DumpSessionLayout + | PluginCommand::GetPanePid { .. } => PermissionType::ReadApplicationState, PluginCommand::RebindKeys { .. } | PluginCommand::Reconfigure(..) => { PermissionType::Reconfigure }, @@ -2868,6 +3129,7 @@ fn check_command_permission( PermissionType::InterceptInput }, PluginCommand::GetPaneScrollback { .. } => PermissionType::ReadPaneContents, + PluginCommand::RunAction(..) => PermissionType::RunActionsAsUser, _ => return (PermissionStatus::Granted, None), }; |
