summaryrefslogtreecommitdiffstats
path: root/zellij-utils
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2023-09-18 16:28:06 +0200
committerGitHub <noreply@github.com>2023-09-18 16:28:06 +0200
commite392a66833046a2958dfcc0e1147257e59454c41 (patch)
tree7792e770ec010ff9ceb52c083882502eabee7d11 /zellij-utils
parent74a3b6363594d53f78c16a05444814d68e3fd76f (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')
-rw-r--r--zellij-utils/assets/prost/api.action.rs2
-rw-r--r--zellij-utils/assets/prost/api.plugin_command.rs17
-rw-r--r--zellij-utils/src/cli.rs50
-rw-r--r--zellij-utils/src/data.rs3
-rw-r--r--zellij-utils/src/errors.rs3
-rw-r--r--zellij-utils/src/input/actions.rs20
-rw-r--r--zellij-utils/src/ipc.rs2
-rw-r--r--zellij-utils/src/kdl/mod.rs9
-rw-r--r--zellij-utils/src/plugin_api/action.proto1
-rw-r--r--zellij-utils/src/plugin_api/action.rs23
-rw-r--r--zellij-utils/src/plugin_api/plugin_command.proto6
-rw-r--r--zellij-utils/src/plugin_api/plugin_command.rs55
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap1
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap1
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_plugins_override_config_plugins.snap1
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap1
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap1
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)) => {
+