summaryrefslogtreecommitdiffstats
path: root/zellij-utils/src
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/src
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/src')
-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
15 files changed, 171 insertions, 6 deletions
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)) => {
+ match command_to_run_payload.command_to_run {
+ Some(command_to_run) => Ok(PluginCommand::OpenCommandPaneInPlace(
+ command_to_run.try_into()?,
+ )),
+ None => Err("Malformed open command pane in-place payload"),
+ }
+ },
+ _ => Err("Mismatched payload for OpenCommandPaneInPlace"),
+ },
None => Err("Unrecognized plugin command"),
}
}
@@ -875,6 +908,26 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand {
pane_id_is_plugin: switch_to_session.pane_id.map(|p| p.1),
})),
}),
+ PluginCommand::OpenTerminalInPlace(cwd) => Ok(ProtobufPluginCommand {
+ name: CommandName::OpenTerminalInPlace as i32,
+ payload: Some(Payload::OpenTerminalInPlacePayload(OpenFilePayload {
+ file_to_open: Some(cwd.try_into()?),
+ })),
+ }),
+ PluginCommand::OpenFileInPlace(file_to_open) => Ok(ProtobufPluginCommand {
+ name: CommandName::OpenFileInPlace as i32,
+ payload: Some(Payload::OpenFileInPlacePayload(OpenFilePayload {
+ file_to_open: Some(file_to_open.try_into()?),
+ })),
+ }),
+ PluginCommand::OpenCommandPaneInPlace(command_to_run) => Ok(ProtobufPluginCommand {
+ name: CommandName::OpenCommandInPlace as i32,
+ payload: Some(Payload::OpenCommandPaneInPlacePayload(
+ OpenCommandPanePayload {
+ command_to_run: Some(command_to_run.try_into()?),
+ },
+ )),
+ }),
}
}
}
diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap
index 2f0a54b9d..971547415 100644
--- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap
+++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap
@@ -2506,6 +2506,7 @@ Config {
},
true,
true,
+ false,
),
SwitchToMode(
Normal,
diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap
index 7ceedc681..589de2328 100644
--- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap
+++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap
@@ -2506,6 +2506,7 @@ Config {
},
true,
true,
+ false,
),
SwitchToMode(
Normal,
diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_plugins_override_config_plugins.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_plugins_override_config_plugins.snap
index 9c8dda671..ab867fa70 100644
--- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_plugins_override_config_plugins.snap
+++ b/