diff options
| author | Aram Drevekenin <aram@poor.dev> | 2026-02-17 15:43:28 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-02-17 15:43:28 +0100 |
| commit | 4e66a0beff5e41bda1dbde521fa1d2858c46fe7b (patch) | |
| tree | 380bee5eeac56bea2ebf341cccbe69615585e394 /zellij-utils/src/plugin_api/plugin_command.rs | |
| parent | Fix startup message and cache file creation (#4705) (diff) | |
| download | sl0ppij-4e66a0beff5e41bda1dbde521fa1d2858c46fe7b.tar.gz sl0ppij-4e66a0beff5e41bda1dbde521fa1d2858c46fe7b.tar.xz sl0ppij-4e66a0beff5e41bda1dbde521fa1d2858c46fe7b.zip | |
Revamp the sequence plugin (#4713)
* initial pipe interface
* initial open_x_pane_in_new_tab plugin api implementation
* fix: send CommandPaneExited for command panes opened as initial_terminals in new tabs from plugins
* open panes in place of specific pane id plugin commands - initial implementation
* sequence and plugin api ux
* focus self when starting
* combine ui and pipe paths
* highlight selected pane
* initial sequence removal of editing capabilities
* fix: translate plugin paths in api
* properly trim commands when loaded from pipe or pasted text
* minor ux fixes
* get ctrl c to work properly
* behavior fixes
* more ui fixes
* fix tests
* close tab and end sequence properly
* default to AND
* zellij sequence alias
* add alias
* consolidate paths
* rustfmt
* fix ui padding
* add pr
* fix: reset scrolling when resetting terminal state
Diffstat (limited to 'zellij-utils/src/plugin_api/plugin_command.rs')
| -rw-r--r-- | zellij-utils/src/plugin_api/plugin_command.rs | 353 |
1 files changed, 347 insertions, 6 deletions
diff --git a/zellij-utils/src/plugin_api/plugin_command.rs b/zellij-utils/src/plugin_api/plugin_command.rs index 94f5e1e1..632fe167 100644 --- a/zellij-utils/src/plugin_api/plugin_command.rs +++ b/zellij-utils/src/plugin_api/plugin_command.rs @@ -56,12 +56,16 @@ pub use super::generated_api::api::{ OpenCommandPaneFloatingNearPluginPayload, OpenCommandPaneFloatingNearPluginResponse as ProtobufOpenCommandPaneFloatingNearPluginResponse, OpenCommandPaneFloatingResponse as ProtobufOpenCommandPaneFloatingResponse, + OpenCommandPaneInPlaceOfPaneIdPayload, + OpenCommandPaneInPlaceOfPaneIdResponse as ProtobufOpenCommandPaneInPlaceOfPaneIdResponse, OpenCommandPaneInPlaceOfPluginPayload, OpenCommandPaneInPlaceOfPluginResponse as ProtobufOpenCommandPaneInPlaceOfPluginResponse, OpenCommandPaneInPlaceResponse as ProtobufOpenCommandPaneInPlaceResponse, OpenCommandPaneNearPluginPayload, OpenCommandPaneNearPluginResponse as ProtobufOpenCommandPaneNearPluginResponse, OpenCommandPanePayload, OpenCommandPaneResponse as ProtobufOpenCommandPaneResponse, + OpenEditPaneInPlaceOfPaneIdPayload, + OpenEditPaneInPlaceOfPaneIdResponse as ProtobufOpenEditPaneInPlaceOfPaneIdResponse, OpenFileFloatingNearPluginPayload, OpenFileFloatingNearPluginResponse as ProtobufOpenFileFloatingNearPluginResponse, OpenFileFloatingResponse as ProtobufOpenFileFloatingResponse, @@ -69,7 +73,10 @@ pub use super::generated_api::api::{ OpenFileInPlaceOfPluginResponse as ProtobufOpenFileInPlaceOfPluginResponse, OpenFileInPlaceResponse as ProtobufOpenFileInPlaceResponse, OpenFileNearPluginPayload, OpenFileNearPluginResponse as ProtobufOpenFileNearPluginResponse, OpenFilePayload, - OpenFileResponse as ProtobufOpenFileResponse, OpenTerminalFloatingNearPluginPayload, + OpenFileResponse as ProtobufOpenFileResponse, + OpenPaneInNewTabResponse as ProtobufOpenPaneInNewTabResponse, + OpenPluginPaneInNewTabPayload as ProtobufOpenPluginPaneInNewTabPayload, + OpenTerminalFloatingNearPluginPayload, OpenTerminalFloatingNearPluginResponse as ProtobufOpenTerminalFloatingNearPluginResponse, OpenTerminalFloatingResponse as ProtobufOpenTerminalFloatingResponse, OpenTerminalInPlaceOfPluginPayload, @@ -77,6 +84,8 @@ pub use super::generated_api::api::{ OpenTerminalInPlaceResponse as ProtobufOpenTerminalInPlaceResponse, OpenTerminalNearPluginPayload, OpenTerminalNearPluginResponse as ProtobufOpenTerminalNearPluginResponse, + OpenTerminalPaneInPlaceOfPaneIdPayload, + OpenTerminalPaneInPlaceOfPaneIdResponse as ProtobufOpenTerminalPaneInPlaceOfPaneIdResponse, OpenTerminalResponse as ProtobufOpenTerminalResponse, OverrideLayoutPayload, PageScrollDownInPaneIdPayload, PageScrollUpInPaneIdPayload, PaneId as ProtobufPaneId, PaneIdAndFloatingPaneCoordinates, PaneType as ProtobufPaneType, ParseLayoutPayload, @@ -2269,6 +2278,129 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand { _ => Err("Mismatched payload for GetSessionEnvironmentVariables"), } }, + Some(CommandName::OpenCommandPaneInNewTab) => match protobuf_plugin_command.payload { + Some(Payload::OpenCommandPaneInNewTabPayload(payload)) => { + match payload.command_to_run { + Some(command_to_run) => { + let context: BTreeMap<String, String> = payload + .context + .into_iter() + .map(|e| (e.name, e.value)) + .collect(); + Ok(PluginCommand::OpenCommandPaneInNewTab( + command_to_run.try_into()?, + context, + )) + }, + None => Err("Malformed open_command_pane_in_new_tab payload"), + } + }, + _ => Err("Mismatched payload for OpenCommandPaneInNewTab"), + }, + Some(CommandName::OpenPluginPaneInNewTab) => match protobuf_plugin_command.payload { + Some(Payload::OpenPluginPaneInNewTabPayload(payload)) => { + let configuration: BTreeMap<String, String> = + payload.configuration.into_iter().collect(); + let context: BTreeMap<String, String> = payload + .context + .into_iter() + .map(|e| (e.name, e.value)) + .collect(); + Ok(PluginCommand::OpenPluginPaneInNewTab { + plugin_url: payload.plugin_url, + configuration, + context, + }) + }, + _ => Err("Mismatched payload for OpenPluginPaneInNewTab"), + }, + Some(CommandName::OpenEditorPaneInNewTab) => match protobuf_plugin_command.payload { + Some(Payload::OpenEditorPaneInNewTabPayload(payload)) => { + match payload.file_to_open { + Some(file) => { + let context: BTreeMap<String, String> = payload + .context + .into_iter() + .map(|e| (e.name, e.value)) + .collect(); + Ok(PluginCommand::OpenEditorPaneInNewTab( + file.try_into()?, + context, + )) + }, + None => Err("Malformed open_editor_pane_in_new_tab payload"), + } + }, + _ => Err("Mismatched payload for OpenEditorPaneInNewTab"), + }, + Some(CommandName::OpenCommandPaneInPlaceOfPaneId) => { + match protobuf_plugin_command.payload { + Some(Payload::OpenCommandPaneInPlaceOfPaneIdPayload(payload)) => { + match (payload.pane_id_to_replace, payload.command_to_run) { + (Some(pane_id), Some(command_to_run)) => { + let context: BTreeMap<String, String> = payload + .context + .into_iter() + .map(|e| (e.name, e.value)) + .collect(); + Ok(PluginCommand::OpenCommandPaneInPlaceOfPaneId( + pane_id.try_into()?, + command_to_run.try_into()?, + payload.close_replaced_pane, + context, + )) + }, + _ => Err("Malformed open_command_pane_in_place_of_pane_id payload"), + } + }, + _ => Err("Mismatched payload for OpenCommandPaneInPlaceOfPaneId"), + } + }, + Some(CommandName::OpenTerminalPaneInPlaceOfPaneId) => { + match protobuf_plugin_command.payload { + Some(Payload::OpenTerminalPaneInPlaceOfPaneIdPayload(payload)) => { + match payload.pane_id_to_replace { + Some(pane_id) => { + let cwd = payload.cwd.map(|f| f.try_into()).transpose()?; + let cwd = cwd.unwrap_or_else(|| crate::data::FileToOpen { + path: std::path::PathBuf::from("."), + ..Default::default() + }); + Ok(PluginCommand::OpenTerminalPaneInPlaceOfPaneId( + pane_id.try_into()?, + cwd, + payload.close_replaced_pane, + )) + }, + None => Err("Malformed open_terminal_pane_in_place_of_pane_id payload"), + } + }, + _ => Err("Mismatched payload for OpenTerminalPaneInPlaceOfPaneId"), + } + }, + Some(CommandName::OpenEditPaneInPlaceOfPaneId) => { + match protobuf_plugin_command.payload { + Some(Payload::OpenEditPaneInPlaceOfPaneIdPayload(payload)) => { + match (payload.pane_id_to_replace, payload.file_to_open) { + (Some(pane_id), Some(file_to_open)) => { + let context: BTreeMap<String, String> = payload + .context + .into_iter() + .map(|e| (e.name, e.value)) + .collect(); + Ok(PluginCommand::OpenEditPaneInPlaceOfPaneId( + pane_id.try_into()?, + file_to_open.try_into()?, + payload.close_replaced_pane, + context, + )) + }, + _ => Err("Malformed open_edit_pane_in_place_of_pane_id payload"), + } + }, + _ => Err("Mismatched payload for OpenEditPaneInPlaceOfPaneId"), + } + }, None => Err("Unrecognized plugin command"), } } @@ -3697,6 +3829,114 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand { payload: Some(Payload::GetSessionEnvironmentVariablesPayload(payload)), }) }, + PluginCommand::OpenCommandPaneInNewTab(command_to_run, context) => { + let context: Vec<_> = context + .into_iter() + .map(|(name, value)| ContextItem { name, value }) + .collect(); + Ok(ProtobufPluginCommand { + name: CommandName::OpenCommandPaneInNewTab as i32, + payload: Some(Payload::OpenCommandPaneInNewTabPayload( + OpenCommandPanePayload { + command_to_run: Some(command_to_run.try_into()?), + floating_pane_coordinates: None, + context, + }, + )), + }) + }, + PluginCommand::OpenPluginPaneInNewTab { + plugin_url, + configuration, + context, + } => { + let context: Vec<_> = context + .into_iter() + .map(|(name, value)| ContextItem { name, value }) + .collect(); + let configuration: std::collections::HashMap<String, String> = + configuration.into_iter().collect(); + Ok(ProtobufPluginCommand { + name: CommandName::OpenPluginPaneInNewTab as i32, + payload: Some(Payload::OpenPluginPaneInNewTabPayload( + ProtobufOpenPluginPaneInNewTabPayload { + plugin_url, + configuration, + context, + }, + )), + }) + }, + PluginCommand::OpenEditorPaneInNewTab(file_to_open, context) => { + let context: Vec<_> = context + .into_iter() + .map(|(name, value)| ContextItem { name, value }) + .collect(); + Ok(ProtobufPluginCommand { + name: CommandName::OpenEditorPaneInNewTab as i32, + payload: Some(Payload::OpenEditorPaneInNewTabPayload(OpenFilePayload { + file_to_open: Some(file_to_open.try_into()?), + floating_pane_coordinates: None, + context, + })), + }) + }, + PluginCommand::OpenCommandPaneInPlaceOfPaneId( + pane_id, + command_to_run, + close_replaced_pane, + context, + ) => { + let context: Vec<_> = context + .into_iter() + .map(|(name, value)| ContextItem { name, value }) + .collect(); + Ok(ProtobufPluginCommand { + name: CommandName::OpenCommandPaneInPlaceOfPaneId as i32, + payload: Some(Payload::OpenCommandPaneInPlaceOfPaneIdPayload( + OpenCommandPaneInPlaceOfPaneIdPayload { + pane_id_to_replace: Some(pane_id.try_into()?), + command_to_run: Some(command_to_run.try_into()?), + close_replaced_pane, + context, + }, + )), + }) + }, + PluginCommand::OpenTerminalPaneInPlaceOfPaneId(pane_id, cwd, close_replaced_pane) => { + Ok(ProtobufPluginCommand { + name: CommandName::OpenTerminalPaneInPlaceOfPaneId as i32, + payload: Some(Payload::OpenTerminalPaneInPlaceOfPaneIdPayload( + OpenTerminalPaneInPlaceOfPaneIdPayload { + pane_id_to_replace: Some(pane_id.try_into()?), + cwd: Some(cwd.try_into()?), + close_replaced_pane, + }, + )), + }) + }, + PluginCommand::OpenEditPaneInPlaceOfPaneId( + pane_id, + file_to_open, + close_replaced_pane, + context, + ) => { + let context: Vec<_> = context + .into_iter() + .map(|(name, value)| ContextItem { name, value }) + .collect(); + Ok(ProtobufPluginCommand { + name: CommandName::OpenEditPaneInPlaceOfPaneId as i32, + payload: Some(Payload::OpenEditPaneInPlaceOfPaneIdPayload( + OpenEditPaneInPlaceOfPaneIdPayload { + pane_id_to_replace: Some(pane_id.try_into()?), + file_to_open: Some(file_to_open.try_into()?), + close_replaced_pane, + context, + }, + )), + }) + }, } } } @@ -3706,12 +3946,14 @@ use crate::data::{ BreakPanesToNewTabResponse, BreakPanesToTabWithIdResponse, BreakPanesToTabWithIndexResponse, FocusOrCreateTabResponse, NewTabResponse, NewTabsResponse, OpenCommandPaneBackgroundResponse, OpenCommandPaneFloatingNearPluginResponse, OpenCommandPaneFloatingResponse, - OpenCommandPaneInPlaceOfPluginResponse, OpenCommandPaneInPlaceResponse, - OpenCommandPaneNearPluginResponse, OpenCommandPaneResponse, OpenFileFloatingNearPluginResponse, + OpenCommandPaneInPlaceOfPaneIdResponse, OpenCommandPaneInPlaceOfPluginResponse, + OpenCommandPaneInPlaceResponse, OpenCommandPaneNearPluginResponse, OpenCommandPaneResponse, + OpenEditPaneInPlaceOfPaneIdResponse, OpenFileFloatingNearPluginResponse, OpenFileFloatingResponse, OpenFileInPlaceOfPluginResponse, OpenFileInPlaceResponse, - OpenFileNearPluginResponse, OpenFileResponse, OpenTerminalFloatingNearPluginResponse, - OpenTerminalFloatingResponse, OpenTerminalInPlaceOfPluginResponse, OpenTerminalInPlaceResponse, - OpenTerminalNearPluginResponse, OpenTerminalResponse, + OpenFileNearPluginResponse, OpenFileResponse, OpenPaneInNewTabResponse, + OpenTerminalFloatingNearPluginResponse, OpenTerminalFloatingResponse, + OpenTerminalInPlaceOfPluginResponse, OpenTerminalInPlaceResponse, + OpenTerminalNearPluginResponse, OpenTerminalPaneInPlaceOfPaneIdResponse, OpenTerminalResponse, }; impl TryFrom<ProtobufNewTabResponse> for NewTabResponse { @@ -3827,6 +4069,16 @@ impl From<BreakPanesToTabWithIndexResponse> for ProtobufBreakPanesToTabWithIndex } } +impl TryFrom<ProtobufBreakPanesToTabWithIdResponse> for BreakPanesToTabWithIdResponse { + type Error = &'static str; + fn try_from(protobuf: ProtobufBreakPanesToTabWithIdResponse) -> Result<Self, Self::Error> { + match protobuf.result { + Some(break_panes_to_tab_with_id_response::Result::TabId(id)) => Ok(Some(id as usize)), + Some(break_panes_to_tab_with_id_response::Result::None(_)) | None => Ok(None), + } + } +} + impl From<BreakPanesToTabWithIdResponse> for ProtobufBreakPanesToTabWithIdResponse { fn from(response: BreakPanesToTabWithIdResponse) -> Self { match response { @@ -4205,3 +4457,92 @@ impl From<OpenCommandPaneBackgroundResponse> for ProtobufOpenCommandPaneBackgrou } } } + +impl TryFrom<ProtobufOpenPaneInNewTabResponse> for OpenPaneInNewTabResponse { + type Error = &'static str; + fn try_from(protobuf: ProtobufOpenPaneInNewTabResponse) -> Result<Self, Self::Error> { + let tab_id = protobuf.tab_id.map(|id| id as usize); + let pane_id = match protobuf.pane_id { + Some(pane_id) => Some(pane_id.try_into()?), + None => None, + }; + Ok(OpenPaneInNewTabResponse { tab_id, pane_id }) + } +} + +impl From<OpenPaneInNewTabResponse> for ProtobufOpenPaneInNewTabResponse { + fn from(response: OpenPaneInNewTabResponse) -> Self { + ProtobufOpenPaneInNewTabResponse { + tab_id: response.tab_id.map(|id| id as u64), + pane_id: response.pane_id.map(|p| p.try_into().unwrap()), + } + } +} + +impl TryFrom<ProtobufOpenCommandPaneInPlaceOfPaneIdResponse> + for OpenCommandPaneInPlaceOfPaneIdResponse +{ + type Error = &'static str; + fn try_from( + protobuf: ProtobufOpenCommandPaneInPlaceOfPaneIdResponse, + ) -> Result<Self, Self::Error> { + match protobuf.pane_id { + Some(pane_id) => Ok(Some(pane_id.try_into()?)), + None => Ok(None), + } + } +} + +impl From<OpenCommandPaneInPlaceOfPaneIdResponse> + for ProtobufOpenCommandPaneInPlaceOfPaneIdResponse +{ + fn from(response: OpenCommandPaneInPlaceOfPaneIdResponse) -> Self { + ProtobufOpenCommandPaneInPlaceOfPaneIdResponse { + pane_id: response.map(|p| p.try_into().unwrap()), + } + } +} + +impl TryFrom<ProtobufOpenTerminalPaneInPlaceOfPaneIdResponse> + for OpenTerminalPaneInPlaceOfPaneIdResponse +{ + type Error = &'static str; + fn try_from( + protobuf: ProtobufOpenTerminalPaneInPlaceOfPaneIdResponse, + ) -> Result<Self, Self::Error> { + match protobuf.pane_id { + Some(pane_id) => Ok(Some(pane_id.try_into()?)), + None => Ok(None), + } + } +} + +impl From<OpenTerminalPaneInPlaceOfPaneIdResponse> + for ProtobufOpenTerminalPaneInPlaceOfPaneIdResponse +{ + fn from(response: OpenTerminalPaneInPlaceOfPaneIdResponse) -> Self { + ProtobufOpenTerminalPaneInPlaceOfPaneIdResponse { + pane_id: response.map(|p| p.try_into().unwrap()), + } + } +} + +impl TryFrom<ProtobufOpenEditPaneInPlaceOfPaneIdResponse> for OpenEditPaneInPlaceOfPaneIdResponse { + type Error = &'static str; + fn try_from( + protobuf: ProtobufOpenEditPaneInPlaceOfPaneIdResponse, + ) -> Result<Self, Self::Error> { + match protobuf.pane_id { + Some(pane_id) => Ok(Some(pane_id.try_into()?)), + None => Ok(None), + } + } +} + +impl From<OpenEditPaneInPlaceOfPaneIdResponse> for ProtobufOpenEditPaneInPlaceOfPaneIdResponse { + fn from(response: OpenEditPaneInPlaceOfPaneIdResponse) -> Self { + ProtobufOpenEditPaneInPlaceOfPaneIdResponse { + pane_id: response.map(|p| p.try_into().unwrap()), + } + } +} |
