From 92e6f0ad19258017f2bfd19aa1520d36f7b684d6 Mon Sep 17 00:00:00 2001 From: Aram Drevekenin Date: Sat, 1 Feb 2025 14:04:26 +0100 Subject: [PATCH] feat(plugins): Allow opening panes near plugin (#3966) * added command + terminal variants * added editor variant * style(fmt): rustfmt --- zellij-server/src/panes/floating_panes/mod.rs | 10 + zellij-server/src/plugins/zellij_exports.rs | 315 +++++++++++++++++- zellij-server/src/screen.rs | 30 +- zellij-server/src/tab/mod.rs | 2 + zellij-tile/src/shim.rs | 104 ++++++ .../assets/prost/api.plugin_command.rs | 149 ++++++++- zellij-utils/src/data.rs | 9 + .../src/plugin_api/plugin_command.proto | 69 ++++ zellij-utils/src/plugin_api/plugin_command.rs | 302 ++++++++++++++++- 9 files changed, 985 insertions(+), 5 deletions(-) diff --git a/zellij-server/src/panes/floating_panes/mod.rs b/zellij-server/src/panes/floating_panes/mod.rs index 10efa2e4..61256ab4 100644 --- a/zellij-server/src/panes/floating_panes/mod.rs +++ b/zellij-server/src/panes/floating_panes/mod.rs @@ -816,6 +816,16 @@ impl FloatingPanes { None => self.focus_pane(pane_id, client_id), } } + pub fn focus_first_pane_if_client_not_focused(&mut self, client_id: ClientId) { + match self.active_panes.get(&client_id) { + Some(already_focused_pane_id) => self.focus_pane(*already_focused_pane_id, client_id), + None => { + if let Some(first_pane_id) = self.panes.iter().next().map(|(p_id, _)| *p_id) { + self.focus_pane(first_pane_id, client_id); + } + }, + } + } pub fn defocus_pane(&mut self, pane_id: PaneId, client_id: ClientId) { self.z_indices.retain(|p_id| *p_id != pane_id); self.active_panes.remove(&client_id, &mut self.panes); diff --git a/zellij-server/src/plugins/zellij_exports.rs b/zellij-server/src/plugins/zellij_exports.rs index c95d2408..158d8c0a 100644 --- a/zellij-server/src/plugins/zellij_exports.rs +++ b/zellij-server/src/plugins/zellij_exports.rs @@ -101,12 +101,26 @@ fn host_run_plugin_command(caller: Caller<'_, PluginEnv>) { context, ) => open_file_floating(env, file_to_open, floating_pane_coordinates, context), PluginCommand::OpenTerminal(cwd) => open_terminal(env, cwd.path.try_into()?), + PluginCommand::OpenTerminalNearPlugin(cwd) => { + open_terminal_near_plugin(env, cwd.path.try_into()?) + }, PluginCommand::OpenTerminalFloating(cwd, floating_pane_coordinates) => { open_terminal_floating(env, cwd.path.try_into()?, floating_pane_coordinates) }, + PluginCommand::OpenTerminalFloatingNearPlugin( + cwd, + floating_pane_coordinates, + ) => open_terminal_floating_near_plugin( + env, + cwd.path.try_into()?, + floating_pane_coordinates, + ), PluginCommand::OpenCommandPane(command_to_run, context) => { open_command_pane(env, command_to_run, context) }, + PluginCommand::OpenCommandPaneNearPlugin(command_to_run, context) => { + open_command_pane_near_plugin(env, command_to_run, context) + }, PluginCommand::OpenCommandPaneFloating( command_to_run, floating_pane_coordinates, @@ -117,6 +131,16 @@ fn host_run_plugin_command(caller: Caller<'_, PluginEnv>) { floating_pane_coordinates, context, ), + PluginCommand::OpenCommandPaneFloatingNearPlugin( + command_to_run, + floating_pane_coordinates, + context, + ) => open_command_pane_floating_near_plugin( + 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), @@ -232,9 +256,15 @@ fn host_run_plugin_command(caller: Caller<'_, PluginEnv>) { PluginCommand::OpenTerminalInPlace(cwd) => { open_terminal_in_place(env, cwd.path.try_into()?) }, + PluginCommand::OpenTerminalInPlaceOfPlugin(cwd) => { + open_terminal_in_place_of_plugin(env, cwd.path.try_into()?) + }, PluginCommand::OpenCommandPaneInPlace(command_to_run, context) => { open_command_pane_in_place(env, command_to_run, context) }, + PluginCommand::OpenCommandPaneInPlaceOfPlugin(command_to_run, context) => { + open_command_pane_in_place_of_plugin(env, command_to_run, context) + }, PluginCommand::RenameSession(new_session_name) => { rename_session(env, new_session_name) }, @@ -370,6 +400,22 @@ fn host_run_plugin_command(caller: Caller<'_, PluginEnv>) { .collect(), ) }, + PluginCommand::OpenFileNearPlugin(file_to_open, context) => { + open_file_near_plugin(env, file_to_open, context) + }, + PluginCommand::OpenFileFloatingNearPlugin( + file_to_open, + floating_pane_coordinates, + context, + ) => open_file_floating_near_plugin( + env, + file_to_open, + floating_pane_coordinates, + context, + ), + PluginCommand::OpenFileInPlaceOfPlugin(file_to_open, context) => { + open_file_in_place_of_plugin(env, file_to_open, context) + }, }, (PermissionStatus::Denied, permission) => { log::error!( @@ -595,6 +641,89 @@ fn open_file_in_place( apply_action!(action, error_msg, env); } +fn open_file_near_plugin( + env: &PluginEnv, + file_to_open: FileToOpen, + context: BTreeMap, +) { + let cwd = file_to_open + .cwd + .map(|cwd| env.plugin_cwd.join(cwd)) + .or_else(|| Some(env.plugin_cwd.clone())); + let path = env.plugin_cwd.join(file_to_open.path); + let open_file_payload = + OpenFilePayload::new(path, file_to_open.line_number, cwd).with_originating_plugin( + OriginatingPlugin::new(env.plugin_id, env.client_id, context), + ); + let title = format!("Editing: {}", open_file_payload.path.display()); + let should_float = false; + let start_suppressed = false; + let open_file = TerminalAction::OpenFile(open_file_payload); + let pty_instr = PtyInstruction::SpawnTerminal( + Some(open_file), + Some(should_float), + Some(title), + None, + start_suppressed, + ClientTabIndexOrPaneId::PaneId(PaneId::Plugin(env.plugin_id)), + ); + let _ = env.senders.send_to_pty(pty_instr); +} + +fn open_file_floating_near_plugin( + env: &PluginEnv, + file_to_open: FileToOpen, + floating_pane_coordinates: Option, + context: BTreeMap, +) { + let cwd = file_to_open + .cwd + .map(|cwd| env.plugin_cwd.join(cwd)) + .or_else(|| Some(env.plugin_cwd.clone())); + let path = env.plugin_cwd.join(file_to_open.path); + let open_file_payload = + OpenFilePayload::new(path, file_to_open.line_number, cwd).with_originating_plugin( + OriginatingPlugin::new(env.plugin_id, env.client_id, context), + ); + let title = format!("Editing: {}", open_file_payload.path.display()); + let should_float = true; + let start_suppressed = false; + let open_file = TerminalAction::OpenFile(open_file_payload); + let pty_instr = PtyInstruction::SpawnTerminal( + Some(open_file), + Some(should_float), + Some(title), + floating_pane_coordinates, + start_suppressed, + ClientTabIndexOrPaneId::PaneId(PaneId::Plugin(env.plugin_id)), + ); + let _ = env.senders.send_to_pty(pty_instr); +} + +fn open_file_in_place_of_plugin( + env: &PluginEnv, + file_to_open: FileToOpen, + context: BTreeMap, +) { + let cwd = file_to_open + .cwd + .map(|cwd| env.plugin_cwd.join(cwd)) + .or_else(|| Some(env.plugin_cwd.clone())); + let path = env.plugin_cwd.join(file_to_open.path); + let open_file_payload = + OpenFilePayload::new(path, file_to_open.line_number, cwd).with_originating_plugin( + OriginatingPlugin::new(env.plugin_id, env.client_id, context), + ); + let title = format!("Editing: {}", open_file_payload.path.display()); + let open_file = TerminalAction::OpenFile(open_file_payload); + let pty_instr = PtyInstruction::SpawnInPlaceTerminal( + Some(open_file), + Some(title), + ClientTabIndexOrPaneId::PaneId(PaneId::Plugin(env.plugin_id)), + ); + let _ = env.senders.send_to_pty(pty_instr); +} + fn open_terminal(env: &PluginEnv, cwd: PathBuf) { let error_msg = || format!("failed to open file in plugin {}", env.name()); let cwd = env.plugin_cwd.join(cwd); @@ -613,6 +742,27 @@ fn open_terminal(env: &PluginEnv, cwd: PathBuf) { apply_action!(action, error_msg, env); } +fn open_terminal_near_plugin(env: &PluginEnv, cwd: PathBuf) { + let cwd = env.plugin_cwd.join(cwd); + let should_float = false; + let mut default_shell = env.default_shell.clone().unwrap_or_else(|| { + TerminalAction::RunCommand(RunCommand { + command: env.path_to_default_shell.clone(), + ..Default::default() + }) + }); + let name = None; + default_shell.change_cwd(cwd); + let _ = env.senders.send_to_pty(PtyInstruction::SpawnTerminal( + Some(default_shell), + Some(should_float), + name, + None, + false, + ClientTabIndexOrPaneId::PaneId(PaneId::Plugin(env.plugin_id)), + )); +} + fn open_terminal_floating( env: &PluginEnv, cwd: PathBuf, @@ -635,6 +785,31 @@ fn open_terminal_floating( apply_action!(action, error_msg, env); } +fn open_terminal_floating_near_plugin( + env: &PluginEnv, + cwd: PathBuf, + floating_pane_coordinates: Option, +) { + let cwd = env.plugin_cwd.join(cwd); + let should_float = true; + let mut default_shell = env.default_shell.clone().unwrap_or_else(|| { + TerminalAction::RunCommand(RunCommand { + command: env.path_to_default_shell.clone(), + ..Default::default() + }) + }); + default_shell.change_cwd(cwd); + let name = None; + let _ = env.senders.send_to_pty(PtyInstruction::SpawnTerminal( + Some(default_shell), + Some(should_float), + name, + floating_pane_coordinates, + false, + ClientTabIndexOrPaneId::PaneId(PaneId::Plugin(env.plugin_id)), + )); +} + fn open_terminal_in_place(env: &PluginEnv, cwd: PathBuf) { let error_msg = || format!("failed to open file in plugin {}", env.name()); let cwd = env.plugin_cwd.join(cwd); @@ -653,6 +828,60 @@ fn open_terminal_in_place(env: &PluginEnv, cwd: PathBuf) { apply_action!(action, error_msg, env); } +fn open_terminal_in_place_of_plugin(env: &PluginEnv, cwd: PathBuf) { + let cwd = env.plugin_cwd.join(cwd); + let mut default_shell = env.default_shell.clone().unwrap_or_else(|| { + TerminalAction::RunCommand(RunCommand { + command: env.path_to_default_shell.clone(), + ..Default::default() + }) + }); + default_shell.change_cwd(cwd); + let name = None; + let _ = env + .senders + .send_to_pty(PtyInstruction::SpawnInPlaceTerminal( + Some(default_shell), + name, + ClientTabIndexOrPaneId::PaneId(PaneId::Plugin(env.plugin_id)), + )); +} + +fn open_command_pane_in_place_of_plugin( + env: &PluginEnv, + command_to_run: CommandToRun, + context: BTreeMap, +) { + let command = command_to_run.path; + let cwd = command_to_run.cwd.map(|cwd| env.plugin_cwd.join(cwd)); + let args = command_to_run.args; + let direction = None; + let hold_on_close = true; + let hold_on_start = false; + let name = None; + let run_command_action = RunCommandAction { + command, + args, + cwd, + direction, + hold_on_close, + hold_on_start, + originating_plugin: Some(OriginatingPlugin::new( + env.plugin_id, + env.client_id, + context, + )), + }; + let run_cmd = TerminalAction::RunCommand(run_command_action.into()); + let _ = env + .senders + .send_to_pty(PtyInstruction::SpawnInPlaceTerminal( + Some(run_cmd), + name, + ClientTabIndexOrPaneId::PaneId(PaneId::Plugin(env.plugin_id)), + )); +} + fn open_command_pane( env: &PluginEnv, command_to_run: CommandToRun, @@ -683,6 +912,43 @@ fn open_command_pane( apply_action!(action, error_msg, env); } +fn open_command_pane_near_plugin( + env: &PluginEnv, + command_to_run: CommandToRun, + context: BTreeMap, +) { + let command = command_to_run.path; + let cwd = command_to_run.cwd.map(|cwd| env.plugin_cwd.join(cwd)); + let args = command_to_run.args; + let direction = None; + let hold_on_close = true; + let hold_on_start = false; + let name = None; + let should_float = false; + let run_command_action = RunCommandAction { + command, + args, + cwd, + direction, + hold_on_close, + hold_on_start, + originating_plugin: Some(OriginatingPlugin::new( + env.plugin_id, + env.client_id, + context, + )), + }; + let run_cmd = TerminalAction::RunCommand(run_command_action.into()); + let _ = env.senders.send_to_pty(PtyInstruction::SpawnTerminal( + Some(run_cmd), + Some(should_float), + name, + None, + false, + ClientTabIndexOrPaneId::PaneId(PaneId::Plugin(env.plugin_id)), + )); +} + fn open_command_pane_floating( env: &PluginEnv, command_to_run: CommandToRun, @@ -714,6 +980,44 @@ fn open_command_pane_floating( apply_action!(action, error_msg, env); } +fn open_command_pane_floating_near_plugin( + env: &PluginEnv, + command_to_run: CommandToRun, + floating_pane_coordinates: Option, + context: BTreeMap, +) { + let command = command_to_run.path; + let cwd = command_to_run.cwd.map(|cwd| env.plugin_cwd.join(cwd)); + let args = command_to_run.args; + let direction = None; + let hold_on_close = true; + let hold_on_start = false; + let name = None; + let should_float = true; + let run_command_action = RunCommandAction { + command, + args, + cwd, + direction, + hold_on_close, + hold_on_start, + originating_plugin: Some(OriginatingPlugin::new( + env.plugin_id, + env.client_id, + context, + )), + }; + let run_cmd = TerminalAction::RunCommand(run_command_action.into()); + let _ = env.senders.send_to_pty(PtyInstruction::SpawnTerminal( + Some(run_cmd), + Some(should_float), + name, + floating_pane_coordinates, + false, + ClientTabIndexOrPaneId::PaneId(PaneId::Plugin(env.plugin_id)), + )); +} + fn open_command_pane_in_place( env: &PluginEnv, command_to_run: CommandToRun, @@ -1881,14 +2185,23 @@ fn check_command_permission( let permission = match command { PluginCommand::OpenFile(..) | PluginCommand::OpenFileFloating(..) + | PluginCommand::OpenFileNearPlugin(..) + | PluginCommand::OpenFileFloatingNearPlugin(..) + | PluginCommand::OpenFileInPlaceOfPlugin(..) | PluginCommand::OpenFileInPlace(..) => PermissionType::OpenFiles, PluginCommand::OpenTerminal(..) + | PluginCommand::OpenTerminalNearPlugin(..) | PluginCommand::StartOrReloadPlugin(..) | PluginCommand::OpenTerminalFloating(..) - | PluginCommand::OpenTerminalInPlace(..) => PermissionType::OpenTerminalsOrPlugins, + | PluginCommand::OpenTerminalFloatingNearPlugin(..) + | PluginCommand::OpenTerminalInPlace(..) + | PluginCommand::OpenTerminalInPlaceOfPlugin(..) => PermissionType::OpenTerminalsOrPlugins, PluginCommand::OpenCommandPane(..) + | PluginCommand::OpenCommandPaneNearPlugin(..) | PluginCommand::OpenCommandPaneFloating(..) + | PluginCommand::OpenCommandPaneFloatingNearPlugin(..) | PluginCommand::OpenCommandPaneInPlace(..) + | PluginCommand::OpenCommandPaneInPlaceOfPlugin(..) | PluginCommand::OpenCommandPaneBackground(..) | PluginCommand::RunCommand(..) | PluginCommand::ExecCmd(..) => PermissionType::RunCommands, diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs index 94f42214..6059cda4 100644 --- a/zellij-server/src/screen.rs +++ b/zellij-server/src/screen.rs @@ -2923,8 +2923,34 @@ pub(crate) fn screen_thread_main( log::error!("Tab index not found: {:?}", tab_index); } }, - ClientTabIndexOrPaneId::PaneId(_pane_id) => { - log::error!("cannot open a pane with a pane id??"); + ClientTabIndexOrPaneId::PaneId(pane_id) => { + let mut found = false; + let all_tabs = screen.get_tabs_mut(); + for tab in all_tabs.values_mut() { + if tab.has_pane_with_pid(&pane_id) { + tab.new_pane( + pid, + initial_pane_title, + should_float, + invoked_with, + floating_pane_coordinates, + start_suppressed, + None, + )?; + if let Some(hold_for_command) = hold_for_command { + let is_first_run = true; + tab.hold_pane(pid, None, is_first_run, hold_for_command); + } + found = true; + break; + } + } + if !found { + log::error!( + "Failed to find tab containing pane with id: {:?}", + pane_id + ); + } }, }; screen.unblock_input()?; diff --git a/zellij-server/src/tab/mod.rs b/zellij-server/src/tab/mod.rs index eec00568..23a791d5 100644 --- a/zellij-server/src/tab/mod.rs +++ b/zellij-server/src/tab/mod.rs @@ -929,6 +929,8 @@ impl Tab { }; self.tiled_panes .focus_pane_if_client_not_focused(focus_pane_id, client_id); + self.floating_panes + .focus_first_pane_if_client_not_focused(client_id); self.connected_clients.borrow_mut().insert(client_id); self.mode_info.borrow_mut().insert( client_id, diff --git a/zellij-tile/src/shim.rs b/zellij-tile/src/shim.rs index 63203901..b717031d 100644 --- a/zellij-tile/src/shim.rs +++ b/zellij-tile/src/shim.rs @@ -104,6 +104,34 @@ pub fn open_file_in_place(file_to_open: FileToOpen, context: BTreeMap) { + let plugin_command = PluginCommand::OpenFileNearPlugin(file_to_open, context); + let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); + object_to_stdout(&protobuf_plugin_command.encode_to_vec()); + unsafe { host_run_plugin_command() }; +} + +/// Open a file in the user's default `$EDITOR` in a new floating pane near the plugin +pub fn open_file_floating_near_plugin( + file_to_open: FileToOpen, + coordinates: Option, + context: BTreeMap, +) { + let plugin_command = + PluginCommand::OpenFileFloatingNearPlugin(file_to_open, coordinates, context); + let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); + object_to_stdout(&protobuf_plugin_command.encode_to_vec()); + unsafe { host_run_plugin_command() }; +} + +/// Open a file in the user's default `$EDITOR`, replacing the plugin pane +pub fn open_file_in_place_of_plugin(file_to_open: FileToOpen, context: BTreeMap) { + let plugin_command = PluginCommand::OpenFileInPlaceOfPlugin(file_to_open, context); + let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); + object_to_stdout(&protobuf_plugin_command.encode_to_vec()); + unsafe { host_run_plugin_command() }; +} /// Open a new terminal pane to the specified location on the host filesystem pub fn open_terminal>(path: P) { let file_to_open = FileToOpen::new(path.as_ref().to_path_buf()); @@ -113,6 +141,17 @@ pub fn open_terminal>(path: P) { unsafe { host_run_plugin_command() }; } +/// Open a new terminal pane to the specified location on the host filesystem +/// This variant is identical to open_terminal, excpet it opens it near the plugin regardless of +/// whether the user was focused on it or not +pub fn open_terminal_near_plugin>(path: P) { + let file_to_open = FileToOpen::new(path.as_ref().to_path_buf()); + let plugin_command = PluginCommand::OpenTerminalNearPlugin(file_to_open); + let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); + object_to_stdout(&protobuf_plugin_command.encode_to_vec()); + unsafe { host_run_plugin_command() }; +} + /// Open a new floating terminal pane to the specified location on the host filesystem pub fn open_terminal_floating>( path: P, @@ -125,6 +164,20 @@ pub fn open_terminal_floating>( unsafe { host_run_plugin_command() }; } +/// Open a new floating terminal pane to the specified location on the host filesystem +/// This variant is identical to open_terminal_floating, excpet it opens it near the plugin regardless of +/// whether the user was focused on it or not +pub fn open_terminal_floating_near_plugin>( + path: P, + coordinates: Option, +) { + let file_to_open = FileToOpen::new(path.as_ref().to_path_buf()); + let plugin_command = PluginCommand::OpenTerminalFloatingNearPlugin(file_to_open, coordinates); + let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); + object_to_stdout(&protobuf_plugin_command.encode_to_vec()); + unsafe { host_run_plugin_command() }; +} + /// Open a new terminal pane to the specified location on the host filesystem, temporarily /// replacing the focused pane pub fn open_terminal_in_place>(path: P) { @@ -135,6 +188,16 @@ pub fn open_terminal_in_place>(path: P) { unsafe { host_run_plugin_command() }; } +/// Open a new terminal pane to the specified location on the host filesystem, temporarily +/// replacing the plugin pane +pub fn open_terminal_in_place_of_plugin>(path: P) { + let file_to_open = FileToOpen::new(path.as_ref().to_path_buf()); + let plugin_command = PluginCommand::OpenTerminalInPlaceOfPlugin(file_to_open); + let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); + object_to_stdout(&protobuf_plugin_command.encode_to_vec()); + unsafe { host_run_plugin_command() }; +} + /// Open a new command pane with the specified command and args (this sort of pane allows the user to control the command, re-run it and see its exit status through the Zellij UI). pub fn open_command_pane(command_to_run: CommandToRun, context: BTreeMap) { let plugin_command = PluginCommand::OpenCommandPane(command_to_run, context); @@ -143,6 +206,19 @@ pub fn open_command_pane(command_to_run: CommandToRun, context: BTreeMap, +) { + let plugin_command = PluginCommand::OpenCommandPaneNearPlugin(command_to_run, context); + let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); + object_to_stdout(&protobuf_plugin_command.encode_to_vec()); + unsafe { host_run_plugin_command() }; +} + /// Open a new floating command pane with the specified command and args (this sort of pane allows the user to control the command, re-run it and see its exit status through the Zellij UI). pub fn open_command_pane_floating( command_to_run: CommandToRun, @@ -156,6 +232,21 @@ pub fn open_command_pane_floating( unsafe { host_run_plugin_command() }; } +/// Open a new floating command pane with the specified command and args (this sort of pane allows the user to control the command, re-run it and see its exit status through the Zellij UI). +/// This variant is the same as `open_command_pane_floating` except it opens the pane in the same tab as the +/// plugin regardless of whether the user is focused on it +pub fn open_command_pane_floating_near_plugin( + command_to_run: CommandToRun, + coordinates: Option, + context: BTreeMap, +) { + let plugin_command = + PluginCommand::OpenCommandPaneFloatingNearPlugin(command_to_run, coordinates, context); + let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); + object_to_stdout(&protobuf_plugin_command.encode_to_vec()); + unsafe { host_run_plugin_command() }; +} + /// Open a new in place command pane with the specified command and args (this sort of pane allows the user to control the command, re-run it and see its exit status through the Zellij UI). pub fn open_command_pane_in_place(command_to_run: CommandToRun, context: BTreeMap) { let plugin_command = PluginCommand::OpenCommandPaneInPlace(command_to_run, context); @@ -164,6 +255,19 @@ pub fn open_command_pane_in_place(command_to_run: CommandToRun, context: BTreeMa unsafe { host_run_plugin_command() }; } +/// Open a new in place command pane with the specified command and args (this sort of pane allows the user to control the command, re-run it and see its exit status through the Zellij UI). +/// This variant is the same as open_command_pane_in_place, except that it always replaces the +/// plugin pane rather than whichever pane the user is focused on +pub fn open_command_pane_in_place_of_plugin( + command_to_run: CommandToRun, + context: BTreeMap, +) { + let plugin_command = PluginCommand::OpenCommandPaneInPlaceOfPlugin(command_to_run, context); + let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); + object_to_stdout(&protobuf_plugin_command.encode_to_vec()); + unsafe { host_run_plugin_command() }; +} + /// Open a new hidden (background) command pane with the specified command and args (this sort of pane allows the user to control the command, re-run it and see its exit status through the Zellij UI). pub fn open_command_pane_background( command_to_run: CommandToRun, diff --git a/zellij-utils/assets/prost/api.plugin_command.rs b/zellij-utils/assets/prost/api.plugin_command.rs index 59091cdf..1920f6b6 100644 --- a/zellij-utils/assets/prost/api.plugin_command.rs +++ b/zellij-utils/assets/prost/api.plugin_command.rs @@ -5,7 +5,7 @@ pub struct PluginCommand { pub name: i32, #[prost( oneof = "plugin_command::Payload", - tags = "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92" + tags = "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101" )] pub payload: ::core::option::Option, } @@ -184,10 +184,118 @@ pub mod plugin_command { ChangeFloatingPanesCoordinatesPayload( super::ChangeFloatingPanesCoordinatesPayload, ), + #[prost(message, tag = "93")] + OpenCommandPaneNearPluginPayload(super::OpenCommandPaneNearPluginPayload), + #[prost(message, tag = "94")] + OpenTerminalNearPluginPayload(super::OpenTerminalNearPluginPayload), + #[prost(message, tag = "95")] + OpenTerminalFloatingNearPluginPayload( + super::OpenTerminalFloatingNearPluginPayload, + ), + #[prost(message, tag = "96")] + OpenTerminalInPlaceOfPluginPayload(super::OpenTerminalInPlaceOfPluginPayload), + #[prost(message, tag = "97")] + OpenCommandPaneFloatingNearPluginPayload( + super::OpenCommandPaneFloatingNearPluginPayload, + ), + #[prost(message, tag = "98")] + OpenCommandPaneInPlaceOfPluginPayload( + super::OpenCommandPaneInPlaceOfPluginPayload, + ), + #[prost(message, tag = "99")] + OpenFileNearPluginPayload(super::OpenFileNearPluginPayload), + #[prost(message, tag = "100")] + OpenFileFloatingNearPluginPayload(super::OpenFileFloatingNearPluginPayload), + #[prost(message, tag = "101")] + OpenFileInPlaceOfPluginPayload(super::OpenFileInPlaceOfPluginPayload), } } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] +pub struct OpenFileInPlaceOfPluginPayload { + #[prost(message, optional, tag = "1")] + pub file_to_open: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub floating_pane_coordinates: ::core::option::Option, + #[prost(message, repeated, tag = "3")] + pub context: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct OpenFileFloatingNearPluginPayload { + #[prost(message, optional, tag = "1")] + pub file_to_open: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub floating_pane_coordinates: ::core::option::Option, + #[prost(message, repeated, tag = "3")] + pub context: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct OpenFileNearPluginPayload { + #[prost(message, optional, tag = "1")] + pub file_to_open: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub floating_pane_coordinates: ::core::option::Option, + #[prost(message, repeated, tag = "3")] + pub context: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct OpenCommandPaneInPlaceOfPluginPayload { + #[prost(message, optional, tag = "1")] + pub command_to_run: ::core::option::Option, + #[prost(message, repeated, tag = "3")] + pub context: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct OpenCommandPaneFloatingNearPluginPayload { + #[prost(message, optional, tag = "1")] + pub command_to_run: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub floating_pane_coordinates: ::core::option::Option, + #[prost(message, repeated, tag = "3")] + pub context: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct OpenTerminalInPlaceOfPluginPayload { + #[prost(message, optional, tag = "1")] + pub file_to_open: ::core::option::Option, + #[prost(message, repeated, tag = "3")] + pub context: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct OpenTerminalFloatingNearPluginPayload { + #[prost(message, optional, tag = "1")] + pub file_to_open: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub floating_pane_coordinates: ::core::option::Option, + #[prost(message, repeated, tag = "3")] + pub context: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct OpenTerminalNearPluginPayload { + #[prost(message, optional, tag = "1")] + pub file_to_open: ::core::option::Option, + #[prost(message, repeated, tag = "3")] + pub context: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct OpenCommandPaneNearPluginPayload { + #[prost(message, optional, tag = "1")] + pub command_to_run: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub floating_pane_coordinates: ::core::option::Option, + #[prost(message, repeated, tag = "3")] + pub context: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct ChangeFloatingPanesCoordinatesPayload { #[prost(message, repeated, tag = "1")] pub pane_ids_and_floating_panes_coordinates: ::prost::alloc::vec::Vec< @@ -768,6 +876,15 @@ pub enum CommandName { SetFloatingPanePinned = 115, StackPanes = 116, ChangeFloatingPanesCoordinates = 117, + OpenCommandPaneNearPlugin = 118, + OpenTerminalNearPlugin = 119, + OpenTerminalFloatingNearPlugin = 120, + OpenTerminalInPlaceOfPlugin = 121, + OpenCommandPaneFloatingNearPlugin = 122, + OpenCommandPaneInPlaceOfPlugin = 123, + OpenFileNearPlugin = 124, + OpenFileFloatingNearPlugin = 125, + OpenFileInPlaceOfPlugin = 126, } impl CommandName { /// String value of the enum field names used in the ProtoBuf definition. @@ -898,6 +1015,21 @@ impl CommandName { CommandName::ChangeFloatingPanesCoordinates => { "ChangeFloatingPanesCoordinates" } + CommandName::OpenCommandPaneNearPlugin => "OpenCommandPaneNearPlugin", + CommandName::OpenTerminalNearPlugin => "OpenTerminalNearPlugin", + CommandName::OpenTerminalFloatingNearPlugin => { + "OpenTerminalFloatingNearPlugin" + } + CommandName::OpenTerminalInPlaceOfPlugin => "OpenTerminalInPlaceOfPlugin", + CommandName::OpenCommandPaneFloatingNearPlugin => { + "OpenCommandPaneFloatingNearPlugin" + } + CommandName::OpenCommandPaneInPlaceOfPlugin => { + "OpenCommandPaneInPlaceOfPlugin" + } + CommandName::OpenFileNearPlugin => "OpenFileNearPlugin", + CommandName::OpenFileFloatingNearPlugin => "OpenFileFloatingNearPlugin", + CommandName::OpenFileInPlaceOfPlugin => "OpenFileInPlaceOfPlugin", } } /// Creates an enum from field names used in the ProtoBuf definition. @@ -1025,6 +1157,21 @@ impl CommandName { "ChangeFloatingPanesCoordinates" => { Some(Self::ChangeFloatingPanesCoordinates) } + "OpenCommandPaneNearPlugin" => Some(Self::OpenCommandPaneNearPlugin), + "OpenTerminalNearPlugin" => Some(Self::OpenTerminalNearPlugin), + "OpenTerminalFloatingNearPlugin" => { + Some(Self::OpenTerminalFloatingNearPlugin) + } + "OpenTerminalInPlaceOfPlugin" => Some(Self::OpenTerminalInPlaceOfPlugin), + "OpenCommandPaneFloatingNearPlugin" => { + Some(Self::OpenCommandPaneFloatingNearPlugin) + } + "OpenCommandPaneInPlaceOfPlugin" => { + Some(Self::OpenCommandPaneInPlaceOfPlugin) + } + "OpenFileNearPlugin" => Some(Self::OpenFileNearPlugin), + "OpenFileFloatingNearPlugin" => Some(Self::OpenFileFloatingNearPlugin), + "OpenFileInPlaceOfPlugin" => Some(Self::OpenFileInPlaceOfPlugin), _ => None, } } diff --git a/zellij-utils/src/data.rs b/zellij-utils/src/data.rs index 0deeeb19..966c87ea 100644 --- a/zellij-utils/src/data.rs +++ b/zellij-utils/src/data.rs @@ -1934,4 +1934,13 @@ pub enum PluginCommand { SetFloatingPanePinned(PaneId, bool), // bool -> should be pinned StackPanes(Vec), ChangeFloatingPanesCoordinates(Vec<(PaneId, FloatingPaneCoordinates)>), + OpenCommandPaneNearPlugin(CommandToRun, Context), + OpenTerminalNearPlugin(FileToOpen), + OpenTerminalFloatingNearPlugin(FileToOpen, Option), + OpenTerminalInPlaceOfPlugin(FileToOpen), + OpenCommandPaneFloatingNearPlugin(CommandToRun, Option, Context), + OpenCommandPaneInPlaceOfPlugin(CommandToRun, Context), + OpenFileNearPlugin(FileToOpen, Context), + OpenFileFloatingNearPlugin(FileToOpen, Option, Context), + OpenFileInPlaceOfPlugin(FileToOpen, Context), } diff --git a/zellij-utils/src/plugin_api/plugin_command.proto b/zellij-utils/src/plugin_api/plugin_command.proto index d0d1841a..e132909e 100644 --- a/zellij-utils/src/plugin_api/plugin_command.proto +++ b/zellij-utils/src/plugin_api/plugin_command.proto @@ -131,6 +131,15 @@ enum CommandName { SetFloatingPanePinned = 115; StackPanes = 116; ChangeFloatingPanesCoordinates = 117; + OpenCommandPaneNearPlugin = 118; + OpenTerminalNearPlugin = 119; + OpenTerminalFloatingNearPlugin = 120; + OpenTerminalInPlaceOfPlugin = 121; + OpenCommandPaneFloatingNearPlugin = 122; + OpenCommandPaneInPlaceOfPlugin = 123; + OpenFileNearPlugin = 124; + OpenFileFloatingNearPlugin = 125; + OpenFileInPlaceOfPlugin = 126; } message PluginCommand { @@ -218,9 +227,69 @@ message PluginCommand { SetFloatingPanePinnedPayload set_floating_pane_pinned_payload = 90; StackPanesPayload stack_panes_payload = 91; ChangeFloatingPanesCoordinatesPayload change_floating_panes_coordinates_payload = 92; + OpenCommandPaneNearPluginPayload open_command_pane_near_plugin_payload = 93; + OpenTerminalNearPluginPayload open_terminal_near_plugin_payload = 94; + OpenTerminalFloatingNearPluginPayload open_terminal_floating_near_plugin_payload = 95; + OpenTerminalInPlaceOfPluginPayload open_terminal_in_place_of_plugin_payload = 96; + OpenCommandPaneFloatingNearPluginPayload open_command_pane_floating_near_plugin_payload = 97; + OpenCommandPaneInPlaceOfPluginPayload open_command_pane_in_place_of_plugin_payload = 98; + OpenFileNearPluginPayload open_file_near_plugin_payload = 99; + OpenFileFloatingNearPluginPayload open_file_floating_near_plugin_payload = 100; + OpenFileInPlaceOfPluginPayload open_file_in_place_of_plugin_payload = 101; } } +message OpenFileInPlaceOfPluginPayload { + file.File file_to_open = 1; + optional FloatingPaneCoordinates floating_pane_coordinates = 2; + repeated ContextItem context = 3; +} + +message OpenFileFloatingNearPluginPayload { + file.File file_to_open = 1; + optional FloatingPaneCoordinates floating_pane_coordinates = 2; + repeated ContextItem context = 3; +} + +message OpenFileNearPluginPayload { + file.File file_to_open = 1; + optional FloatingPaneCoordinates floating_pane_coordinates = 2; + repeated ContextItem context = 3; +} + +message OpenCommandPaneInPlaceOfPluginPayload { + command.Command command_to_run = 1; + repeated ContextItem context = 3; +} + +message OpenCommandPaneFloatingNearPluginPayload { + command.Command command_to_run = 1; + optional FloatingPaneCoordinates floating_pane_coordinates = 2; + repeated ContextItem context = 3; +} + +message OpenTerminalInPlaceOfPluginPayload { + file.File file_to_open = 1; + repeated ContextItem context = 3; +} + +message OpenTerminalFloatingNearPluginPayload { + file.File file_to_open = 1; + optional FloatingPaneCoordinates floating_pane_coordinates = 2; + repeated ContextItem context = 3; +} + +message OpenTerminalNearPluginPayload { + file.File file_to_open = 1; + repeated ContextItem context = 3; +} + +message OpenCommandPaneNearPluginPayload { + command.Command command_to_run = 1; + optional FloatingPaneCoordinates floating_pane_coordinates = 2; + repeated ContextItem context = 3; +} + message ChangeFloatingPanesCoordinatesPayload { repeated PaneIdAndFloatingPaneCoordinates pane_ids_and_floating_panes_coordinates = 1; } diff --git a/zellij-utils/src/plugin_api/plugin_command.rs b/zellij-utils/src/plugin_api/plugin_command.rs index 5eb634c2..1ec95d0f 100644 --- a/zellij-utils/src/plugin_api/plugin_command.rs +++ b/zellij-utils/src/plugin_api/plugin_command.rs @@ -13,7 +13,11 @@ pub use super::generated_api::api::{ HttpVerb as ProtobufHttpVerb, IdAndNewName, KeyToRebind, KeyToUnbind, KillSessionsPayload, LoadNewPluginPayload, MessageToPluginPayload, MovePaneWithPaneIdInDirectionPayload, MovePaneWithPaneIdPayload, MovePayload, NewPluginArgs as ProtobufNewPluginArgs, - NewTabsWithLayoutInfoPayload, OpenCommandPanePayload, OpenFilePayload, + NewTabsWithLayoutInfoPayload, OpenCommandPaneFloatingNearPluginPayload, + OpenCommandPaneInPlaceOfPluginPayload, OpenCommandPaneNearPluginPayload, + OpenCommandPanePayload, OpenFileFloatingNearPluginPayload, OpenFileInPlaceOfPluginPayload, + OpenFileNearPluginPayload, OpenFilePayload, OpenTerminalFloatingNearPluginPayload, + OpenTerminalInPlaceOfPluginPayload, OpenTerminalNearPluginPayload, PageScrollDownInPaneIdPayload, PageScrollUpInPaneIdPayload, PaneId as ProtobufPaneId, PaneIdAndFloatingPaneCoordinates, PaneType as ProtobufPaneType, PluginCommand as ProtobufPluginCommand, PluginMessagePayload, RebindKeysPayload, @@ -1362,6 +1366,176 @@ impl TryFrom for PluginCommand { _ => Err("Mismatched payload for ChangeFloatingPanesCoordinates"), } }, + Some(CommandName::OpenCommandPaneNearPlugin) => match protobuf_plugin_command.payload { + Some(Payload::OpenCommandPaneNearPluginPayload(command_to_run_payload)) => { + match command_to_run_payload.command_to_run { + Some(command_to_run) => { + let context: BTreeMap = command_to_run_payload + .context + .into_iter() + .map(|e| (e.name, e.value)) + .collect(); + Ok(PluginCommand::OpenCommandPaneNearPlugin( + command_to_run.try_into()?, + context, + )) + }, + None => Err("Malformed open command pane near plugin payload"), + } + }, + _ => Err("Mismatched payload for OpenCommandPaneNearPlugin"), + }, + Some(CommandName::OpenTerminalNearPlugin) => match protobuf_plugin_command.payload { + Some(Payload::OpenTerminalNearPluginPayload(open_terminal_near_plugin_payload)) => { + match open_terminal_near_plugin_payload.file_to_open { + Some(file_to_open) => Ok(PluginCommand::OpenTerminalNearPlugin( + file_to_open.try_into()?, + )), + None => Err("Malformed open terminal near plugin payload"), + } + }, + _ => Err("Mismatched payload for OpenTerminalNearPluginPayload"), + }, + Some(CommandName::OpenTerminalFloatingNearPlugin) => match protobuf_plugin_command + .payload + { + Some(Payload::OpenTerminalFloatingNearPluginPayload( + open_terminal_floating_near_plugin_payload, + )) => { + let floating_pane_coordinates = open_terminal_floating_near_plugin_payload + .floating_pane_coordinates + .map(|f| f.into()); + match open_terminal_floating_near_plugin_payload.file_to_open { + Some(file_to_open) => Ok(PluginCommand::OpenTerminalFloatingNearPlugin( + file_to_open.try_into()?, + floating_pane_coordinates, + )), + None => Err("Malformed open terminal floating near plugin payload"), + } + }, + _ => Err("Mismatched payload for OpenTerminalFloatingNearPlugin"), + }, + Some(CommandName::OpenTerminalInPlaceOfPlugin) => match protobuf_plugin_command.payload + { + Some(Payload::OpenTerminalInPlaceOfPluginPayload( + open_terminal_in_place_of_plugin_payload, + )) => match open_terminal_in_place_of_plugin_payload.file_to_open { + Some(file_to_open) => Ok(PluginCommand::OpenTerminalInPlaceOfPlugin( + file_to_open.try_into()?, + )), + None => Err("Malformed open terminal in place of plugin payload"), + }, + _ => Err("Mismatched payload for OpenTerminalInPlaceOfPlugin"), + }, + Some(CommandName::OpenCommandPaneFloatingNearPlugin) => { + match protobuf_plugin_command.payload { + Some(Payload::OpenCommandPaneFloatingNearPluginPayload( + open_command_pane_floating_near_plugin, + )) => match open_command_pane_floating_near_plugin.command_to_run { + Some(command_to_run) => { + let context: BTreeMap = + open_command_pane_floating_near_plugin + .context + .into_iter() + .map(|e| (e.name, e.value)) + .collect(); + let floating_pane_coordinates = open_command_pane_floating_near_plugin + .floating_pane_coordinates + .map(|f| f.into()); + Ok(PluginCommand::OpenCommandPaneFloatingNearPlugin( + command_to_run.try_into()?, + floating_pane_coordinates, + context, + )) + }, + None => Err("Malformed open command pane floating near plugin payload"), + }, + _ => Err("Mismatched payload for OpenCommandPaneFloatingNearPlugin"), + } + }, + Some(CommandName::OpenCommandPaneInPlaceOfPlugin) => { + match protobuf_plugin_command.payload { + Some(Payload::OpenCommandPaneInPlaceOfPluginPayload( + open_command_pane_in_place_of_plugin_payload, + )) => match open_command_pane_in_place_of_plugin_payload.command_to_run { + Some(command_to_run) => { + let context: BTreeMap = + open_command_pane_in_place_of_plugin_payload + .context + .into_iter() + .map(|e| (e.name, e.value)) + .collect(); + Ok(PluginCommand::OpenCommandPaneInPlaceOfPlugin( + command_to_run.try_into()?, + context, + )) + }, + None => Err("Malformed open command pane in place of plugin payload"), + }, + _ => Err("Mismatched payload for OpenCommandPaneInPlaceOfPlugin"), + } + }, + Some(CommandName::OpenFileNearPlugin) => match protobuf_plugin_command.payload { + Some(Payload::OpenFileNearPluginPayload(file_to_open_payload)) => { + match file_to_open_payload.file_to_open { + Some(file_to_open) => { + let context: BTreeMap = file_to_open_payload + .context + .into_iter() + .map(|e| (e.name, e.value)) + .collect(); + Ok(PluginCommand::OpenFileNearPlugin( + file_to_open.try_into()?, + context, + )) + }, + None => Err("Malformed open file payload"), + } + }, + _ => Err("Mismatched payload for OpenFileNearPlugin"), + }, + Some(CommandName::OpenFileFloatingNearPlugin) => { + match protobuf_plugin_command.payload { + Some(Payload::OpenFileFloatingNearPluginPayload(file_to_open_payload)) => { + let floating_pane_coordinates = file_to_open_payload + .floating_pane_coordinates + .map(|f| f.into()); + let context: BTreeMap = file_to_open_payload + .context + .into_iter() + .map(|e| (e.name, e.value)) + .collect(); + match file_to_open_payload.file_to_open { + Some(file_to_open) => Ok(PluginCommand::OpenFileFloatingNearPlugin( + file_to_open.try_into()?, + floating_pane_coordinates, + context, + )), + None => Err("Malformed open file payload"), + } + }, + _ => Err("Mismatched payload for OpenFileFloatingNearPlugin"), + } + }, + Some(CommandName::OpenFileInPlaceOfPlugin) => match protobuf_plugin_command.payload { + Some(Payload::OpenFileInPlaceOfPluginPayload(file_to_open_payload)) => { + match file_to_open_payload.file_to_open { + Some(file_to_open) => { + let context: BTreeMap = file_to_open_payload + .context + .into_iter() + .map(|e| (e.name, e.value)) + .collect(); + Ok(PluginCommand::OpenFileInPlaceOfPlugin( + file_to_open.try_into()?, + context, + )) + }, + None => Err("Malformed open file in place payload"), + } + }, + _ => Err("Mismatched payload for OpenFileInPlaceOfPlugin"), + }, None => Err("Unrecognized plugin command"), } } @@ -2236,6 +2410,132 @@ impl TryFrom for ProtobufPluginCommand { }, )), }), + PluginCommand::OpenCommandPaneNearPlugin(command_to_run, context) => { + let context: Vec<_> = context + .into_iter() + .map(|(name, value)| ContextItem { name, value }) + .collect(); + Ok(ProtobufPluginCommand { + name: CommandName::OpenCommandPaneNearPlugin as i32, + payload: Some(Payload::OpenCommandPaneNearPluginPayload( + OpenCommandPaneNearPluginPayload { + command_to_run: Some(command_to_run.try_into()?), + floating_pane_coordinates: None, + context, + }, + )), + }) + }, + PluginCommand::OpenCommandPaneFloatingNearPlugin( + command_to_run, + floating_pane_coordinates, + context, + ) => { + let context: Vec<_> = context + .into_iter() + .map(|(name, value)| ContextItem { name, value }) + .collect(); + Ok(ProtobufPluginCommand { + name: CommandName::OpenCommandPaneFloatingNearPlugin as i32, + payload: Some(Payload::OpenCommandPaneFloatingNearPluginPayload( + OpenCommandPaneFloatingNearPluginPayload { + command_to_run: Some(command_to_run.try_into()?), + floating_pane_coordinates: floating_pane_coordinates.map(|f| f.into()), + context, + }, + )), + }) + }, + PluginCommand::OpenTerminalNearPlugin(cwd) => Ok(ProtobufPluginCommand { + name: CommandName::OpenTerminalNearPlugin as i32, + payload: Some(Payload::OpenTerminalNearPluginPayload( + OpenTerminalNearPluginPayload { + file_to_open: Some(cwd.try_into()?), + context: vec![], // will be added in the future + }, + )), + }), + PluginCommand::OpenTerminalFloatingNearPlugin(cwd, floating_pane_coordinates) => { + Ok(ProtobufPluginCommand { + name: CommandName::OpenTerminalFloatingNearPlugin as i32, + payload: Some(Payload::OpenTerminalFloatingNearPluginPayload( + OpenTerminalFloatingNearPluginPayload { + file_to_open: Some(cwd.try_into()?), + floating_pane_coordinates: floating_pane_coordinates.map(|f| f.into()), + context: vec![], // will be added in the future + }, + )), + }) + }, + PluginCommand::OpenTerminalInPlaceOfPlugin(cwd) => Ok(ProtobufPluginCommand { + name: CommandName::OpenTerminalInPlaceOfPlugin as i32, + payload: Some(Payload::OpenTerminalInPlaceOfPluginPayload( + OpenTerminalInPlaceOfPluginPayload { + file_to_open: Some(cwd.try_into()?), + context: vec![], // will be added in the future + }, + )), + }), + PluginCommand::OpenCommandPaneInPlaceOfPlugin(command_to_run, context) => { + let context: Vec<_> = context + .into_iter() + .map(|(name, value)| ContextItem { name, value }) + .collect(); + Ok(ProtobufPluginCommand { + name: CommandName::OpenCommandPaneInPlaceOfPlugin as i32, + payload: Some(Payload::OpenCommandPaneInPlaceOfPluginPayload( + OpenCommandPaneInPlaceOfPluginPayload { + command_to_run: Some(command_to_run.try_into()?), + context, + }, + )), + }) + }, + PluginCommand::OpenFileNearPlugin(file_to_open, context) => Ok(ProtobufPluginCommand { + name: CommandName::OpenFileNearPlugin as i32, + payload: Some(Payload::OpenFileNearPluginPayload( + OpenFileNearPluginPayload { + file_to_open: Some(file_to_open.try_into()?), + floating_pane_coordinates: None, + context: context + .into_iter() + .map(|(name, value)| ContextItem { name, value }) + .collect(), + }, + )), + }), + PluginCommand::OpenFileFloatingNearPlugin( + file_to_open, + floating_pane_coordinates, + context, + ) => Ok(ProtobufPluginCommand { + name: CommandName::OpenFileFloatingNearPlugin as i32, + payload: Some(Payload::OpenFileFloatingNearPluginPayload( + OpenFileFloatingNearPluginPayload { + file_to_open: Some(file_to_open.try_into()?), + floating_pane_coordinates: floating_pane_coordinates.map(|f| f.into()), + context: context + .into_iter() + .map(|(name, value)| ContextItem { name, value }) + .collect(), + }, + )), + }), + PluginCommand::OpenFileInPlaceOfPlugin(file_to_open, context) => { + Ok(ProtobufPluginCommand { + name: CommandName::OpenFileInPlaceOfPlugin as i32, + payload: Some(Payload::OpenFileInPlaceOfPluginPayload( + OpenFileInPlaceOfPluginPayload { + file_to_open: Some(file_to_open.try_into()?), + floating_pane_coordinates: None, + context: context + .into_iter() + .map(|(name, value)| ContextItem { name, value }) + .collect(), + }, + )), + }) + }, } } }