diff options
| author | Aram Drevekenin <aram@poor.dev> | 2024-07-22 18:30:18 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-22 18:30:18 +0200 |
| commit | ffbdb095ec5402455ac7f1cc8ef2f1bb8ebc8df2 (patch) | |
| tree | 99467c7156aa1b9c2fa6d0b65464e1b0c948c913 /zellij-server/src | |
| parent | docs(changelog): current process refresh fix (diff) | |
| download | sl0ppij-ffbdb095ec5402455ac7f1cc8ef2f1bb8ebc8df2.tar.gz sl0ppij-ffbdb095ec5402455ac7f1cc8ef2f1bb8ebc8df2.tar.xz sl0ppij-ffbdb095ec5402455ac7f1cc8ef2f1bb8ebc8df2.zip | |
feat(plugins): some APIs for controlling and receiving information about other panes (#3515)
* add context to opening command panes, and events for their start/finish
* show/hide other panes plugin apis
* get tests to pass
* style(fmt): rustfmt
* update plugin test snapshots
Diffstat (limited to 'zellij-server/src')
10 files changed, 135 insertions, 22 deletions
diff --git a/zellij-server/src/os_input_output.rs b/zellij-server/src/os_input_output.rs index 426d3485..099a3434 100644 --- a/zellij-server/src/os_input_output.rs +++ b/zellij-server/src/os_input_output.rs @@ -337,6 +337,7 @@ fn spawn_terminal( cwd, hold_on_close: false, hold_on_start: false, + ..Default::default() } }, TerminalAction::RunCommand(command) => command, 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 a1ab0475..f8262b52 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 @@ -1,6 +1,6 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 4400 +assertion_line: 4557 expression: "format!(\"{:#?}\", new_tab_event)" --- Some( @@ -16,6 +16,13 @@ Some( cwd: None, hold_on_close: true, hold_on_start: false, + originating_plugin: Some( + OriginatingPlugin { + plugin_id: 0, + client_id: 1, + context: {}, + }, + ), }, ), ), 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 935f72bb..a1247d5e 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 @@ -1,6 +1,6 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 4323 +assertion_line: 4479 expression: "format!(\"{:#?}\", new_tab_event)" --- Some( @@ -16,6 +16,13 @@ Some( cwd: None, hold_on_close: true, hold_on_start: false, + originating_plugin: Some( + OriginatingPlugin { + plugin_id: 0, + client_id: 1, + context: {}, + }, + ), }, ), ), 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 09752304..0ade1098 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 @@ -1,6 +1,6 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 4390 +assertion_line: 4401 expression: "format!(\"{:#?}\", new_tab_event)" --- Some( @@ -15,6 +15,7 @@ Some( ), hold_on_close: false, hold_on_start: false, + originating_plugin: None, }, ), ), 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 425190e1..3491f831 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 @@ -1,6 +1,6 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 4312 +assertion_line: 4323 expression: "format!(\"{:#?}\", new_tab_event)" --- Some( @@ -15,6 +15,7 @@ Some( ), hold_on_close: false, hold_on_start: false, + originating_plugin: None, }, ), ), diff --git a/zellij-server/src/plugins/wasm_bridge.rs b/zellij-server/src/plugins/wasm_bridge.rs index 00a7795b..ce68c109 100644 --- a/zellij-server/src/plugins/wasm_bridge.rs +++ b/zellij-server/src/plugins/wasm_bridge.rs @@ -1314,6 +1314,8 @@ fn check_event_permission( | Event::SessionUpdate(..) | Event::CopyToClipboard(..) | Event::SystemClipboardFailure + | Event::CommandPaneOpened(..) + | Event::CommandPaneExited(..) | Event::InputReceived => PermissionType::ReadApplicationState, _ => return (PermissionStatus::Granted, None), }; diff --git a/zellij-server/src/plugins/zellij_exports.rs b/zellij-server/src/plugins/zellij_exports.rs index 0006e048..8722d64a 100644 --- a/zellij-server/src/plugins/zellij_exports.rs +++ b/zellij-server/src/plugins/zellij_exports.rs @@ -18,7 +18,7 @@ use std::{ use wasmtime::{Caller, Linker}; use zellij_utils::data::{ CommandType, ConnectToSession, FloatingPaneCoordinates, HttpVerb, LayoutInfo, MessageToPlugin, - PermissionStatus, PermissionType, PluginPermission, + OriginatingPlugin, PermissionStatus, PermissionType, PluginPermission, }; use zellij_utils::input::permission::PermissionCache; use zellij_utils::{ @@ -99,13 +99,19 @@ fn host_run_plugin_command(caller: Caller<'_, PluginEnv>) { PluginCommand::OpenTerminalFloating(cwd, floating_pane_coordinates) => { open_terminal_floating(env, cwd.path.try_into()?, floating_pane_coordinates) }, - PluginCommand::OpenCommandPane(command_to_run) => { - open_command_pane(env, command_to_run) + PluginCommand::OpenCommandPane(command_to_run, context) => { + open_command_pane(env, command_to_run, context) }, PluginCommand::OpenCommandPaneFloating( command_to_run, floating_pane_coordinates, - ) => open_command_pane_floating(env, command_to_run, floating_pane_coordinates), + context, + ) => open_command_pane_floating( + env, + command_to_run, + floating_pane_coordinates, + context, + ), PluginCommand::SwitchTabTo(tab_index) => switch_tab_to(env, tab_index), PluginCommand::SetTimeout(seconds) => set_timeout(env, seconds), PluginCommand::ExecCmd(command_line) => exec_cmd(env, command_line), @@ -221,8 +227,8 @@ fn host_run_plugin_command(caller: Caller<'_, PluginEnv>) { PluginCommand::OpenTerminalInPlace(cwd) => { open_terminal_in_place(env, cwd.path.try_into()?) }, - PluginCommand::OpenCommandPaneInPlace(command_to_run) => { - open_command_pane_in_place(env, command_to_run) + PluginCommand::OpenCommandPaneInPlace(command_to_run, context) => { + open_command_pane_in_place(env, command_to_run, context) }, PluginCommand::RenameSession(new_session_name) => { rename_session(env, new_session_name) @@ -246,6 +252,12 @@ fn host_run_plugin_command(caller: Caller<'_, PluginEnv>) { PluginCommand::DumpSessionLayout => dump_session_layout(env), PluginCommand::CloseSelf => close_self(env), PluginCommand::Reconfigure(new_config) => reconfigure(env, new_config)?, + 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) + }, }, (PermissionStatus::Denied, permission) => { log::error!( @@ -530,7 +542,11 @@ fn open_terminal_in_place(env: &PluginEnv, cwd: PathBuf) { apply_action!(action, error_msg, env); } -fn open_command_pane(env: &PluginEnv, command_to_run: CommandToRun) { +fn open_command_pane( + env: &PluginEnv, + command_to_run: CommandToRun, + context: BTreeMap<String, String>, +) { let error_msg = || format!("failed to open command in plugin {}", env.name()); let command = command_to_run.path; let cwd = command_to_run.cwd.map(|cwd| env.plugin_cwd.join(cwd)); @@ -546,6 +562,11 @@ fn open_command_pane(env: &PluginEnv, command_to_run: CommandToRun) { direction, hold_on_close, hold_on_start, + originating_plugin: Some(OriginatingPlugin::new( + env.plugin_id, + env.client_id, + context, + )), }; let action = Action::NewTiledPane(direction, Some(run_command_action), name); apply_action!(action, error_msg, env); @@ -555,6 +576,7 @@ fn open_command_pane_floating( env: &PluginEnv, command_to_run: CommandToRun, floating_pane_coordinates: Option<FloatingPaneCoordinates>, + context: BTreeMap<String, String>, ) { let error_msg = || format!("failed to open command in plugin {}", env.name()); let command = command_to_run.path; @@ -571,12 +593,21 @@ fn open_command_pane_floating( direction, hold_on_close, hold_on_start, + originating_plugin: Some(OriginatingPlugin::new( + env.plugin_id, + env.client_id, + context, + )), }; let action = Action::NewFloatingPane(Some(run_command_action), name, floating_pane_coordinates); apply_action!(action, error_msg, env); } -fn open_command_pane_in_place(env: &PluginEnv, command_to_run: CommandToRun) { +fn open_command_pane_in_place( + env: &PluginEnv, + command_to_run: CommandToRun, + context: BTreeMap<String, String>, +) { let error_msg = || format!("failed to open command in plugin {}", env.name()); let command = command_to_run.path; let cwd = command_to_run.cwd.map(|cwd| env.plugin_cwd.join(cwd)); @@ -592,6 +623,11 @@ fn open_command_pane_in_place(env: &PluginEnv, command_to_run: CommandToRun) { direction, hold_on_close, hold_on_start, + originating_plugin: Some(OriginatingPlugin::new( + env.plugin_id, + env.client_id, + context, + )), }; let action = Action::NewInPlacePane(Some(run_command_action), name); apply_action!(action, error_msg, env); @@ -762,12 +798,28 @@ fn hide_self(env: &PluginEnv) -> Result<()> { .with_context(|| format!("failed to hide self")) } +fn hide_pane_with_id(env: &PluginEnv, pane_id: PaneId) -> Result<()> { + env.senders + .send_to_screen(ScreenInstruction::SuppressPane(pane_id, env.client_id)) + .with_context(|| format!("failed to hide self")) +} + fn show_self(env: &PluginEnv, should_float_if_hidden: bool) { let action = Action::FocusPluginPaneWithId(env.plugin_id, should_float_if_hidden); 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, + )); +} + fn close_self(env: &PluginEnv) { env.senders .send_to_screen(ScreenInstruction::ClosePane( @@ -1448,6 +1500,8 @@ fn check_command_permission( | PluginCommand::RenameSession(..) | PluginCommand::RenameTab(..) | PluginCommand::DisconnectOtherClients + | PluginCommand::ShowPaneWithId(..) + | PluginCommand::HidePaneWithId(..) | PluginCommand::KillSessions(..) => PermissionType::ChangeApplicationState, PluginCommand::UnblockCliPipeInput(..) | PluginCommand::BlockCliPipeInput(..) diff --git a/zellij-server/src/pty.rs b/zellij-server/src/pty.rs index 2d91e3ac..74d66a57 100644 --- a/zellij-server/src/pty.rs +++ b/zellij-server/src/pty.rs @@ -9,11 +9,12 @@ use crate::{ ClientId, ServerInstruction, }; use async_std::task::{self, JoinHandle}; +use std::sync::Arc; use std::{collections::HashMap, os::unix::io::RawFd, path::PathBuf}; use zellij_utils::nix::unistd::Pid; use zellij_utils::{ async_std, - data::FloatingPaneCoordinates, + data::{Event, FloatingPaneCoordinates}, errors::prelude::*, errors::{ContextType, PtyContext}, input::{ @@ -173,6 +174,24 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<Layout>) -> Result<()> { } else { None }; + + // if this command originated in a plugin, we send the plugin back an event + // to let it know the command started and which pane_id it has + if let Some(originating_plugin) = + run_command.and_then(|r| r.originating_plugin) + { + let update_event = + Event::CommandPaneOpened(pid, originating_plugin.context.clone()); + pty.bus + .senders + .send_to_plugin(PluginInstruction::Update(vec![( + Some(originating_plugin.plugin_id), + Some(originating_plugin.client_id), + update_event, + )])) + .with_context(err_context)?; + } + pty.bus .senders .send_to_screen(ScreenInstruction::NewPane( @@ -764,6 +783,7 @@ impl Pty { cwd, // note: this might also be filled by the calling function, eg. spawn_terminal hold_on_close: false, hold_on_start: false, + ..Default::default() }) }, } @@ -827,11 +847,13 @@ impl Pty { terminal_action }, }; - let (hold_on_start, hold_on_close) = match &terminal_action { - TerminalAction::RunCommand(run_command) => { - (run_command.hold_on_start, run_command.hold_on_close) - }, - _ => (false, false), + let (hold_on_start, hold_on_close, originating_plugin) = match &terminal_action { + TerminalAction::RunCommand(run_command) => ( + run_command.hold_on_start, + run_command.hold_on_close, + run_command.originating_plugin.clone(), + ), + _ => (false, false, None), }; if hold_on_start { @@ -847,9 +869,27 @@ impl Pty { return Ok((terminal_id, starts_held)); } + let originating_plugin = Arc::new(originating_plugin.clone()); let quit_cb = Box::new({ let senders = self.bus.senders.clone(); move |pane_id, exit_status, command| { + // if this command originated in a plugin, we send the plugin an event letting it + // know the command exited and some other useful information + if let PaneId::Terminal(pane_id) = pane_id { + if let Some(originating_plugin) = originating_plugin.as_ref() { + let update_event = Event::CommandPaneExited( + pane_id, + exit_status, + originating_plugin.context.clone(), + ); + let _ = senders.send_to_plugin(PluginInstruction::Update(vec![( + Some(originating_plugin.plugin_id), + Some(originating_plugin.client_id), + update_event, + )])); + } + } + if hold_on_close { let _ = senders.send_to_screen(ScreenInstruction::HoldPane( pane_id, diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_command_and_cwd.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_command_and_cwd.snap index 1e88d09c..0f9b59e1 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_command_and_cwd.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_command_and_cwd.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 1915 +assertion_line: 2306 expression: "format!(\"{:?}\", * received_pty_instructions.lock().unwrap())" --- -[SpawnTerminalVertically(Some(RunCommand(RunCommand { command: "htop", args: [], cwd: Some("/some/folder"), hold_on_close: true, hold_on_start: false })), None, 10), UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), Exit] +[SpawnTerminalVertically(Some(RunCommand(RunCommand { command: "htop", args: [], cwd: Some("/some/folder"), hold_on_close: true, hold_on_start: false, originating_plugin: None })), None, 10), UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), Exit] diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_floating_pane_and_coordinates.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_floating_pane_and_coordinates.snap index bb30c0d2..a1fd2b91 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_floating_pane_and_coordinates.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_floating_pane_and_coordinates.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2040 +assertion_line: 2349 expression: "format!(\"{:?}\", * received_pty_instructions.lock().unwrap())" --- -[SpawnTerminal(Some(RunCommand(RunCommand { command: "htop", args: [], cwd: Some("/some/folder"), hold_on_close: true, hold_on_start: false })), Some(true), None, Some(FloatingPaneCoordinates { x: Some(Fixed(10)), y: None, width: Some(Percent(20)), height: None }), ClientId(10)), UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), Exit] +[SpawnTerminal(Some(RunCommand(RunCommand { command: "htop", args: [], cwd: Some("/some/folder"), hold_on_close: true, hold_on_start: false, originating_plugin: None })), Some(true), None, Some(FloatingPaneCoordinates { x: Some(Fixed(10)), y: None, width: Some(Percent(20)), height: None }), ClientId(10)), UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), Exit] |
