diff options
author | Aram Drevekenin <aram@poor.dev> | 2023-09-18 16:28:06 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-18 16:28:06 +0200 |
commit | e392a66833046a2958dfcc0e1147257e59454c41 (patch) | |
tree | 7792e770ec010ff9ceb52c083882502eabee7d11 /zellij-utils | |
parent | 74a3b6363594d53f78c16a05444814d68e3fd76f (diff) |
feat(panes): in place run (#2795)
* prototype
* fix tests
* add to all the things except plugins
* add in-place to plugin commands
* fix launch-or-focus should_float and in place behavior
* various cleanups
* style(fmt): rustfmt
Diffstat (limited to 'zellij-utils')
17 files changed, 189 insertions, 7 deletions
diff --git a/zellij-utils/assets/prost/api.action.rs b/zellij-utils/assets/prost/api.action.rs index 9099b6ef5..97976393b 100644 --- a/zellij-utils/assets/prost/api.action.rs +++ b/zellij-utils/assets/prost/api.action.rs @@ -137,6 +137,8 @@ pub struct LaunchOrFocusPluginPayload { pub plugin_configuration: ::core::option::Option<PluginConfiguration>, #[prost(bool, tag = "4")] pub move_to_focused_tab: bool, + #[prost(bool, tag = "5")] + pub should_open_in_place: bool, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] diff --git a/zellij-utils/assets/prost/api.plugin_command.rs b/zellij-utils/assets/prost/api.plugin_command.rs index da13196c0..b86f95491 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" + 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" )] pub payload: ::core::option::Option<plugin_command::Payload>, } @@ -90,6 +90,12 @@ pub mod plugin_command { RequestPluginPermissionPayload(super::RequestPluginPermissionPayload), #[prost(message, tag = "39")] SwitchSessionPayload(super::SwitchSessionPayload), + #[prost(message, tag = "40")] + OpenFileInPlacePayload(super::OpenFilePayload), + #[prost(message, tag = "41")] + OpenTerminalInPlacePayload(super::OpenFilePayload), + #[prost(message, tag = "42")] + OpenCommandPaneInPlacePayload(super::OpenCommandPanePayload), } } #[allow(clippy::derive_partial_eq_without_eq)] @@ -254,6 +260,9 @@ pub enum CommandName { ReportCrash = 65, RequestPluginPermissions = 66, SwitchSession = 67, + OpenTerminalInPlace = 68, + OpenCommandInPlace = 69, + OpenFileInPlace = 70, } impl CommandName { /// String value of the enum field names used in the ProtoBuf definition. @@ -330,6 +339,9 @@ impl CommandName { CommandName::ReportCrash => "ReportCrash", CommandName::RequestPluginPermissions => "RequestPluginPermissions", CommandName::SwitchSession => "SwitchSession", + CommandName::OpenTerminalInPlace => "OpenTerminalInPlace", + CommandName::OpenCommandInPlace => "OpenCommandInPlace", + CommandName::OpenFileInPlace => "OpenFileInPlace", } } /// Creates an enum from field names used in the ProtoBuf definition. @@ -403,6 +415,9 @@ impl CommandName { "ReportCrash" => Some(Self::ReportCrash), "RequestPluginPermissions" => Some(Self::RequestPluginPermissions), "SwitchSession" => Some(Self::SwitchSession), + "OpenTerminalInPlace" => Some(Self::OpenTerminalInPlace), + "OpenCommandInPlace" => Some(Self::OpenCommandInPlace), + "OpenFileInPlace" => Some(Self::OpenFileInPlace), _ => None, } } diff --git a/zellij-utils/src/cli.rs b/zellij-utils/src/cli.rs index 323834b37..d09625450 100644 --- a/zellij-utils/src/cli.rs +++ b/zellij-utils/src/cli.rs @@ -158,6 +158,18 @@ pub enum Sessions { #[clap(short, long, value_parser, default_value("false"), takes_value(false))] floating: bool, + /// Open the new pane in place of the current pane, temporarily suspending it + #[clap( + short, + long, + value_parser, + default_value("false"), + takes_value(false), + conflicts_with("floating"), + conflicts_with("direction") + )] + in_place: bool, + /// Name of the new pane #[clap(short, long, value_parser)] name: Option<String>, @@ -183,6 +195,18 @@ pub enum Sessions { #[clap(short, long, value_parser, conflicts_with("floating"))] direction: Option<Direction>, + /// Open the new pane in place of the current pane, temporarily suspending it + #[clap( + short, + long, + value_parser, + default_value("false"), + takes_value(false), + conflicts_with("floating"), + conflicts_with("direction") + )] + in_place: bool, + /// Open the new pane in floating mode #[clap(short, long, value_parser, default_value("false"), takes_value(false))] floating: bool, @@ -292,6 +316,18 @@ pub enum CliAction { #[clap(short, long, value_parser, default_value("false"), takes_value(false))] floating: bool, + /// Open the new pane in place of the current pane, temporarily suspending it + #[clap( + short, + long, + value_parser, + default_value("false"), + takes_value(false), + conflicts_with("floating"), + conflicts_with("direction") + )] + in_place: bool, + /// Name of the new pane #[clap(short, long, value_parser)] name: Option<String>, @@ -335,6 +371,18 @@ pub enum CliAction { #[clap(short, long, value_parser, default_value("false"), takes_value(false))] floating: bool, + /// Open the new pane in place of the current pane, temporarily suspending it + #[clap( + short, + long, + value_parser, + default_value("false"), + takes_value(false), + conflicts_with("floating"), + conflicts_with("direction") + )] + in_place: bool, + /// Change the working directory of the editor #[clap(long, value_parser)] cwd: Option<PathBuf>, @@ -409,6 +457,8 @@ pub enum CliAction { #[clap(short, long, value_parser)] floating: bool, #[clap(short, long, value_parser)] + in_place: bool, + #[clap(short, long, value_parser)] move_to_focused_tab: bool, url: Url, #[clap(short, long, value_parser)] diff --git a/zellij-utils/src/data.rs b/zellij-utils/src/data.rs index fc09538cb..3702dace4 100644 --- a/zellij-utils/src/data.rs +++ b/zellij-utils/src/data.rs @@ -1061,4 +1061,7 @@ pub enum PluginCommand { ReportPanic(String), // stringified panic RequestPluginPermissions(Vec<PermissionType>), SwitchSession(ConnectToSession), + OpenTerminalInPlace(FileToOpen), // only used for the path as cwd + OpenFileInPlace(FileToOpen), + OpenCommandPaneInPlace(CommandToRun), } diff --git a/zellij-utils/src/errors.rs b/zellij-utils/src/errors.rs index 677cbc420..a06980400 100644 --- a/zellij-utils/src/errors.rs +++ b/zellij-utils/src/errors.rs @@ -343,6 +343,8 @@ pub enum ScreenContext { BreakPaneRight, BreakPaneLeft, UpdateSessionInfos, + ReplacePane, + NewInPlacePluginPane, } /// Stack call representations corresponding to the different types of [`PtyInstruction`]s. @@ -358,6 +360,7 @@ pub enum PtyContext { ClosePane, CloseTab, ReRunCommandInPane, + SpawnInPlaceTerminal, Exit, } diff --git a/zellij-utils/src/input/actions.rs b/zellij-utils/src/input/actions.rs index 054273a0a..766764c89 100644 --- a/zellij-utils/src/input/actions.rs +++ b/zellij-utils/src/input/actions.rs @@ -161,11 +161,14 @@ pub enum Action { Option<PathBuf>, Option<Direction>, bool, - ), // usize is an optional line number, Option<PathBuf> is an optional cwd, bool is floating true/false + bool, + ), // usize is an optional line number, Option<PathBuf> is an optional cwd, bool is floating true/false, second bool is in_place /// Open a new floating pane NewFloatingPane(Option<RunCommandAction>, Option<String>), // String is an optional pane name /// Open a new tiled (embedded, non-floating) pane NewTiledPane(Option<Direction>, Option<RunCommandAction>, Option<String>), // String is an + /// Open a new pane in place of the focused one, suppressing it instead + NewInPlacePane(Option<RunCommandAction>, Option<String>), // String is an // optional pane // name /// Embed focused pane in tab if floating or float focused pane if embedded @@ -204,7 +207,8 @@ pub enum Action { LeftClick(Position), RightClick(Position), MiddleClick(Position), - LaunchOrFocusPlugin(RunPlugin, bool, bool), // bools => should float, move_to_focused_tab + LaunchOrFocusPlugin(RunPlugin, bool, bool, bool), // bools => should float, + // move_to_focused_tab, should_open_in_place LeftMouseRelease(Position), RightMouseRelease(Position), MiddleMouseRelease(Position), @@ -232,6 +236,7 @@ pub enum Action { /// Open a new tiled (embedded, non-floating) plugin pane NewTiledPluginPane(RunPlugin, Option<String>), // String is an optional name NewFloatingPluginPane(RunPlugin, Option<String>), // String is an optional name + NewInPlacePluginPane(RunPlugin, Option<String>), // String is an optional name StartOrReloadPlugin(RunPlugin), CloseTerminalPane(u32), ClosePluginPane(u32), @@ -293,6 +298,7 @@ impl Action { plugin, cwd, floating, + in_place, name, close_on_exit, start_suspended, @@ -313,6 +319,8 @@ impl Action { }; if floating { Ok(vec![Action::NewFloatingPluginPane(plugin, name)]) + } else if in_place { + Ok(vec![Action::NewInPlacePluginPane(plugin, name)]) } else { // it is intentional that a new tiled plugin pane cannot include a // direction @@ -342,6 +350,8 @@ impl Action { Some(run_command_action), name, )]) + } else if in_place { + Ok(vec![Action::NewInPlacePane(Some(run_command_action), name)]) } else { Ok(vec![Action::NewTiledPane( direction, @@ -352,6 +362,8 @@ impl Action { } else { if floating { Ok(vec![Action::NewFloatingPane(None, name)]) + } else if in_place { + Ok(vec![Action::NewInPlacePane(None, name)]) } else { Ok(vec![Action::NewTiledPane(direction, None, name)]) } @@ -362,6 +374,7 @@ impl Action { file, line_number, floating, + in_place, cwd, } => { let mut file = file; @@ -380,6 +393,7 @@ impl Action { cwd, direction, floating, + in_place, )]) }, CliAction::SwitchMode { input_mode } => { @@ -501,6 +515,7 @@ impl Action { CliAction::LaunchOrFocusPlugin { url, floating, + in_place, move_to_focused_tab, configuration, } => { @@ -516,6 +531,7 @@ impl Action { run_plugin, floating, move_to_focused_tab, + in_place, )]) }, } diff --git a/zellij-utils/src/ipc.rs b/zellij-utils/src/ipc.rs index 0f3415209..a60ecc615 100644 --- a/zellij-utils/src/ipc.rs +++ b/zellij-utils/src/ipc.rs @@ -84,7 +84,7 @@ pub enum ClientToServerMsg { Option<usize>, // tab position to focus Option<(u32, bool)>, // (pane_id, is_plugin) => pane id to focus ), - Action(Action, Option<ClientId>), + Action(Action, Option<u32>, Option<ClientId>), // u32 is the terminal id ClientExited, KillSession, ConnStatus, diff --git a/zellij-utils/src/kdl/mod.rs b/zellij-utils/src/kdl/mod.rs index a7573af55..db72b80d2 100644 --- a/zellij-utils/src/kdl/mod.rs +++ b/zellij-utils/src/kdl/mod.rs @@ -886,6 +886,9 @@ impl TryFrom<(&KdlNode, &Options)> for Action { let floating = command_metadata .and_then(|c_m| kdl_child_bool_value_for_entry(c_m, "floating")) .unwrap_or(false); + let in_place = command_metadata + .and_then(|c_m| kdl_child_bool_value_for_entry(c_m, "in_place")) + .unwrap_or(false); let run_command_action = RunCommandAction { command: PathBuf::from(command), args, @@ -896,6 +899,8 @@ impl TryFrom<(&KdlNode, &Options)> for Action { }; if floating { Ok(Action::NewFloatingPane(Some(run_command_action), name)) + } else if in_place { + Ok(Action::NewInPlacePane(Some(run_command_action), name)) } else { Ok(Action::NewTiledPane( direction, @@ -923,6 +928,9 @@ impl TryFrom<(&KdlNode, &Options)> for Action { let move_to_focused_tab = command_metadata .and_then(|c_m| kdl_child_bool_value_for_entry(c_m, "move_to_focused_tab")) .unwrap_or(false); + let should_open_in_place = command_metadata + .and_then(|c_m| kdl_child_bool_value_for_entry(c_m, "in_place")) + .unwrap_or(false); let current_dir = std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")); let location = RunPluginLocation::parse(&plugin_path, Some(current_dir))?; let configuration = KdlLayoutParser::parse_plugin_user_configuration(&kdl_action)?; @@ -935,6 +943,7 @@ impl TryFrom<(&KdlNode, &Options)> for Action { run_plugin, should_float, move_to_focused_tab, + should_open_in_place, )) }, "PreviousSwapLayout" => Ok(Action::PreviousSwapLayout), diff --git a/zellij-utils/src/plugin_api/action.proto b/zellij-utils/src/plugin_api/action.proto index 7e40bde24..1545b9bf4 100644 --- a/zellij-utils/src/plugin_api/action.proto +++ b/zellij-utils/src/plugin_api/action.proto @@ -85,6 +85,7 @@ message LaunchOrFocusPluginPayload { bool should_float = 2; optional PluginConfiguration plugin_configuration = 3; bool move_to_focused_tab = 4; + bool should_open_in_place = 5; } message GoToTabNamePayload { diff --git a/zellij-utils/src/plugin_api/action.rs b/zellij-utils/src/plugin_api/action.rs index 0d70af692..bba6e821c 100644 --- a/zellij-utils/src/plugin_api/action.rs +++ b/zellij-utils/src/plugin_api/action.rs @@ -232,12 +232,14 @@ impl TryFrom<ProtobufAction> for Action { .and_then(|d| ProtobufResizeDirection::from_i32(d)) .and_then(|d| d.try_into().ok()); let should_float = payload.should_float; + let should_be_in_place = false; Ok(Action::EditFile( file_to_edit, line_number, cwd, direction, should_float, + should_be_in_place, )) }, _ => Err("Wrong payload for Action::NewPane"), @@ -400,10 +402,12 @@ impl TryFrom<ProtobufAction> for Action { }; let should_float = payload.should_float; let move_to_focused_tab = payload.move_to_focused_tab; + let should_open_in_place = payload.should_open_in_place; Ok(Action::LaunchOrFocusPlugin( run_plugin, should_float, move_to_focused_tab, + should_open_in_place, )) }, _ => Err("Wrong payload for Action::LaunchOrFocusPlugin"), @@ -814,7 +818,14 @@ impl TryFrom<Action> for ProtobufAction { })), }) }, - Action::EditFile(path_to_file, line_number, cwd, direction, should_float) => { + Action::EditFile( + path_to_file, + line_number, + cwd, + direction, + should_float, + _should_be_in_place, + ) => { let file_to_edit = path_to_file.display().to_string(); let cwd = cwd.map(|cwd| cwd.display().to_string()); let direction: Option<i32> = direction @@ -959,7 +970,12 @@ impl TryFrom<Action> for ProtobufAction { optional_payload: Some(OptionalPayload::MiddleClickPayload(position)), }) }, - Action::LaunchOrFocusPlugin(run_plugin, should_float, move_to_focused_tab) => { + Action::LaunchOrFocusPlugin( + run_plugin, + should_float, + move_to_focused_tab, + should_open_in_place, + ) => { let url: Url = Url::from(&run_plugin.location); Ok(ProtobufAction { name: ProtobufActionName::LaunchOrFocusPlugin as i32, @@ -968,6 +984,7 @@ impl TryFrom<Action> for ProtobufAction { plugin_url: url.into(), should_float, move_to_focused_tab, + should_open_in_place, plugin_configuration: Some(run_plugin.configuration.try_into()?), }, )), @@ -1149,6 +1166,8 @@ impl TryFrom<Action> for ProtobufAction { }), Action::NoOp | Action::Confirm + | Action::NewInPlacePane(..) + | Action::NewInPlacePluginPane(..) | Action::Deny | Action::Copy | Action::SkipConfirm(..) => Err("Unsupported action"), diff --git a/zellij-utils/src/plugin_api/plugin_command.proto b/zellij-utils/src/plugin_api/plugin_command.proto index fed8ec54d..17b153810 100644 --- a/zellij-utils/src/plugin_api/plugin_command.proto +++ b/zellij-utils/src/plugin_api/plugin_command.proto @@ -79,6 +79,9 @@ enum CommandName { ReportCrash = 65; RequestPluginPermissions = 66; SwitchSession = 67; + OpenTerminalInPlace = 68; + OpenCommandInPlace = 69; + OpenFileInPlace = 70; } message PluginCommand { @@ -122,6 +125,9 @@ message PluginCommand { string report_crash_payload = 37; RequestPluginPermissionPayload request_plugin_permission_payload = 38; SwitchSessionPayload switch_session_payload = 39; + OpenFilePayload open_file_in_place_payload = 40; + OpenFilePayload open_terminal_in_place_payload = 41; + OpenCommandPanePayload open_command_pane_in_place_payload = 42; } } diff --git a/zellij-utils/src/plugin_api/plugin_command.rs b/zellij-utils/src/plugin_api/plugin_command.rs index 25773ba3a..3d34f10fc 100644 --- a/zellij-utils/src/plugin_api/plugin_command.rs +++ b/zellij-utils/src/plugin_api/plugin_command.rs @@ -82,7 +82,7 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand { None => Err("Malformed open file payload"), } }, - _ => Err("Mismatched payload for OpenFile"), + _ => Err("Mismatched payload for OpenFileFloating"), }, Some(CommandName::OpenTerminal) => match protobuf_plugin_command.payload { Some(Payload::OpenTerminalPayload(file_to_open_payload)) => { @@ -520,6 +520,39 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand { }, _ => Err("Mismatched payload for SwitchSession"), }, + Some(CommandName::OpenTerminalInPlace) => match protobuf_plugin_command.payload { + Some(Payload::OpenTerminalInPlacePayload(file_to_open_payload)) => { + match file_to_open_payload.file_to_open { + Some(file_to_open) => { + Ok(PluginCommand::OpenTerminalInPlace(file_to_open.try_into()?)) + }, + None => Err("Malformed open terminal in-place payload"), + } + }, + _ => Err("Mismatched payload for OpenTerminalInPlace"), + }, + Some(CommandName::OpenFileInPlace) => match protobuf_plugin_command.payload { + Some(Payload::OpenFileInPlacePayload(file_to_open_payload)) => { + match file_to_open_payload.file_to_open { + Some(file_to_open) => { + Ok(PluginCommand::OpenFileInPlace(file_to_open.try_into()?)) + }, + None => Err("Malformed open file in place payload"), + } + }, + _ => Err("Mismatched payload for OpenFileInPlace"), + }, + Some(CommandName::OpenCommandInPlace) => match protobuf_plugin_command.payload { + Some(Payload::OpenCommandPaneInPlacePayload(command_to_run_payload)) => { + |