From ca0048bdcb6d5f3bc0d7f05806efe1319a218e93 Mon Sep 17 00:00:00 2001 From: Aram Drevekenin Date: Tue, 1 Jul 2025 20:17:37 +0200 Subject: [PATCH] feat: stack pane action (#4255) * refactor: group placement properties * add stackpane cli and keybinding * add test * refactor: move spawn vertically/horizontally to spawnterminal * fix tests and cleanups * some cleanups and minor fixes * more cleanups * add stack action to the UI * style(fmt): rustfmt * fix serialization * add to default config * fix e2e tests * style(fmt): rustfmt * fix cli * fix tests * docs(changelog): add PR --- CHANGELOG.md | 1 + default-plugins/configuration/src/presets.rs | 6 + default-plugins/status-bar/src/one_line_ui.rs | 1 + src/main.rs | 4 + src/tests/e2e/cases.rs | 1 - zellij-server/src/panes/tiled_panes/mod.rs | 66 ++ ...ommand_pane_background_plugin_command.snap | 6 +- ..._command_pane_floating_plugin_command.snap | 8 +- ...sts__open_command_pane_plugin_command.snap | 8 +- ...ts__open_file_floating_plugin_command.snap | 10 +- ...lugin_tests__open_file_plugin_command.snap | 10 +- ...ile_with_line_floating_plugin_command.snap | 10 +- ...s__open_file_with_line_plugin_command.snap | 10 +- ...open_terminal_floating_plugin_command.snap | 8 +- ...n_tests__open_terminal_plugin_command.snap | 8 +- zellij-server/src/plugins/zellij_exports.rs | 29 +- zellij-server/src/pty.rs | 238 +++--- zellij-server/src/route.rs | 164 ++--- zellij-server/src/screen.rs | 45 +- zellij-server/src/tab/mod.rs | 453 +++++++++++- ...b_integration_tests__new_stacked_pane.snap | 24 + .../src/tab/unit/tab_integration_tests.rs | 686 +++++++----------- zellij-server/src/tab/unit/tab_tests.rs | 67 +- zellij-server/src/unit/screen_tests.rs | 42 +- ...i_edit_action_with_default_parameters.snap | 2 +- ...send_cli_edit_action_with_line_number.snap | 2 +- ..._cli_edit_action_with_split_direction.snap | 2 +- ..._new_pane_action_with_command_and_cwd.snap | 3 +- ...w_pane_action_with_default_parameters.snap | 2 +- ...on_with_floating_pane_and_coordinates.snap | 2 +- ..._new_pane_action_with_split_direction.snap | 2 +- zellij-utils/assets/config/default.kdl | 1 + zellij-utils/assets/prost/api.action.rs | 3 + zellij-utils/src/cli.rs | 18 + zellij-utils/src/input/actions.rs | 7 + zellij-utils/src/kdl/mod.rs | 49 ++ ..._config_from_default_assets_to_string.snap | 1 + ...efault_assets_to_string_with_comments.snap | 1 + zellij-utils/src/plugin_api/action.proto | 1 + zellij-utils/src/plugin_api/action.rs | 8 + ..._default_config_with_no_cli_arguments.snap | 14 + ...out_env_vars_override_config_env_vars.snap | 14 + ..._layout_themes_override_config_themes.snap | 14 + ..._ui_config_overrides_config_ui_config.snap | 14 + 44 files changed, 1202 insertions(+), 863 deletions(-) create mode 100644 zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__new_stacked_pane.snap diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ee3babd..55b38f54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) * feat: web-client, allowing users to share sessions in the browser (https://github.com/zellij-org/zellij/pull/4242) * performance: consolidate renders (https://github.com/zellij-org/zellij/pull/4245) * feat: add plugin API to replace a pane with another existing pane (https://github.com/zellij-org/zellij/pull/4246) +* feat: add "stack" keybinding and CLI action to add a stacked pane to the current pane (https://github.com/zellij-org/zellij/pull/4255) ## [0.42.2] - 2025-04-15 * refactor(terminal): track scroll_region as tuple rather than Option (https://github.com/zellij-org/zellij/pull/4082) diff --git a/default-plugins/configuration/src/presets.rs b/default-plugins/configuration/src/presets.rs index a26f51a4..0c972a1d 100644 --- a/default-plugins/configuration/src/presets.rs +++ b/default-plugins/configuration/src/presets.rs @@ -31,6 +31,7 @@ keybinds clear-defaults=true {{ bind "n" {{ NewPane; SwitchToMode "Locked"; }} bind "d" {{ NewPane "Down"; SwitchToMode "Locked"; }} bind "r" {{ NewPane "Right"; SwitchToMode "Locked"; }} + bind "s" {{ NewPane "stacked"; SwitchToMode "Locked"; }} bind "x" {{ CloseFocus; SwitchToMode "Locked"; }} bind "f" {{ ToggleFocusFullscreen; SwitchToMode "Locked"; }} bind "z" {{ TogglePaneFrames; SwitchToMode "Locked"; }} @@ -244,6 +245,7 @@ keybinds clear-defaults=true {{ bind "n" {{ NewPane; SwitchToMode "Normal"; }} bind "d" {{ NewPane "Down"; SwitchToMode "Normal"; }} bind "r" {{ NewPane "Right"; SwitchToMode "Normal"; }} + bind "s" {{ NewPane "stacked"; SwitchToMode "Normal"; }} bind "x" {{ CloseFocus; SwitchToMode "Normal"; }} bind "f" {{ ToggleFocusFullscreen; SwitchToMode "Normal"; }} bind "z" {{ TogglePaneFrames; SwitchToMode "Normal"; }} @@ -468,6 +470,7 @@ keybinds clear-defaults=true {{ bind "n" {{ NewPane; SwitchToMode "Normal"; }} bind "d" {{ NewPane "Down"; SwitchToMode "Normal"; }} bind "r" {{ NewPane "Right"; SwitchToMode "Normal"; }} + bind "s" {{ NewPane "stacked"; SwitchToMode "Normal"; }} bind "x" {{ CloseFocus; SwitchToMode "Normal"; }} bind "f" {{ ToggleFocusFullscreen; SwitchToMode "Normal"; }} bind "z" {{ TogglePaneFrames; SwitchToMode "Normal"; }} @@ -663,6 +666,7 @@ keybinds clear-defaults=true {{ bind "n" {{ NewPane; SwitchToMode "Normal"; }} bind "d" {{ NewPane "Down"; SwitchToMode "Normal"; }} bind "r" {{ NewPane "Right"; SwitchToMode "Normal"; }} + bind "s" {{ NewPane "stacked"; SwitchToMode "Normal"; }} bind "x" {{ CloseFocus; SwitchToMode "Normal"; }} bind "f" {{ ToggleFocusFullscreen; SwitchToMode "Normal"; }} bind "z" {{ TogglePaneFrames; SwitchToMode "Normal"; }} @@ -865,6 +869,7 @@ keybinds clear-defaults=true {{ bind "n" {{ NewPane; SwitchToMode "Normal"; }} bind "d" {{ NewPane "Down"; SwitchToMode "Normal"; }} bind "r" {{ NewPane "Right"; SwitchToMode "Normal"; }} + bind "s" {{ NewPane "stacked"; SwitchToMode "Normal"; }} bind "x" {{ CloseFocus; SwitchToMode "Normal"; }} bind "f" {{ ToggleFocusFullscreen; SwitchToMode "Normal"; }} bind "z" {{ TogglePaneFrames; SwitchToMode "Normal"; }} @@ -1042,6 +1047,7 @@ keybinds clear-defaults=true {{ bind "n" {{ NewPane; SwitchToMode "Normal"; }} bind "d" {{ NewPane "Down"; SwitchToMode "Normal"; }} bind "r" {{ NewPane "Right"; SwitchToMode "Normal"; }} + bind "s" {{ NewPane "stacked"; SwitchToMode "Normal"; }} bind "x" {{ CloseFocus; SwitchToMode "Normal"; }} bind "f" {{ ToggleFocusFullscreen; SwitchToMode "Normal"; }} bind "z" {{ TogglePaneFrames; SwitchToMode "Normal"; }} diff --git a/default-plugins/status-bar/src/one_line_ui.rs b/default-plugins/status-bar/src/one_line_ui.rs index 23d3c133..1902ac63 100644 --- a/default-plugins/status-bar/src/one_line_ui.rs +++ b/default-plugins/status-bar/src/one_line_ui.rs @@ -1276,6 +1276,7 @@ fn get_keys_and_hints(mi: &ModeInfo) -> Vec<(String, String, Vec bool { let mut step_is_complete = false; - eprintln!("current_snapshot: {}", remote_terminal.current_snapshot()); if remote_terminal.cursor_position_is(53, 2) && remote_terminal.ctrl_plus_appears() { // size has been changed diff --git a/zellij-server/src/panes/tiled_panes/mod.rs b/zellij-server/src/panes/tiled_panes/mod.rs index fcaa8d25..5ccafab9 100644 --- a/zellij-server/src/panes/tiled_panes/mod.rs +++ b/zellij-server/src/panes/tiled_panes/mod.rs @@ -395,6 +395,72 @@ impl TiledPanes { }, } } + pub fn add_pane_to_stack_of_active_pane( + &mut self, + pane_id: PaneId, + mut pane: Box, + client_id: ClientId, + ) { + let mut pane_grid = TiledPaneGrid::new( + &mut self.panes, + &self.panes_to_hide, + *self.display_area.borrow(), + *self.viewport.borrow(), + ); + let Some(active_pane_id) = self.active_panes.get(&client_id) else { + log::error!("Could not find active pane id for client_id"); + return; + }; + let pane_id_is_stacked = pane_grid + .get_pane_geom(active_pane_id) + .map(|p| p.is_stacked()) + .unwrap_or(false); + if !pane_id_is_stacked { + let _ = pane_grid.make_pane_stacked(&active_pane_id); + } + match pane_grid.make_room_in_stack_of_pane_id_for_pane(active_pane_id) { + Ok(new_pane_geom) => { + pane.set_geom(new_pane_geom); + self.panes.insert(pane_id, pane); + self.set_force_render(); // TODO: why do we need this? + return; + }, + Err(e) => { + log::error!("Failed to add pane to stack: {}", e); + }, + } + } + pub fn add_pane_to_stack_of_pane_id( + &mut self, + pane_id: PaneId, + mut pane: Box, + root_pane_id: PaneId, + ) { + let mut pane_grid = TiledPaneGrid::new( + &mut self.panes, + &self.panes_to_hide, + *self.display_area.borrow(), + *self.viewport.borrow(), + ); + let pane_id_is_stacked = pane_grid + .get_pane_geom(&root_pane_id) + .map(|p| p.is_stacked()) + .unwrap_or(false); + if !pane_id_is_stacked { + let _ = pane_grid.make_pane_stacked(&root_pane_id); + } + match pane_grid.make_room_in_stack_of_pane_id_for_pane(&root_pane_id) { + Ok(new_pane_geom) => { + pane.set_geom(new_pane_geom); + self.panes.insert(pane_id, pane); + self.set_force_render(); // TODO: why do we need this? + return; + }, + Err(e) => { + log::error!("Failed to add pane to stack: {}", e); + }, + } + } pub fn fixed_pane_geoms(&self) -> Vec { self.panes .values() diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_background_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_background_plugin_command.snap index e8cb7daf..4df8fed1 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_background_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_background_plugin_command.snap @@ -1,7 +1,6 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 6878 -expression: "format!(\"{:#?}\",\n new_tab_event).replace(&format!(\"{:?}\", temp_folder.path()),\n \"\\\"CWD\\\"\")" +expression: "format!(\"{:#?}\",\nnew_tab_event).replace(&format!(\"{:?}\", temp_folder.path()), \"\\\"CWD\\\"\")" --- Some( SpawnTerminal( @@ -29,8 +28,7 @@ Some( ), ), None, - None, - None, + NoPreference, true, ClientId( 1, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_floating_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_floating_plugin_command.snap index a89e1b2f..f78d2f04 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_floating_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_floating_plugin_command.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 4557 expression: "format!(\"{:#?}\", new_tab_event)" --- Some( @@ -26,11 +25,10 @@ Some( }, ), ), - Some( - true, + None, + Floating( + None, ), - None, - None, false, ClientId( 1, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_plugin_command.snap index 048dc905..124456ca 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_plugin_command.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 4479 expression: "format!(\"{:#?}\", new_tab_event)" --- Some( @@ -26,11 +25,10 @@ Some( }, ), ), - Some( - false, + None, + Tiled( + None, ), - None, - None, false, ClientId( 1, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_floating_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_floating_plugin_command.snap index e4a14a40..82d7c861 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_floating_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_floating_plugin_command.snap @@ -1,7 +1,6 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 3996 -expression: "format!(\"{:#?}\",\n new_tab_event).replace(&format!(\"{:?}\", temp_folder.path()),\n \"\\\"CWD\\\"\")" +expression: "format!(\"{:#?}\",\nnew_tab_event).replace(&format!(\"{:?}\", temp_folder.path()), \"\\\"CWD\\\"\")" --- Some( SpawnTerminal( @@ -23,13 +22,12 @@ Some( }, ), ), - Some( - true, - ), Some( "Editing: /path/to/my/file.rs", ), - None, + Floating( + None, + ), false, ClientId( 1, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_plugin_command.snap index ab031be5..8ff9d6d0 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_plugin_command.snap @@ -1,7 +1,6 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 4078 -expression: "format!(\"{:#?}\",\n new_tab_event).replace(&format!(\"{:?}\", temp_folder.path()),\n \"\\\"CWD\\\"\")" +expression: "format!(\"{:#?}\",\nnew_tab_event).replace(&format!(\"{:?}\", temp_folder.path()), \"\\\"CWD\\\"\")" --- Some( SpawnTerminal( @@ -23,13 +22,12 @@ Some( }, ), ), - Some( - false, - ), Some( "Editing: /path/to/my/file.rs", ), - None, + Tiled( + None, + ), false, ClientId( 1, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_floating_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_floating_plugin_command.snap index 9d9747d8..1909e504 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_floating_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_floating_plugin_command.snap @@ -1,7 +1,6 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 4243 -expression: "format!(\"{:#?}\",\n new_tab_event).replace(&format!(\"{:?}\", temp_folder.path()),\n \"\\\"CWD\\\"\")" +expression: "format!(\"{:#?}\",\nnew_tab_event).replace(&format!(\"{:?}\", temp_folder.path()), \"\\\"CWD\\\"\")" --- Some( SpawnTerminal( @@ -25,13 +24,12 @@ Some( }, ), ), - Some( - true, - ), Some( "Editing: /path/to/my/file.rs", ), - None, + Floating( + None, + ), false, ClientId( 1, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_plugin_command.snap index aa3aa515..88597b2b 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_plugin_command.snap @@ -1,7 +1,6 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 4161 -expression: "format!(\"{:#?}\",\n new_tab_event).replace(&format!(\"{:?}\", temp_folder.path()),\n \"\\\"CWD\\\"\")" +expression: "format!(\"{:#?}\",\nnew_tab_event).replace(&format!(\"{:?}\", temp_folder.path()), \"\\\"CWD\\\"\")" --- Some( SpawnTerminal( @@ -25,13 +24,12 @@ Some( }, ), ), - Some( - false, - ), Some( "Editing: /path/to/my/file.rs", ), - None, + Tiled( + None, + ), false, ClientId( 1, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_floating_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_floating_plugin_command.snap index e61ebbdb..5fc39f2d 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_floating_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_floating_plugin_command.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 4401 expression: "format!(\"{:#?}\", new_tab_event)" --- Some( @@ -19,11 +18,10 @@ Some( }, ), ), - Some( - true, + None, + Floating( + None, ), - None, - None, false, ClientId( 1, diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_plugin_command.snap index 1df64a8f..8ba221a2 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_plugin_command.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 4323 expression: "format!(\"{:#?}\", new_tab_event)" --- Some( @@ -19,11 +18,10 @@ Some( }, ), ), - Some( - false, + None, + Tiled( + None, ), - None, - None, false, ClientId( 1, diff --git a/zellij-server/src/plugins/zellij_exports.rs b/zellij-server/src/plugins/zellij_exports.rs index 7b682f6d..ed43f091 100644 --- a/zellij-server/src/plugins/zellij_exports.rs +++ b/zellij-server/src/plugins/zellij_exports.rs @@ -2,7 +2,7 @@ use super::PluginInstruction; use crate::background_jobs::BackgroundJob; use crate::plugins::plugin_map::PluginEnv; use crate::plugins::wasm_bridge::handle_plugin_crash; -use crate::pty::{ClientTabIndexOrPaneId, PtyInstruction}; +use crate::pty::{ClientTabIndexOrPaneId, NewPanePlacement, PtyInstruction}; use crate::route::route_action; use crate::ServerInstruction; use async_std::task; @@ -744,14 +744,12 @@ fn open_file_near_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, + NewPanePlacement::default(), start_suppressed, ClientTabIndexOrPaneId::PaneId(PaneId::Plugin(env.plugin_id)), ); @@ -774,14 +772,12 @@ fn open_file_floating_near_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, + NewPanePlacement::Floating(floating_pane_coordinates), start_suppressed, ClientTabIndexOrPaneId::PaneId(PaneId::Plugin(env.plugin_id)), ); @@ -834,7 +830,6 @@ fn open_terminal(env: &PluginEnv, cwd: PathBuf) { 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(), @@ -845,9 +840,8 @@ fn open_terminal_near_plugin(env: &PluginEnv, cwd: PathBuf) { default_shell.change_cwd(cwd); let _ = env.senders.send_to_pty(PtyInstruction::SpawnTerminal( Some(default_shell), - Some(should_float), name, - None, + NewPanePlacement::Tiled(None), false, ClientTabIndexOrPaneId::PaneId(PaneId::Plugin(env.plugin_id)), )); @@ -881,7 +875,6 @@ fn open_terminal_floating_near_plugin( 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(), @@ -892,9 +885,8 @@ fn open_terminal_floating_near_plugin( let name = None; let _ = env.senders.send_to_pty(PtyInstruction::SpawnTerminal( Some(default_shell), - Some(should_float), name, - floating_pane_coordinates, + NewPanePlacement::Floating(floating_pane_coordinates), false, ClientTabIndexOrPaneId::PaneId(PaneId::Plugin(env.plugin_id)), )); @@ -1021,7 +1013,6 @@ fn open_command_pane_near_plugin( let hold_on_close = true; let hold_on_start = false; let name = None; - let should_float = false; let run_command_action = RunCommandAction { command, args, @@ -1038,9 +1029,8 @@ fn open_command_pane_near_plugin( 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, + NewPanePlacement::Tiled(None), false, ClientTabIndexOrPaneId::PaneId(PaneId::Plugin(env.plugin_id)), )); @@ -1090,7 +1080,6 @@ fn open_command_pane_floating_near_plugin( let hold_on_close = true; let hold_on_start = false; let name = None; - let should_float = true; let run_command_action = RunCommandAction { command, args, @@ -1107,9 +1096,8 @@ fn open_command_pane_floating_near_plugin( 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, + NewPanePlacement::Floating(floating_pane_coordinates), false, ClientTabIndexOrPaneId::PaneId(PaneId::Plugin(env.plugin_id)), )); @@ -1177,9 +1165,8 @@ fn open_command_pane_background( let run_cmd = TerminalAction::RunCommand(run_command_action.into()); let _ = env.senders.send_to_pty(PtyInstruction::SpawnTerminal( Some(run_cmd), - None, name, - None, + NewPanePlacement::default(), start_suppressed, ClientTabIndexOrPaneId::ClientId(env.client_id), )); diff --git a/zellij-server/src/pty.rs b/zellij-server/src/pty.rs index 39ac2d72..d9d2fb77 100644 --- a/zellij-server/src/pty.rs +++ b/zellij-server/src/pty.rs @@ -16,7 +16,7 @@ use nix::unistd::Pid; use std::sync::Arc; use std::{collections::HashMap, os::unix::io::RawFd, path::PathBuf}; use zellij_utils::{ - data::{Event, FloatingPaneCoordinates, OriginatingPlugin}, + data::{Direction, Event, FloatingPaneCoordinates, OriginatingPlugin}, errors::prelude::*, errors::{ContextType, PtyContext}, input::{ @@ -37,26 +37,95 @@ pub enum ClientTabIndexOrPaneId { PaneId(PaneId), } +// TODO: move elsewhere +#[derive(Clone, Debug)] +pub enum NewPanePlacement { + NoPreference, + Tiled(Option), + Floating(Option), + InPlace { + pane_id_to_replace: Option, + close_replaced_pane: bool, + }, + Stacked(Option), +} + +impl Default for NewPanePlacement { + fn default() -> Self { + NewPanePlacement::NoPreference + } +} + +impl NewPanePlacement { + pub fn with_floating_pane_coordinates( + floating_pane_coordinates: Option, + ) -> Self { + NewPanePlacement::Floating(floating_pane_coordinates) + } + pub fn with_should_be_in_place( + self, + should_be_in_place: bool, + close_replaced_pane: bool, + ) -> Self { + if should_be_in_place { + NewPanePlacement::InPlace { + pane_id_to_replace: None, + close_replaced_pane, + } + } else { + self + } + } + pub fn with_pane_id_to_replace( + pane_id_to_replace: Option, + close_replaced_pane: bool, + ) -> Self { + NewPanePlacement::InPlace { + pane_id_to_replace, + close_replaced_pane, + } + } + pub fn should_float(&self) -> Option { + match self { + NewPanePlacement::Floating(_) => Some(true), + NewPanePlacement::Tiled(_) => Some(false), + _ => None, + } + } + pub fn floating_pane_coordinates(&self) -> Option { + match self { + NewPanePlacement::Floating(floating_pane_coordinates) => { + floating_pane_coordinates.clone() + }, + _ => None, + } + } + pub fn should_stack(&self) -> bool { + match self { + NewPanePlacement::Stacked(_) => true, + _ => false, + } + } + pub fn id_of_stack_root(&self) -> Option { + match self { + NewPanePlacement::Stacked(id) => *id, + _ => None, + } + } +} + /// Instructions related to PTYs (pseudoterminals). #[derive(Clone, Debug)] pub enum PtyInstruction { SpawnTerminal( Option, - Option, Option, - Option, + NewPanePlacement, bool, // start suppressed ClientTabIndexOrPaneId, ), // bool (if Some) is // should_float, String is an optional pane name OpenInPlaceEditor(PathBuf, Option, ClientTabIndexOrPaneId), // Option is the optional line number - SpawnTerminalVertically(Option, Option, ClientId), // String is an - // optional pane - // name - // bool is start_suppressed - SpawnTerminalHorizontally(Option, Option, ClientId), // String is an - // optional pane - // name UpdateActivePane(Option, ClientId), GoToTab(TabIndex, ClientId), NewTab( @@ -114,8 +183,6 @@ impl From<&PtyInstruction> for PtyContext { match *pty_instruction { PtyInstruction::SpawnTerminal(..) => PtyContext::SpawnTerminal, PtyInstruction::OpenInPlaceEditor(..) => PtyContext::OpenInPlaceEditor, - PtyInstruction::SpawnTerminalVertically(..) => PtyContext::SpawnTerminalVertically, - PtyInstruction::SpawnTerminalHorizontally(..) => PtyContext::SpawnTerminalHorizontally, PtyInstruction::UpdateActivePane(..) => PtyContext::UpdateActivePane, PtyInstruction::GoToTab(..) => PtyContext::GoToTab, PtyInstruction::ClosePane(_) => PtyContext::ClosePane, @@ -153,9 +220,8 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box) -> Result<()> { match event { PtyInstruction::SpawnTerminal( terminal_action, - should_float, name, - floating_pane_coordinates, + new_pane_placement, start_suppressed, client_or_tab_index, ) => { @@ -235,10 +301,9 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box) -> Result<()> { .send_to_screen(ScreenInstruction::NewPane( PaneId::Terminal(pid), pane_title, - should_float, hold_for_command, invoked_with, - floating_pane_coordinates, + new_pane_placement, start_suppressed, client_or_tab_index, )) @@ -253,10 +318,9 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box) -> Result<()> { .send_to_screen(ScreenInstruction::NewPane( PaneId::Terminal(*terminal_id), pane_title, - should_float, hold_for_command, invoked_with, - floating_pane_coordinates, + new_pane_placement, start_suppressed, client_or_tab_index, )) @@ -390,144 +454,6 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box) -> Result<()> { }, } }, - PtyInstruction::SpawnTerminalVertically(terminal_action, name, client_id) => { - let err_context = - || format!("failed to spawn terminal vertically for client {client_id}"); - - let (hold_on_close, run_command, pane_title) = match &terminal_action { - Some(TerminalAction::RunCommand(run_command)) => ( - run_command.hold_on_close, - Some(run_command.clone()), - Some(name.unwrap_or_else(|| run_command.to_string())), - ), - _ => (false, None, name), - }; - match pty - .spawn_terminal(terminal_action, ClientTabIndexOrPaneId::ClientId(client_id)) - .with_context(err_context) - { - Ok((pid, starts_held)) => { - let hold_for_command = if starts_held { run_command } else { None }; - pty.bus - .senders - .send_to_screen(ScreenInstruction::VerticalSplit( - PaneId::Terminal(pid), - pane_title, - hold_for_command, - client_id, - )) - .with_context(err_context)?; - }, - Err(err) => match err.downcast_ref::() { - Some(ZellijError::CommandNotFound { terminal_id, .. }) => { - let hold_for_command = None; // we do not hold an "error" pane - if hold_on_close { - pty.bus - .senders - .send_to_screen(ScreenInstruction::VerticalSplit( - PaneId::Terminal(*terminal_id), - pane_title, - hold_for_command, - client_id, - )) - .with_context(err_context)?; - if let Some(run_command) = run_command { - pty.bus - .senders - .send_to_screen(ScreenInstruction::PtyBytes( - *terminal_id, - format!( - "Command not found: {}", - run_command.command.display() - ) - .as_bytes() - .to_vec(), - )) - .with_context(err_context)?; - pty.bus - .senders - .send_to_screen(ScreenInstruction::HoldPane( - PaneId::Terminal(*terminal_id), - Some(2), // exit status - run_command, - )) - .with_context(err_context)?; - } - } - }, - _ => Err::<(), _>(err).non_fatal(), - }, - } - }, - PtyInstruction::SpawnTerminalHorizontally(terminal_action, name, client_id) => { - let err_context = - || format!("failed to spawn terminal horizontally for client {client_id}"); - - let (hold_on_close, run_command, pane_title) = match &terminal_action { - Some(TerminalAction::RunCommand(run_command)) => ( - run_command.hold_on_close, - Some(run_command.clone()), - Some(name.unwrap_or_else(|| run_command.to_string())), - ), - _ => (false, None, name), - }; - match pty - .spawn_terminal(terminal_action, ClientTabIndexOrPaneId::ClientId(client_id)) - .with_context(err_context) - { - Ok((pid, starts_held)) => { - let hold_for_command = if starts_held { run_command } else { None }; - pty.bus - .senders - .send_to_screen(ScreenInstruction::HorizontalSplit( - PaneId::Terminal(pid), - pane_title, - hold_for_command, - client_id, - )) - .with_context(err_context)?; - }, - Err(err) => match err.downcast_ref::() { - Some(ZellijError::CommandNotFound { terminal_id, .. }) => { - if hold_on_close { - let hold_for_command = None; // we do not hold an "error" pane - pty.bus - .senders - .send_to_screen(ScreenInstruction::HorizontalSplit( - PaneId::Terminal(*terminal_id), - pane_title, - hold_for_command, - client_id, - )) - .with_context(err_context)?; - if let Some(run_command) = run_command { - pty.bus - .senders - .send_to_screen(ScreenInstruction::PtyBytes( - *terminal_id, - format!( - "Command not found: {}", - run_command.command.display() - ) - .as_bytes() - .to_vec(), - )) - .with_context(err_context)?; - pty.bus - .senders - .send_to_screen(ScreenInstruction::HoldPane( - PaneId::Terminal(*terminal_id), - Some(2), // exit status - run_command, - )) - .with_context(err_context)?; - } - } - }, - _ => Err::<(), _>(err).non_fatal(), - }, - } - }, PtyInstruction::UpdateActivePane(pane_id, client_id) => { pty.set_active_pane(pane_id, client_id); }, diff --git a/zellij-server/src/route.rs b/zellij-server/src/route.rs index cb67c336..678c1558 100644 --- a/zellij-server/src/route.rs +++ b/zellij-server/src/route.rs @@ -6,7 +6,7 @@ use crate::{ os_input_output::ServerOsApi, panes::PaneId, plugins::PluginInstruction, - pty::{ClientTabIndexOrPaneId, PtyInstruction}, + pty::{ClientTabIndexOrPaneId, NewPanePlacement, PtyInstruction}, screen::ScreenInstruction, ServerInstruction, SessionMetaData, SessionState, }; @@ -257,30 +257,13 @@ pub(crate) fn route_action( }, Action::NewPane(direction, name, start_suppressed) => { let shell = default_shell.clone(); - let pty_instr = match direction { - Some(Direction::Left) => { - PtyInstruction::SpawnTerminalVertically(shell, name, client_id) - }, - Some(Direction::Right) => { - PtyInstruction::SpawnTerminalVertically(shell, name, client_id) - }, - Some(Direction::Up) => { - PtyInstruction::SpawnTerminalHorizontally(shell, name, client_id) - }, - Some(Direction::Down) => { - PtyInstruction::SpawnTerminalHorizontally(shell, name, client_id) - }, - // No direction specified - try to put it in the biggest available spot - None => PtyInstruction::SpawnTerminal( - shell, - None, - name, - None, - start_suppressed, - ClientTabIndexOrPaneId::ClientId(client_id), - ), - }; - senders.send_to_pty(pty_instr).with_context(err_context)?; + senders.send_to_pty(PtyInstruction::SpawnTerminal( + shell, + name, + NewPanePlacement::Tiled(direction), + start_suppressed, + ClientTabIndexOrPaneId::ClientId(client_id), + )); }, Action::EditFile( open_file_payload, @@ -292,25 +275,8 @@ pub(crate) fn route_action( ) => { let title = format!("Editing: {}", open_file_payload.path.display()); let open_file = TerminalAction::OpenFile(open_file_payload); - let pty_instr = match (split_direction, should_float, should_open_in_place) { - (Some(Direction::Left), false, false) => { - PtyInstruction::SpawnTerminalVertically(Some(open_file), Some(title), client_id) - }, - (Some(Direction::Right), false, false) => { - PtyInstruction::SpawnTerminalVertically(Some(open_file), Some(title), client_id) - }, - (Some(Direction::Up), false, false) => PtyInstruction::SpawnTerminalHorizontally( - Some(open_file), - Some(title), - client_id, - ), - (Some(Direction::Down), false, false) => PtyInstruction::SpawnTerminalHorizontally( - Some(open_file), - Some(title), - client_id, - ), - // open terminal in place - (_, _, true) => match pane_id { + let pty_instr = if should_open_in_place { + match pane_id { Some(pane_id) => PtyInstruction::SpawnInPlaceTerminal( Some(open_file), Some(title), @@ -323,17 +289,19 @@ pub(crate) fn route_action( false, ClientTabIndexOrPaneId::ClientId(client_id), ), - }, - // Open either floating terminal if we were asked with should_float or defer - // placement to screen - (None, _, _) | (_, true, _) => PtyInstruction::SpawnTerminal( + } + } else { + PtyInstruction::SpawnTerminal( Some(open_file), - Some(should_float), Some(title), - floating_pane_coordinates, + if should_float { + NewPanePlacement::Floating(floating_pane_coordinates) + } else { + NewPanePlacement::Tiled(split_direction) + }, start_suppressed, ClientTabIndexOrPaneId::ClientId(client_id), - ), + ) }; senders.send_to_pty(pty_instr).with_context(err_context)?; }, @@ -368,16 +336,14 @@ pub(crate) fn route_action( .with_context(err_context)?; }, Action::NewFloatingPane(run_command, name, floating_pane_coordinates) => { - let should_float = true; let run_cmd = run_command .map(|cmd| TerminalAction::RunCommand(cmd.into())) .or_else(|| default_shell.clone()); senders .send_to_pty(PtyInstruction::SpawnTerminal( run_cmd, - Some(should_float), name, - floating_pane_coordinates, + NewPanePlacement::Floating(floating_pane_coordinates), false, ClientTabIndexOrPaneId::ClientId(client_id), )) @@ -410,35 +376,46 @@ pub(crate) fn route_action( }, } }, - Action::NewTiledPane(direction, run_command, name) => { - let should_float = false; + Action::NewStackedPane(run_command, name) => { let run_cmd = run_command .map(|cmd| TerminalAction::RunCommand(cmd.into())) .or_else(|| default_shell.clone()); - let pty_instr = match direction { - Some(Direction::Left) => { - PtyInstruction::SpawnTerminalVertically(run_cmd, name, client_id) + match pane_id { + Some(pane_id) => { + senders + .send_to_pty(PtyInstruction::SpawnTerminal( + run_cmd, + name, + NewPanePlacement::Stacked(Some(pane_id)), + false, + ClientTabIndexOrPaneId::PaneId(pane_id), + )) + .with_context(err_context)?; }, - Some(Direction::Right) => { - PtyInstruction::SpawnTerminalVertically(run_cmd, name, client_id) + None => { + senders + .send_to_pty(PtyInstruction::SpawnTerminal( + run_cmd, + name, + NewPanePlacement::Stacked(None), + false, + ClientTabIndexOrPaneId::ClientId(client_id), + )) + .with_context(err_context)?; }, - Some(Direction::Up) => { - PtyInstruction::SpawnTerminalHorizontally(run_cmd, name, client_id) - }, - Some(Direction::Down) => { - PtyInstruction::SpawnTerminalHorizontally(run_cmd, name, client_id) - }, - // No direction specified - try to put it in the biggest available spot - None => PtyInstruction::SpawnTerminal( - run_cmd, - Some(should_float), - name, - None, - false, - ClientTabIndexOrPaneId::ClientId(client_id), - ), - }; - senders.send_to_pty(pty_instr).with_context(err_context)?; + } + }, + Action::NewTiledPane(direction, run_command, name) => { + let run_cmd = run_command + .map(|cmd| TerminalAction::RunCommand(cmd.into())) + .or_else(|| default_shell.clone()); + let _ = senders.send_to_pty(PtyInstruction::SpawnTerminal( + run_cmd, + name, + NewPanePlacement::Tiled(direction), + false, + ClientTabIndexOrPaneId::ClientId(client_id), + )); }, Action::TogglePaneEmbedOrFloating => { senders @@ -465,30 +442,13 @@ pub(crate) fn route_action( }, Action::Run(command) => { let run_cmd = Some(TerminalAction::RunCommand(command.clone().into())); - let pty_instr = match command.direction { - Some(Direction::Left) => { - PtyInstruction::SpawnTerminalVertically(run_cmd, None, client_id) - }, - Some(Direction::Right) => { - PtyInstruction::SpawnTerminalVertically(run_cmd, None, client_id) - }, - Some(Direction::Up) => { - PtyInstruction::SpawnTerminalHorizontally(run_cmd, None, client_id) - }, - Some(Direction::Down) => { - PtyInstruction::SpawnTerminalHorizontally(run_cmd, None, client_id) - }, - // No direction specified - try to put it in the biggest available spot - None => PtyInstruction::SpawnTerminal( - run_cmd, - None, - None, - None, - false, - ClientTabIndexOrPaneId::ClientId(client_id), - ), - }; - senders.send_to_pty(pty_instr).with_context(err_context)?; + let _ = senders.send_to_pty(PtyInstruction::SpawnTerminal( + run_cmd, + None, + NewPanePlacement::Tiled(command.direction), + false, + ClientTabIndexOrPaneId::ClientId(client_id), + )); }, Action::CloseFocus => { senders diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs index 376c726e..0c073aed 100644 --- a/zellij-server/src/screen.rs +++ b/zellij-server/src/screen.rs @@ -43,7 +43,7 @@ use crate::{ panes::sixel::SixelImageStore, panes::PaneId, plugins::{PluginId, PluginInstruction, PluginRenderAsset}, - pty::{get_default_shell, ClientTabIndexOrPaneId, PtyInstruction, VteBytes}, + pty::{get_default_shell, ClientTabIndexOrPaneId, NewPanePlacement, PtyInstruction, VteBytes}, tab::{SuppressedPanes, Tab}, thread_bus::Bus, ui::{ @@ -138,7 +138,6 @@ macro_rules! active_tab_and_connected_client_id { } type InitialTitle = String; -type ShouldFloat = bool; type HoldForCommand = Option; /// Instructions that can be sent to the [`Screen`]. @@ -151,10 +150,9 @@ pub enum ScreenInstruction { NewPane( PaneId, Option, - Option, HoldForCommand, Option, // invoked with - Option, + NewPanePlacement, bool, // start suppressed ClientTabIndexOrPaneId, ), @@ -3335,10 +3333,9 @@ pub(crate) fn screen_thread_main( ScreenInstruction::NewPane( pid, initial_pane_title, - should_float, hold_for_command, invoked_with, - floating_pane_coordinates, + new_pane_placement, start_suppressed, client_or_tab_index, ) => { @@ -3347,11 +3344,10 @@ pub(crate) fn screen_thread_main( active_tab_and_connected_client_id!(screen, client_id, |tab: &mut Tab, client_id: ClientId| { tab.new_pane(pid, initial_pane_title, - should_float, invoked_with, - floating_pane_coordinates, start_suppressed, true, + new_pane_placement, Some(client_id) ) }, ?); @@ -3374,11 +3370,10 @@ pub(crate) fn screen_thread_main( active_tab.new_pane( pid, initial_pane_title, - should_float, invoked_with, - floating_pane_coordinates, start_suppressed, true, + new_pane_placement, None, )?; if let Some(hold_for_command) = hold_for_command { @@ -3397,11 +3392,10 @@ pub(crate) fn screen_thread_main( tab.new_pane( pid, initial_pane_title, - should_float, invoked_with, - floating_pane_coordinates, start_suppressed, true, + new_pane_placement, None, )?; if let Some(hold_for_command) = hold_for_command { @@ -4659,9 +4653,28 @@ pub(crate) fn screen_thread_main( should_focus_plugin, client_id, ) => { + let close_replaced_pane = false; // TODO: support this + let mut new_pane_placement = NewPanePlacement::default(); + let maybe_should_float = should_float; + let should_be_tiled = maybe_should_float.map(|f| !f).unwrap_or(false); + let should_float = maybe_should_float.unwrap_or(false); + if floating_pane_coordinates.is_some() || should_float { + new_pane_placement = NewPanePlacement::with_floating_pane_coordinates( + floating_pane_coordinates.clone(), + ); + } + if should_be_tiled { + new_pane_placement = NewPanePlacement::Tiled(None); + } + if should_be_in_place { + new_pane_placement = NewPanePlacement::with_pane_id_to_replace( + pane_id_to_replace, + close_replaced_pane, + ); + } if screen.active_tab_indices.is_empty() && tab_index.is_none() { pending_events_waiting_for_client.push(ScreenInstruction::AddPlugin( - should_float, + maybe_should_float, should_be_in_place, run_plugin_or_alias, pane_title, @@ -4718,11 +4731,10 @@ pub(crate) fn screen_thread_main( active_tab.new_pane( PaneId::Plugin(plugin_id), Some(pane_title), - should_float, Some(run_plugin), - floating_pane_coordinates, start_suppressed, should_focus_plugin.unwrap_or(true), + new_pane_placement, Some(client_id), ) }, ?); @@ -4732,11 +4744,10 @@ pub(crate) fn screen_thread_main( active_tab.new_pane( PaneId::Plugin(plugin_id), Some(pane_title), - should_float, Some(run_plugin), - None, start_suppressed, should_focus_plugin.unwrap_or(true), + new_pane_placement, None, )?; } else { diff --git a/zellij-server/src/tab/mod.rs b/zellij-server/src/tab/mod.rs index 683a3d4a..20e87f9d 100644 --- a/zellij-server/src/tab/mod.rs +++ b/zellij-server/src/tab/mod.rs @@ -39,7 +39,7 @@ use crate::{ panes::{FloatingPanes, TiledPanes}, panes::{LinkHandler, PaneId, PluginPane, TerminalPane}, plugins::PluginInstruction, - pty::{ClientTabIndexOrPaneId, PtyInstruction, VteBytes}, + pty::{ClientTabIndexOrPaneId, NewPanePlacement, PtyInstruction, VteBytes}, thread_bus::ThreadSenders, ClientId, ServerInstruction, }; @@ -1238,7 +1238,6 @@ impl Tab { }, None => { let name = None; - let should_float = true; let client_id_or_tab_index = match client_id { Some(client_id) => ClientTabIndexOrPaneId::ClientId(client_id), None => ClientTabIndexOrPaneId::TabIndex(self.index), @@ -1246,9 +1245,8 @@ impl Tab { let should_start_suppressed = false; let instruction = PtyInstruction::SpawnTerminal( default_shell, - Some(should_float), name, - None, + NewPanePlacement::Floating(None), should_start_suppressed, client_id_or_tab_index, ); @@ -1266,21 +1264,81 @@ impl Tab { &mut self, pid: PaneId, initial_pane_title: Option, - should_float: Option, invoked_with: Option, - floating_pane_coordinates: Option, + start_suppressed: bool, + should_focus_pane: bool, + new_pane_placement: NewPanePlacement, + client_id: Option, + ) -> Result<()> { + match new_pane_placement { + NewPanePlacement::NoPreference => self.new_no_preference_pane( + pid, + initial_pane_title, + invoked_with, + start_suppressed, + should_focus_pane, + client_id, + ), + NewPanePlacement::Tiled(None) => self.new_tiled_pane( + pid, + initial_pane_title, + invoked_with, + start_suppressed, + should_focus_pane, + client_id, + ), + NewPanePlacement::Tiled(Some(direction)) => { + if let Some(client_id) = client_id { + if direction == Direction::Left || direction == Direction::Right { + self.vertical_split(pid, initial_pane_title, client_id)?; + } else { + self.horizontal_split(pid, initial_pane_title, client_id)?; + } + } + Ok(()) + }, + NewPanePlacement::Floating(floating_pane_coordinates) => self.new_floating_pane( + pid, + initial_pane_title, + invoked_with, + start_suppressed, + should_focus_pane, + floating_pane_coordinates, + ), + NewPanePlacement::InPlace { + pane_id_to_replace, + close_replaced_pane, + } => self.new_in_place_pane( + pid, + initial_pane_title, + invoked_with, + start_suppressed, + should_focus_pane, + pane_id_to_replace, + close_replaced_pane, + client_id, + ), + NewPanePlacement::Stacked(pane_id_to_stack_under) => self.new_stacked_pane( + pid, + initial_pane_title, + invoked_with, + start_suppressed, + should_focus_pane, + pane_id_to_stack_under, + client_id, + ), + } + } + pub fn new_no_preference_pane( + &mut self, + pid: PaneId, + initial_pane_title: Option, + invoked_with: Option, start_suppressed: bool, should_focus_pane: bool, client_id: Option, ) -> Result<()> { let err_context = || format!("failed to create new pane with id {pid:?}"); - if should_focus_pane { - match should_float { - Some(true) => self.show_floating_panes(), - Some(false) => self.hide_floating_panes(), - None => {}, - }; - } self.close_down_to_max_terminals() .with_context(err_context)?; let mut new_pane = match pid { @@ -1357,23 +1415,340 @@ impl Tab { Ok(()) } else if should_focus_pane { if self.floating_panes.panes_are_visible() { - self.add_floating_pane(new_pane, pid, floating_pane_coordinates, true) + self.add_floating_pane(new_pane, pid, None, true) } else { self.add_tiled_pane(new_pane, pid, client_id) } } else { - match should_float { - Some(true) => { - self.add_floating_pane(new_pane, pid, floating_pane_coordinates, false) + if self.floating_panes.panes_are_visible() { + self.add_floating_pane(new_pane, pid, None, false) + } else { + self.add_tiled_pane(new_pane, pid, client_id) + } + } + } + pub fn new_tiled_pane( + &mut self, + pid: PaneId, + initial_pane_title: Option, + invoked_with: Option, + start_suppressed: bool, + should_focus_pane: bool, + client_id: Option, + ) -> Result<()> { + let err_context = || format!("failed to create new pane with id {pid:?}"); + if should_focus_pane { + self.hide_floating_panes(); + } + self.close_down_to_max_terminals() + .with_context(err_context)?; + let mut new_pane = match pid { + PaneId::Terminal(term_pid) => { + let next_terminal_position = self.get_next_terminal_position(); + Box::new(TerminalPane::new( + term_pid, + PaneGeom::default(), // this will be filled out later + self.style, + next_terminal_position, + String::new(), + self.link_handler.clone(), + self.character_cell_size.clone(), + self.sixel_image_store.clone(), + self.terminal_emulator_colors.clone(), + self.terminal_emulator_color_codes.clone(), + initial_pane_title, + invoked_with, + self.debug, + self.arrow_fonts, + self.styled_underlines, + self.explicitly_disable_kitty_keyboard_protocol, + )) as Box + }, + PaneId::Plugin(plugin_pid) => { + Box::new(PluginPane::new( + plugin_pid, + PaneGeom::default(), // this will be filled out later + self.senders + .to_plugin + .as_ref() + .with_context(err_context)? + .clone(), + initial_pane_title.unwrap_or("".to_owned()), + String::new(), + self.sixel_image_store.clone(), + self.terminal_emulator_colors.clone(), + self.terminal_emulator_color_codes.clone(), + self.link_handler.clone(), + self.character_cell_size.clone(), + self.connected_clients.borrow().iter().copied().collect(), + self.style, + invoked_with, + self.debug, + self.arrow_fonts, + self.styled_underlines, + )) as Box + }, + }; + + if start_suppressed { + // this pane needs to start in the background (suppressed), only accessible if a plugin takes it out + // of there in one way or another + // we need to do some bookkeeping for this pane, namely setting its geom and + // content_offset so that things will appear properly in the terminal - we set it to + // the default geom of the first floating pane - this is just in order to give it some + // reasonable size, when it is shown - if needed - it will be given the proper geom as if it were + // resized + let viewport = { self.viewport.borrow().clone() }; + let new_pane_geom = half_size_middle_geom(&viewport, 0); + new_pane.set_active_at(Instant::now()); + new_pane.set_geom(new_pane_geom); + new_pane.set_content_offset(Offset::frame(1)); + resize_pty!( + new_pane, + self.os_api, + self.senders, + self.character_cell_size + ) + .with_context(err_context)?; + let is_scrollback_editor = false; + self.suppressed_panes + .insert(pid, (is_scrollback_editor, new_pane)); + Ok(()) + } else { + self.add_tiled_pane(new_pane, pid, client_id) + } + } + pub fn new_floating_pane( + &mut self, + pid: PaneId, + initial_pane_title: Option, + invoked_with: Option, + start_suppressed: bool, + should_focus_pane: bool, + floating_pane_coordinates: Option, + ) -> Result<()> { + let err_context = || format!("failed to create new pane with id {pid:?}"); + if should_focus_pane { + self.show_floating_panes(); + } + self.close_down_to_max_terminals() + .with_context(err_context)?; + let mut new_pane = match pid { + PaneId::Terminal(term_pid) => { + let next_terminal_position = self.get_next_terminal_position(); + Box::new(TerminalPane::new( + term_pid, + PaneGeom::default(), // this will be filled out later + self.style, + next_terminal_position, + String::new(), + self.link_handler.clone(), + self.character_cell_size.clone(), + self.sixel_image_store.clone(), + self.terminal_emulator_colors.clone(), + self.terminal_emulator_color_codes.clone(), + initial_pane_title, + invoked_with, + self.debug, + self.arrow_fonts, + self.styled_underlines, + self.explicitly_disable_kitty_keyboard_protocol, + )) as Box + }, + PaneId::Plugin(plugin_pid) => { + Box::new(PluginPane::new( + plugin_pid, + PaneGeom::default(), // this will be filled out later + self.senders + .to_plugin + .as_ref() + .with_context(err_context)? + .clone(), + initial_pane_title.unwrap_or("".to_owned()), + String::new(), + self.sixel_image_store.clone(), + self.terminal_emulator_colors.clone(), + self.terminal_emulator_color_codes.clone(), + self.link_handler.clone(), + self.character_cell_size.clone(), + self.connected_clients.borrow().iter().copied().collect(), + self.style, + invoked_with, + self.debug, + self.arrow_fonts, + self.styled_underlines, + )) as Box + }, + }; + + if start_suppressed { + // this pane needs to start in the background (suppressed), only accessible if a plugin takes it out + // of there in one way or another + // we need to do some bookkeeping for this pane, namely setting its geom and + // content_offset so that things will appear properly in the terminal - we set it to + // the default geom of the first floating pane - this is just in order to give it some + // reasonable size, when it is shown - if needed - it will be given the proper geom as if it were + // resized + let viewport = { self.viewport.borrow().clone() }; + let new_pane_geom = half_size_middle_geom(&viewport, 0); + new_pane.set_active_at(Instant::now()); + new_pane.set_geom(new_pane_geom); + new_pane.set_content_offset(Offset::frame(1)); + resize_pty!( + new_pane, + self.os_api, + self.senders, + self.character_cell_size + ) + .with_context(err_context)?; + let is_scrollback_editor = false; + self.suppressed_panes + .insert(pid, (is_scrollback_editor, new_pane)); + Ok(()) + } else { + self.add_floating_pane(new_pane, pid, floating_pane_coordinates, should_focus_pane) + } + } + pub fn new_in_place_pane( + &mut self, + pid: PaneId, + initial_pane_title: Option, + invoked_with: Option, + start_suppressed: bool, + should_focus_pane: bool, + pane_id_to_replace: Option, + close_replaced_pane: bool, + client_id: Option, + ) -> Result<()> { + match (pane_id_to_replace, client_id) { + (Some(pane_id_to_replace), _) => { + self.suppress_pane_and_replace_with_pid( + pane_id_to_replace, + pid, + close_replaced_pane, + invoked_with, + )?; + }, + (None, Some(client_id)) => match self.get_active_pane_id(client_id) { + Some(active_pane_id) => { + self.suppress_pane_and_replace_with_pid( + active_pane_id, + pid, + close_replaced_pane, + invoked_with, + )?; }, - Some(false) => self.add_tiled_pane(new_pane, pid, client_id), None => { - if self.floating_panes.panes_are_visible() { - self.add_floating_pane(new_pane, pid, floating_pane_coordinates, false) - } else { - self.add_tiled_pane(new_pane, pid, client_id) - } + log::error!("Cannot find active pane"); }, + }, + _ => { + log::error!("Must have pane id to replace or client id to start pane in place>"); + }, + } + if let Some(initial_pane_title) = initial_pane_title { + let _ = self.rename_pane(initial_pane_title.as_bytes().to_vec(), pid); + } + Ok(()) + } + pub fn new_stacked_pane( + &mut self, + pid: PaneId, + initial_pane_title: Option, + invoked_with: Option, + start_suppressed: bool, + should_focus_pane: bool, + pane_id_to_stack_under: Option, + client_id: Option, + ) -> Result<()> { + let err_context = || format!("failed to create new pane with id {pid:?}"); + if should_focus_pane { + self.hide_floating_panes(); + } + self.close_down_to_max_terminals() + .with_context(err_context)?; + let mut new_pane = match pid { + PaneId::Terminal(term_pid) => { + let next_terminal_position = self.get_next_terminal_position(); + Box::new(TerminalPane::new( + term_pid, + PaneGeom::default(), // this will be filled out later + self.style, + next_terminal_position, + String::new(), + self.link_handler.clone(), + self.character_cell_size.clone(), + self.sixel_image_store.clone(), + self.terminal_emulator_colors.clone(), + self.terminal_emulator_color_codes.clone(), + initial_pane_title, + invoked_with, + self.debug, + self.arrow_fonts, + self.styled_underlines, + self.explicitly_disable_kitty_keyboard_protocol, + )) as Box + }, + PaneId::Plugin(plugin_pid) => { + Box::new(PluginPane::new( + plugin_pid, + PaneGeom::default(), // this will be filled out later + self.senders + .to_plugin + .as_ref() + .with_context(err_context)? + .clone(), + initial_pane_title.unwrap_or("".to_owned()), + String::new(), + self.sixel_image_store.clone(), + self.terminal_emulator_colors.clone(), + self.terminal_emulator_color_codes.clone(), + self.link_handler.clone(), + self.character_cell_size.clone(), + self.connected_clients.borrow().iter().copied().collect(), + self.style, + invoked_with, + self.debug, + self.arrow_fonts, + self.styled_underlines, + )) as Box + }, + }; + + if start_suppressed { + // this pane needs to start in the background (suppressed), only accessible if a plugin takes it out + // of there in one way or another + // we need to do some bookkeeping for this pane, namely setting its geom and + // content_offset so that things will appear properly in the terminal - we set it to + // the default geom of the first floating pane - this is just in order to give it some + // reasonable size, when it is shown - if needed - it will be given the proper geom as if it were + // resized + let viewport = { self.viewport.borrow().clone() }; + let new_pane_geom = half_size_middle_geom(&viewport, 0); + new_pane.set_active_at(Instant::now()); + new_pane.set_geom(new_pane_geom); + new_pane.set_content_offset(Offset::frame(1)); + resize_pty!( + new_pane, + self.os_api, + self.senders, + self.character_cell_size + ) + .with_context(err_context)?; + let is_scrollback_editor = false; + self.suppressed_panes + .insert(pid, (is_scrollback_editor, new_pane)); + Ok(()) + } else { + if let Some(pane_id_to_stack_under) = pane_id_to_stack_under { + // TODO: also focus pane if should_focus_pane? in cases where we did this from the CLI in an unfocused + // pane... + self.add_stacked_pane_to_pane_id(new_pane, pid, pane_id_to_stack_under) + } else if let Some(client_id) = client_id { + self.add_stacked_pane_to_active_pane(new_pane, pid, client_id) + } else { + log::error!("Must have client id or pane id to stack pane"); + return Ok(()); } } } @@ -4653,6 +5028,38 @@ impl Tab { } Ok(()) } + pub fn add_stacked_pane_to_pane_id( + &mut self, + pane: Box, + pane_id: PaneId, + root_pane_id: PaneId, + ) -> Result<()> { + if self.tiled_panes.fullscreen_is_active() { + self.tiled_panes.unset_fullscreen(); + } + self.tiled_panes + .add_pane_to_stack_of_pane_id(pane_id, pane, root_pane_id); + self.set_should_clear_display_before_rendering(); + self.tiled_panes.expand_pane_in_stack(pane_id); // so that it will get focused by all + // clients + self.swap_layouts.set_is_tiled_damaged(); + Ok(()) + } + pub fn add_stacked_pane_to_active_pane( + &mut self, + pane: Box, + pane_id: PaneId, + client_id: ClientId, + ) -> Result<()> { + if self.tiled_panes.fullscreen_is_active() { + self.tiled_panes.unset_fullscreen(); + } + self.tiled_panes + .add_pane_to_stack_of_active_pane(pane_id, pane, client_id); + self.tiled_panes.focus_pane(pane_id, client_id); + self.swap_layouts.set_is_tiled_damaged(); + Ok(()) + } pub fn request_plugin_permissions(&mut self, pid: u32, permissions: Option) { let mut should_focus_pane = false; if let Some(plugin_pane) = self diff --git a/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__new_stacked_pane.snap b/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__new_stacked_pane.snap new file mode 100644 index 00000000..19463392 --- /dev/null +++ b/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__new_stacked_pane.snap @@ -0,0 +1,24 @@ +--- +source: zellij-server/src/tab/./unit/tab_integration_tests.rs +expression: snapshot +--- +00 (C): ┌ Pane #1 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +01 (C): ┌ Pane #2 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +02 (C): │ │ +03 (C): │ │ +04 (C): │ │ +05 (C): │ │ +06 (C): │ │ +07 (C): │ │ +08 (C): │ │ +09 (C): │ │ +10 (C): │ │ +11 (C): │ │ +12 (C): │ │ +13 (C): │ │ +14 (C): │ │ +15 (C): │ │ +16 (C): │ │ +17 (C): │ │ +18 (C): │ │ +19 (C): └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/zellij-server/src/tab/unit/tab_integration_tests.rs b/zellij-server/src/tab/unit/tab_integration_tests.rs index 8df5effb..8f5ff185 100644 --- a/zellij-server/src/tab/unit/tab_integration_tests.rs +++ b/zellij-server/src/tab/unit/tab_integration_tests.rs @@ -32,6 +32,7 @@ use zellij_utils::ipc::IpcReceiverWithContext; use zellij_utils::pane_size::{Size, SizeInPixels}; use zellij_utils::position::Position; +use crate::pty::NewPanePlacement; use crate::pty_writer::PtyWriteInstruction; use zellij_utils::channels::{self, ChannelWithContext, SenderWithContext}; @@ -961,10 +962,9 @@ fn increase_tiled_pane_sizes_with_stacked_resizes() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1015,10 +1015,9 @@ fn increase_tiled_pane_sizes_with_stacked_resizes_into_uneven_panes() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1078,10 +1077,9 @@ fn split_stack_vertically() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1119,10 +1117,9 @@ fn split_stack_horizontally() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1162,10 +1159,9 @@ fn render_stacks_without_pane_frames() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1183,10 +1179,9 @@ fn render_stacks_without_pane_frames() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1198,10 +1193,9 @@ fn render_stacks_without_pane_frames() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1213,10 +1207,9 @@ fn render_stacks_without_pane_frames() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1257,10 +1250,9 @@ fn dump_screen() { new_pane_id, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1294,10 +1286,9 @@ fn clear_screen() { new_pane_id, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1329,10 +1320,9 @@ fn new_floating_pane() { new_pane_id, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1351,6 +1341,36 @@ fn new_floating_pane() { assert_snapshot!(snapshot); } +#[test] +fn new_stacked_pane() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 1; + let mut tab = create_new_tab(size, ModeInfo::default()); + let new_pane_id = PaneId::Terminal(2); + let mut output = Output::default(); + tab.new_pane( + new_pane_id, + None, + None, + false, + true, + NewPanePlacement::Stacked(None), + Some(client_id), + ) + .unwrap(); + tab.render(&mut output).unwrap(); + let snapshot = take_snapshot( + output.serialize().unwrap().get(&client_id).unwrap(), + size.rows, + size.cols, + Palette::default(), + ); + assert_snapshot!(snapshot); +} + #[test] fn floating_panes_persist_across_toggles() { let size = Size { @@ -1366,10 +1386,9 @@ fn floating_panes_persist_across_toggles() { new_pane_id, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1407,10 +1426,9 @@ fn toggle_floating_panes_off() { new_pane_id, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1445,10 +1463,9 @@ fn toggle_floating_panes_on() { new_pane_id, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1488,10 +1505,9 @@ fn five_new_floating_panes() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1499,10 +1515,9 @@ fn five_new_floating_panes() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1510,10 +1525,9 @@ fn five_new_floating_panes() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1521,10 +1535,9 @@ fn five_new_floating_panes() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1532,10 +1545,9 @@ fn five_new_floating_panes() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1577,10 +1589,9 @@ fn increase_floating_pane_size() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1616,10 +1627,9 @@ fn decrease_floating_pane_size() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1655,10 +1665,9 @@ fn resize_floating_pane_left() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1697,10 +1706,9 @@ fn resize_floating_pane_right() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1739,10 +1747,9 @@ fn resize_floating_pane_up() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1781,10 +1788,9 @@ fn resize_floating_pane_down() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1827,10 +1833,9 @@ fn move_floating_pane_focus_left() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1838,10 +1843,9 @@ fn move_floating_pane_focus_left() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1849,10 +1853,9 @@ fn move_floating_pane_focus_left() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1860,10 +1863,9 @@ fn move_floating_pane_focus_left() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1871,10 +1873,9 @@ fn move_floating_pane_focus_left() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1927,10 +1928,9 @@ fn move_floating_pane_focus_right() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1938,10 +1938,9 @@ fn move_floating_pane_focus_right() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1949,10 +1948,9 @@ fn move_floating_pane_focus_right() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1960,10 +1958,9 @@ fn move_floating_pane_focus_right() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -1971,10 +1968,9 @@ fn move_floating_pane_focus_right() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2028,10 +2024,9 @@ fn move_floating_pane_focus_up() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2039,10 +2034,9 @@ fn move_floating_pane_focus_up() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2050,10 +2044,9 @@ fn move_floating_pane_focus_up() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2061,10 +2054,9 @@ fn move_floating_pane_focus_up() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2072,10 +2064,9 @@ fn move_floating_pane_focus_up() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2128,10 +2119,9 @@ fn move_floating_pane_focus_down() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2139,10 +2129,9 @@ fn move_floating_pane_focus_down() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2150,10 +2139,9 @@ fn move_floating_pane_focus_down() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2161,10 +2149,9 @@ fn move_floating_pane_focus_down() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2172,10 +2159,9 @@ fn move_floating_pane_focus_down() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2229,10 +2215,9 @@ fn move_floating_pane_focus_with_mouse() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2240,10 +2225,9 @@ fn move_floating_pane_focus_with_mouse() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2251,10 +2235,9 @@ fn move_floating_pane_focus_with_mouse() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2262,10 +2245,9 @@ fn move_floating_pane_focus_with_mouse() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2273,10 +2255,9 @@ fn move_floating_pane_focus_with_mouse() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2338,10 +2319,9 @@ fn move_pane_focus_with_mouse_to_non_floating_pane() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2349,10 +2329,9 @@ fn move_pane_focus_with_mouse_to_non_floating_pane() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2360,10 +2339,9 @@ fn move_pane_focus_with_mouse_to_non_floating_pane() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2371,10 +2349,9 @@ fn move_pane_focus_with_mouse_to_non_floating_pane() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2382,10 +2359,9 @@ fn move_pane_focus_with_mouse_to_non_floating_pane() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2447,10 +2423,9 @@ fn drag_pane_with_mouse() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2458,10 +2433,9 @@ fn drag_pane_with_mouse() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2469,10 +2443,9 @@ fn drag_pane_with_mouse() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2480,10 +2453,9 @@ fn drag_pane_with_mouse() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2491,10 +2463,9 @@ fn drag_pane_with_mouse() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2556,10 +2527,9 @@ fn mark_text_inside_floating_pane() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2567,10 +2537,9 @@ fn mark_text_inside_floating_pane() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2578,10 +2547,9 @@ fn mark_text_inside_floating_pane() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2589,10 +2557,9 @@ fn mark_text_inside_floating_pane() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2600,10 +2567,9 @@ fn mark_text_inside_floating_pane() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2673,10 +2639,9 @@ fn resize_tab_with_floating_panes() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2684,10 +2649,9 @@ fn resize_tab_with_floating_panes() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2695,10 +2659,9 @@ fn resize_tab_with_floating_panes() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2706,10 +2669,9 @@ fn resize_tab_with_floating_panes() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2717,10 +2679,9 @@ fn resize_tab_with_floating_panes() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2772,10 +2733,9 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2783,10 +2743,9 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2794,10 +2753,9 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2805,10 +2763,9 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2816,10 +2773,9 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2867,10 +2823,9 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically_and_expand_b new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2878,10 +2833,9 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically_and_expand_b new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2889,10 +2843,9 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically_and_expand_b new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2900,10 +2853,9 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically_and_expand_b new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2911,10 +2863,9 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically_and_expand_b new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -2963,10 +2914,9 @@ fn embed_floating_pane() { new_pane_id, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -3000,10 +2950,9 @@ fn float_embedded_pane() { new_pane_id, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -3039,10 +2988,9 @@ fn embed_floating_pane_without_pane_frames() { new_pane_id, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -3077,10 +3025,9 @@ fn float_embedded_pane_without_pane_frames() { new_pane_id, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -3189,10 +3136,9 @@ fn rename_floating_pane() { new_pane_id, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -3294,10 +3240,9 @@ fn move_floating_pane_with_sixel_image() { new_pane_id, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -3347,10 +3292,9 @@ fn floating_pane_above_sixel_image() { new_pane_id, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -3420,10 +3364,9 @@ fn suppress_floating_pane() { new_pane_id, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -3485,10 +3428,9 @@ fn close_suppressing_floating_pane() { new_pane_id, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -3554,10 +3496,9 @@ fn suppress_floating_pane_embed_it_and_close_it() { new_pane_id, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -3625,10 +3566,9 @@ fn resize_whole_tab_while_floting_pane_is_suppressed() { new_pane_id, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -3736,10 +3676,9 @@ fn enter_search_floating_pane() { new_pane_id, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -4512,10 +4451,9 @@ fn move_pane_focus_sends_tty_csi_event() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -4556,10 +4494,9 @@ fn move_floating_pane_focus_sends_tty_csi_event() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -4567,10 +4504,9 @@ fn move_floating_pane_focus_sends_tty_csi_event() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -4617,10 +4553,9 @@ fn toggle_floating_panes_on_sends_tty_csi_event() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -4628,10 +4563,9 @@ fn toggle_floating_panes_on_sends_tty_csi_event() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -4679,10 +4613,9 @@ fn toggle_floating_panes_off_sends_tty_csi_event() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -4690,10 +4623,9 @@ fn toggle_floating_panes_off_sends_tty_csi_event() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -4761,10 +4693,9 @@ fn can_swap_tiled_layout_at_runtime() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -4827,10 +4758,9 @@ fn can_swap_floating_layout_at_runtime() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -4838,10 +4768,9 @@ fn can_swap_floating_layout_at_runtime() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -4900,10 +4829,9 @@ fn swapping_layouts_after_resize_snaps_to_current_layout() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -4961,10 +4889,9 @@ fn swap_tiled_layout_with_stacked_children() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -4972,10 +4899,9 @@ fn swap_tiled_layout_with_stacked_children() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -4983,10 +4909,9 @@ fn swap_tiled_layout_with_stacked_children() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5037,10 +4962,9 @@ fn swap_tiled_layout_with_only_stacked_children() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5048,10 +4972,9 @@ fn swap_tiled_layout_with_only_stacked_children() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5059,10 +4982,9 @@ fn swap_tiled_layout_with_only_stacked_children() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5116,10 +5038,9 @@ fn swap_tiled_layout_with_stacked_children_and_no_pane_frames() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5127,10 +5048,9 @@ fn swap_tiled_layout_with_stacked_children_and_no_pane_frames() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5138,10 +5058,9 @@ fn swap_tiled_layout_with_stacked_children_and_no_pane_frames() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5195,10 +5114,9 @@ fn move_focus_up_with_stacked_panes() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5206,10 +5124,9 @@ fn move_focus_up_with_stacked_panes() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5217,10 +5134,9 @@ fn move_focus_up_with_stacked_panes() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5276,10 +5192,9 @@ fn move_focus_down_with_stacked_panes() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5287,10 +5202,9 @@ fn move_focus_down_with_stacked_panes() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5298,10 +5212,9 @@ fn move_focus_down_with_stacked_panes() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5359,10 +5272,9 @@ fn move_focus_right_into_stacked_panes() { PaneId::Terminal(new_pane_id), None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5431,10 +5343,9 @@ fn move_focus_left_into_stacked_panes() { PaneId::Terminal(new_pane_id), None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5505,10 +5416,9 @@ fn move_focus_up_into_stacked_panes() { PaneId::Terminal(new_pane_id), None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5580,10 +5490,9 @@ fn move_focus_down_into_stacked_panes() { PaneId::Terminal(new_pane_id), None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5651,10 +5560,9 @@ fn close_main_stacked_pane() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5662,10 +5570,9 @@ fn close_main_stacked_pane() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5673,10 +5580,9 @@ fn close_main_stacked_pane() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5733,10 +5639,9 @@ fn close_main_stacked_pane_in_mid_stack() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5744,10 +5649,9 @@ fn close_main_stacked_pane_in_mid_stack() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5755,10 +5659,9 @@ fn close_main_stacked_pane_in_mid_stack() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5766,10 +5669,9 @@ fn close_main_stacked_pane_in_mid_stack() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5777,10 +5679,9 @@ fn close_main_stacked_pane_in_mid_stack() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5840,10 +5741,9 @@ fn close_one_liner_stacked_pane_below_main_pane() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5851,10 +5751,9 @@ fn close_one_liner_stacked_pane_below_main_pane() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5862,10 +5761,9 @@ fn close_one_liner_stacked_pane_below_main_pane() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5873,10 +5771,9 @@ fn close_one_liner_stacked_pane_below_main_pane() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5884,10 +5781,9 @@ fn close_one_liner_stacked_pane_below_main_pane() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5948,10 +5844,9 @@ fn close_one_liner_stacked_pane_above_main_pane() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5959,10 +5854,9 @@ fn close_one_liner_stacked_pane_above_main_pane() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5970,10 +5864,9 @@ fn close_one_liner_stacked_pane_above_main_pane() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5981,10 +5874,9 @@ fn close_one_liner_stacked_pane_above_main_pane() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -5992,10 +5884,9 @@ fn close_one_liner_stacked_pane_above_main_pane() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6055,10 +5946,9 @@ fn can_increase_size_of_main_pane_in_stack_horizontally() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6066,10 +5956,9 @@ fn can_increase_size_of_main_pane_in_stack_horizontally() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6077,10 +5966,9 @@ fn can_increase_size_of_main_pane_in_stack_horizontally() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6088,10 +5976,9 @@ fn can_increase_size_of_main_pane_in_stack_horizontally() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6099,10 +5986,9 @@ fn can_increase_size_of_main_pane_in_stack_horizontally() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6166,10 +6052,9 @@ fn can_increase_size_of_main_pane_in_stack_vertically() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6177,10 +6062,9 @@ fn can_increase_size_of_main_pane_in_stack_vertically() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6188,10 +6072,9 @@ fn can_increase_size_of_main_pane_in_stack_vertically() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6199,10 +6082,9 @@ fn can_increase_size_of_main_pane_in_stack_vertically() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6210,10 +6092,9 @@ fn can_increase_size_of_main_pane_in_stack_vertically() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6277,10 +6158,9 @@ fn can_increase_size_of_main_pane_in_stack_non_directionally() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6288,10 +6168,9 @@ fn can_increase_size_of_main_pane_in_stack_non_directionally() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6299,10 +6178,9 @@ fn can_increase_size_of_main_pane_in_stack_non_directionally() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6310,10 +6188,9 @@ fn can_increase_size_of_main_pane_in_stack_non_directionally() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6321,10 +6198,9 @@ fn can_increase_size_of_main_pane_in_stack_non_directionally() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6383,10 +6259,9 @@ fn can_increase_size_into_pane_stack_horizontally() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6394,10 +6269,9 @@ fn can_increase_size_into_pane_stack_horizontally() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6405,10 +6279,9 @@ fn can_increase_size_into_pane_stack_horizontally() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6416,10 +6289,9 @@ fn can_increase_size_into_pane_stack_horizontally() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6427,10 +6299,9 @@ fn can_increase_size_into_pane_stack_horizontally() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6493,10 +6364,9 @@ fn can_increase_size_into_pane_stack_vertically() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6504,10 +6374,9 @@ fn can_increase_size_into_pane_stack_vertically() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6515,10 +6384,9 @@ fn can_increase_size_into_pane_stack_vertically() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6526,10 +6394,9 @@ fn can_increase_size_into_pane_stack_vertically() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6537,10 +6404,9 @@ fn can_increase_size_into_pane_stack_vertically() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6606,10 +6472,9 @@ fn can_increase_size_into_pane_stack_non_directionally() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6617,10 +6482,9 @@ fn can_increase_size_into_pane_stack_non_directionally() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6628,10 +6492,9 @@ fn can_increase_size_into_pane_stack_non_directionally() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6639,10 +6502,9 @@ fn can_increase_size_into_pane_stack_non_directionally() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6650,10 +6512,9 @@ fn can_increase_size_into_pane_stack_non_directionally() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6711,10 +6572,9 @@ fn decreasing_size_of_whole_tab_treats_stacked_panes_properly() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6722,10 +6582,9 @@ fn decreasing_size_of_whole_tab_treats_stacked_panes_properly() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6733,10 +6592,9 @@ fn decreasing_size_of_whole_tab_treats_stacked_panes_properly() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6744,10 +6602,9 @@ fn decreasing_size_of_whole_tab_treats_stacked_panes_properly() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6755,10 +6612,9 @@ fn decreasing_size_of_whole_tab_treats_stacked_panes_properly() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6818,10 +6674,9 @@ fn increasing_size_of_whole_tab_treats_stacked_panes_properly() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6829,10 +6684,9 @@ fn increasing_size_of_whole_tab_treats_stacked_panes_properly() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6840,10 +6694,9 @@ fn increasing_size_of_whole_tab_treats_stacked_panes_properly() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6851,10 +6704,9 @@ fn increasing_size_of_whole_tab_treats_stacked_panes_properly() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6862,10 +6714,9 @@ fn increasing_size_of_whole_tab_treats_stacked_panes_properly() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6930,10 +6781,9 @@ fn cannot_decrease_stack_size_beyond_minimum_height() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6941,10 +6791,9 @@ fn cannot_decrease_stack_size_beyond_minimum_height() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6952,10 +6801,9 @@ fn cannot_decrease_stack_size_beyond_minimum_height() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6963,10 +6811,9 @@ fn cannot_decrease_stack_size_beyond_minimum_height() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -6974,10 +6821,9 @@ fn cannot_decrease_stack_size_beyond_minimum_height() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7042,10 +6888,9 @@ fn focus_stacked_pane_over_flexible_pane_with_the_mouse() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7053,10 +6898,9 @@ fn focus_stacked_pane_over_flexible_pane_with_the_mouse() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7064,10 +6908,9 @@ fn focus_stacked_pane_over_flexible_pane_with_the_mouse() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7075,10 +6918,9 @@ fn focus_stacked_pane_over_flexible_pane_with_the_mouse() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7086,10 +6928,9 @@ fn focus_stacked_pane_over_flexible_pane_with_the_mouse() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7151,10 +6992,9 @@ fn focus_stacked_pane_under_flexible_pane_with_the_mouse() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7162,10 +7002,9 @@ fn focus_stacked_pane_under_flexible_pane_with_the_mouse() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7173,10 +7012,9 @@ fn focus_stacked_pane_under_flexible_pane_with_the_mouse() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7184,10 +7022,9 @@ fn focus_stacked_pane_under_flexible_pane_with_the_mouse() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7195,10 +7032,9 @@ fn focus_stacked_pane_under_flexible_pane_with_the_mouse() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7265,10 +7101,9 @@ fn close_stacked_pane_with_previously_focused_other_pane() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7276,10 +7111,9 @@ fn close_stacked_pane_with_previously_focused_other_pane() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7287,10 +7121,9 @@ fn close_stacked_pane_with_previously_focused_other_pane() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7298,10 +7131,9 @@ fn close_stacked_pane_with_previously_focused_other_pane() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7309,10 +7141,9 @@ fn close_stacked_pane_with_previously_focused_other_pane() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7385,10 +7216,9 @@ fn close_pane_near_stacked_panes() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7396,10 +7226,9 @@ fn close_pane_near_stacked_panes() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7407,10 +7236,9 @@ fn close_pane_near_stacked_panes() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7418,10 +7246,9 @@ fn close_pane_near_stacked_panes() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7429,10 +7256,9 @@ fn close_pane_near_stacked_panes() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7496,10 +7322,9 @@ fn focus_next_pane_expands_stacked_panes() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7507,10 +7332,9 @@ fn focus_next_pane_expands_stacked_panes() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7518,10 +7342,9 @@ fn focus_next_pane_expands_stacked_panes() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7529,10 +7352,9 @@ fn focus_next_pane_expands_stacked_panes() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7540,10 +7362,9 @@ fn focus_next_pane_expands_stacked_panes() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7603,10 +7424,9 @@ fn stacked_panes_can_become_fullscreen() { new_pane_id_1, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7614,10 +7434,9 @@ fn stacked_panes_can_become_fullscreen() { new_pane_id_2, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7625,10 +7444,9 @@ fn stacked_panes_can_become_fullscreen() { new_pane_id_3, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7636,10 +7454,9 @@ fn stacked_panes_can_become_fullscreen() { new_pane_id_4, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -7647,10 +7464,9 @@ fn stacked_panes_can_become_fullscreen() { new_pane_id_5, None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -8306,10 +8122,9 @@ fn new_pane_in_auto_layout() { PaneId::Terminal(new_pane_id), None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -8377,10 +8192,9 @@ fn new_pane_in_stacked_resizes() { PaneId::Terminal(new_pane_id), None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(client_id), ) .unwrap(); @@ -9324,15 +9138,13 @@ fn new_floating_pane_in_auto_layout() { let mut expected_cursor_coordinates = vec![(62, 11), (62, 6), (31, 12)]; for i in 0..3 { let new_pane_id = i + 2; - let should_float = true; tab.new_pane( PaneId::Terminal(new_pane_id), None, - Some(should_float), - None, None, false, true, + NewPanePlacement::Floating(None), Some(client_id), ) .unwrap(); diff --git a/zellij-server/src/tab/unit/tab_tests.rs b/zellij-server/src/tab/unit/tab_tests.rs index 1c4eabe4..bca69529 100644 --- a/zellij-server/src/tab/unit/tab_tests.rs +++ b/zellij-server/src/tab/unit/tab_tests.rs @@ -1,6 +1,7 @@ use super::Tab; use crate::pane_groups::PaneGroups; use crate::panes::sixel::SixelImageStore; +use crate::pty::NewPanePlacement; use crate::screen::CopyOptions; use crate::{ os_input_output::{AsyncReader, Pid, ServerOsApi}, @@ -625,8 +626,16 @@ fn split_largest_pane() { let mut tab = create_new_tab(size, stacked_resize); for i in 2..5 { let new_pane_id = PaneId::Terminal(i); - tab.new_pane(new_pane_id, None, None, None, None, false, true, Some(1)) - .unwrap(); + tab.new_pane( + new_pane_id, + None, + None, + false, + true, + NewPanePlacement::default(), + Some(1), + ) + .unwrap(); } assert_eq!(tab.tiled_panes.panes.len(), 4, "The tab has four panes"); @@ -838,10 +847,9 @@ pub fn cannot_split_largest_pane_when_there_is_no_room() { PaneId::Terminal(2), None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(1), ) .unwrap(); @@ -888,8 +896,16 @@ pub fn toggle_focused_pane_fullscreen() { let mut tab = create_new_tab(size, stacked_resize); for i in 2..5 { let new_pane_id = PaneId::Terminal(i); - tab.new_pane(new_pane_id, None, None, None, None, false, true, Some(1)) - .unwrap(); + tab.new_pane( + new_pane_id, + None, + None, + false, + true, + NewPanePlacement::default(), + Some(1), + ) + .unwrap(); } tab.toggle_active_pane_fullscreen(1); assert_eq!( @@ -964,8 +980,16 @@ pub fn toggle_focused_pane_fullscreen_with_stacked_resizes() { let mut tab = create_new_tab(size, stacked_resize); for i in 2..5 { let new_pane_id = PaneId::Terminal(i); - tab.new_pane(new_pane_id, None, None, None, None, false, true, Some(1)) - .unwrap(); + tab.new_pane( + new_pane_id, + None, + None, + false, + true, + NewPanePlacement::default(), + Some(1), + ) + .unwrap(); } tab.toggle_active_pane_fullscreen(1); assert_eq!( @@ -1044,10 +1068,9 @@ fn switch_to_next_pane_fullscreen() { PaneId::Terminal(1), None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(1), ) .unwrap(); @@ -1056,10 +1079,9 @@ fn switch_to_next_pane_fullscreen() { PaneId::Terminal(2), None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(1), ) .unwrap(); @@ -1068,10 +1090,9 @@ fn switch_to_next_pane_fullscreen() { PaneId::Terminal(3), None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(1), ) .unwrap(); @@ -1080,10 +1101,9 @@ fn switch_to_next_pane_fullscreen() { PaneId::Terminal(4), None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(1), ) .unwrap(); @@ -1121,10 +1141,9 @@ fn switch_to_prev_pane_fullscreen() { PaneId::Terminal(1), None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(1), ) .unwrap(); @@ -1133,10 +1152,9 @@ fn switch_to_prev_pane_fullscreen() { PaneId::Terminal(2), None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(1), ) .unwrap(); @@ -1145,10 +1163,9 @@ fn switch_to_prev_pane_fullscreen() { PaneId::Terminal(3), None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(1), ) .unwrap(); @@ -1157,10 +1174,9 @@ fn switch_to_prev_pane_fullscreen() { PaneId::Terminal(4), None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(1), ) .unwrap(); @@ -14758,10 +14774,9 @@ fn correctly_resize_frameless_panes_on_pane_close() { PaneId::Terminal(2), None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(1), ) .unwrap(); diff --git a/zellij-server/src/unit/screen_tests.rs b/zellij-server/src/unit/screen_tests.rs index 6e0e4870..a1164864 100644 --- a/zellij-server/src/unit/screen_tests.rs +++ b/zellij-server/src/unit/screen_tests.rs @@ -34,7 +34,7 @@ use std::sync::{Arc, Mutex}; use crate::{ plugins::PluginInstruction, - pty::{ClientTabIndexOrPaneId, PtyInstruction}, + pty::{ClientTabIndexOrPaneId, NewPanePlacement, PtyInstruction}, }; use zellij_utils::ipc::PixelDimensions; @@ -1235,10 +1235,9 @@ fn switch_to_tab_with_fullscreen() { PaneId::Terminal(2), None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(1), ) .unwrap(); @@ -1359,10 +1358,9 @@ fn attach_after_first_tab_closed() { PaneId::Terminal(2), None, None, - None, - None, false, true, + NewPanePlacement::default(), Some(1), ) .unwrap(); @@ -1385,22 +1383,20 @@ fn open_new_floating_pane_with_custom_coordinates() { new_tab(&mut screen, 1, 0); let active_tab = screen.get_active_tab_mut(1).unwrap(); - let should_float = Some(true); active_tab .new_pane( PaneId::Terminal(2), None, - should_float, None, - Some(FloatingPaneCoordinates { + false, + true, + NewPanePlacement::Floating(Some(FloatingPaneCoordinates { x: Some(SplitSize::Percent(10)), y: Some(SplitSize::Fixed(5)), width: Some(SplitSize::Percent(1)), height: Some(SplitSize::Fixed(2)), pinned: None, - }), - false, - true, + })), Some(1), ) .unwrap(); @@ -1421,22 +1417,20 @@ fn open_new_floating_pane_with_custom_coordinates_exceeding_viewport() { new_tab(&mut screen, 1, 0); let active_tab = screen.get_active_tab_mut(1).unwrap(); - let should_float = Some(true); active_tab .new_pane( PaneId::Terminal(2), None, - should_float, None, - Some(FloatingPaneCoordinates { + false, + true, + NewPanePlacement::Floating(Some(FloatingPaneCoordinates { x: Some(SplitSize::Fixed(122)), y: Some(SplitSize::Fixed(21)), width: Some(SplitSize::Fixed(10)), height: Some(SplitSize::Fixed(10)), pinned: None, - }), - false, - true, + })), Some(1), ) .unwrap(); @@ -1611,17 +1605,15 @@ fn group_panes_following_focus() { { let active_tab = screen.get_active_tab_mut(client_id).unwrap(); - let should_float = Some(false); for i in 2..5 { active_tab .new_pane( PaneId::Terminal(i), None, - should_float, - None, None, false, true, + NewPanePlacement::Tiled(None), Some(client_id), ) .unwrap(); @@ -1670,17 +1662,15 @@ fn break_group_with_mouse() { { let active_tab = screen.get_active_tab_mut(client_id).unwrap(); - let should_float = Some(false); for i in 2..5 { active_tab .new_pane( PaneId::Terminal(i), None, - should_float, - None, None, false, true, + NewPanePlacement::Tiled(None), Some(client_id), ) .unwrap(); @@ -2596,6 +2586,7 @@ pub fn send_cli_new_pane_action_with_default_parameters() { width: None, height: None, pinned: None, + stacked: false, }; send_cli_action_to_server(&session_metadata, cli_new_pane_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); // give time for actions to be @@ -2640,6 +2631,7 @@ pub fn send_cli_new_pane_action_with_split_direction() { width: None, height: None, pinned: None, + stacked: false, }; send_cli_action_to_server(&session_metadata, cli_new_pane_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); // give time for actions to be @@ -2684,6 +2676,7 @@ pub fn send_cli_new_pane_action_with_command_and_cwd() { width: None, height: None, pinned: None, + stacked: false, }; send_cli_action_to_server(&session_metadata, cli_new_pane_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); // give time for actions to be @@ -2694,7 +2687,7 @@ pub fn send_cli_new_pane_action_with_command_and_cwd() { .unwrap() .iter() .find(|instruction| match instruction { - PtyInstruction::SpawnTerminalVertically(..) => true, + PtyInstruction::SpawnTerminal(..) => true, _ => false, }) .cloned(); @@ -2739,6 +2732,7 @@ pub fn send_cli_new_pane_action_with_floating_pane_and_coordinates() { width: Some("20%".to_owned()), height: None, pinned: None, + stacked: false, }; send_cli_action_to_server(&session_metadata, cli_new_pane_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); // give time for actions to be diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_default_parameters.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_default_parameters.snap index 01736b70..aaa64760 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_default_parameters.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_default_parameters.snap @@ -2,4 +2,4 @@ source: zellij-server/src/./unit/screen_tests.rs expression: "format!(\"{:?}\", *received_pty_instructions.lock().unwrap())" --- -[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(Some(OpenFile(OpenFilePayload { path: "/file/to/edit", line_number: None, cwd: Some("."), originating_plugin: None })), Some(false), Some("Editing: /file/to/edit"), None, false, ClientId(10)), Exit] +[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(Some(OpenFile(OpenFilePayload { path: "/file/to/edit", line_number: None, cwd: Some("."), originating_plugin: None })), Some("Editing: /file/to/edit"), Tiled(None), false, ClientId(10)), Exit] diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_line_number.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_line_number.snap index 097e9f01..bbe39929 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_line_number.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_line_number.snap @@ -2,4 +2,4 @@ source: zellij-server/src/./unit/screen_tests.rs expression: "format!(\"{:?}\", *received_pty_instructions.lock().unwrap())" --- -[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(Some(OpenFile(OpenFilePayload { path: "/file/to/edit", line_number: Some(100), cwd: Some("."), originating_plugin: None })), Some(false), Some("Editing: /file/to/edit"), None, false, ClientId(10)), Exit] +[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(Some(OpenFile(OpenFilePayload { path: "/file/to/edit", line_number: Some(100), cwd: Some("."), originating_plugin: None })), Some("Editing: /file/to/edit"), Tiled(None), false, ClientId(10)), Exit] diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_split_direction.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_split_direction.snap index 80db096e..c621db39 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_split_direction.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_split_direction.snap @@ -2,4 +2,4 @@ source: zellij-server/src/./unit/screen_tests.rs expression: "format!(\"{:?}\", *received_pty_instructions.lock().unwrap())" --- -[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminalHorizontally(Some(OpenFile(OpenFilePayload { path: "/file/to/edit", line_number: None, cwd: Some("."), originating_plugin: None })), Some("Editing: /file/to/edit"), 10), Exit] +[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(Some(OpenFile(OpenFilePayload { path: "/file/to/edit", line_number: None, cwd: Some("."), originating_plugin: None })), Some("Editing: /file/to/edit"), Tiled(Some(Down)), false, ClientId(10)), Exit] diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_command_and_cwd.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_command_and_cwd.snap index 57042301..aa2ff031 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_command_and_cwd.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_command_and_cwd.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2339 expression: "format!(\"{:?}\", new_pane_instruction)" --- -Some(SpawnTerminalVertically(Some(RunCommand(RunCommand { command: "htop", args: [], cwd: Some("/some/folder"), hold_on_close: true, hold_on_start: false, originating_plugin: None })), None, 10)) +Some(SpawnTerminal(Some(RunCommand(RunCommand { command: "htop", args: [], cwd: Some("/some/folder"), hold_on_close: true, hold_on_start: false, originating_plugin: None })), None, Tiled(Some(Right)), false, ClientId(10))) diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_default_parameters.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_default_parameters.snap index 93561eb3..70d863de 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_default_parameters.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_default_parameters.snap @@ -2,4 +2,4 @@ source: zellij-server/src/./unit/screen_tests.rs expression: "format!(\"{:?}\", *received_pty_instructions.lock().unwrap())" --- -[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(None, Some(false), None, None, false, ClientId(10)), Exit] +[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(None, None, Tiled(None), false, ClientId(10)), Exit] diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_floating_pane_and_coordinates.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_floating_pane_and_coordinates.snap index cb24294e..cfd057f8 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_floating_pane_and_coordinates.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_floating_pane_and_coordinates.snap @@ -2,4 +2,4 @@ source: zellij-server/src/./unit/screen_tests.rs expression: "format!(\"{:?}\", *received_pty_instructions.lock().unwrap())" --- -[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(Some(RunCommand(RunCommand { command: "htop", args: [], cwd: Some("/some/folder"), hold_on_close: true, hold_on_start: false, originating_plugin: None })), Some(true), None, Some(FloatingPaneCoordinates { x: Some(Fixed(10)), y: None, width: Some(Percent(20)), height: None, pinned: None }), false, ClientId(10)), Exit] +[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(Some(RunCommand(RunCommand { command: "htop", args: [], cwd: Some("/some/folder"), hold_on_close: true, hold_on_start: false, originating_plugin: None })), None, Floating(Some(FloatingPaneCoordinates { x: Some(Fixed(10)), y: None, width: Some(Percent(20)), height: None, pinned: None })), false, ClientId(10)), Exit] diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_split_direction.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_split_direction.snap index a42fe8e1..a46b0152 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_split_direction.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_split_direction.snap @@ -2,4 +2,4 @@ source: zellij-server/src/./unit/screen_tests.rs expression: "format!(\"{:?}\", *received_pty_instructions.lock().unwrap())" --- -[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminalVertically(None, None, 10), Exit] +[UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), SpawnTerminal(None, None, Tiled(Some(Right)), false, ClientId(10)), Exit] diff --git a/zellij-utils/assets/config/default.kdl b/zellij-utils/assets/config/default.kdl index 0ea6ca78..a5f083cb 100644 --- a/zellij-utils/assets/config/default.kdl +++ b/zellij-utils/assets/config/default.kdl @@ -30,6 +30,7 @@ keybinds { bind "n" { NewPane; SwitchToMode "Normal"; } bind "d" { NewPane "Down"; SwitchToMode "Normal"; } bind "r" { NewPane "Right"; SwitchToMode "Normal"; } + bind "s" { NewPane "stacked"; SwitchToMode "Normal"; } bind "x" { CloseFocus; SwitchToMode "Normal"; } bind "f" { ToggleFocusFullscreen; SwitchToMode "Normal"; } bind "z" { TogglePaneFrames; SwitchToMode "Normal"; } diff --git a/zellij-utils/assets/prost/api.action.rs b/zellij-utils/assets/prost/api.action.rs index 97b88452..b835236b 100644 --- a/zellij-utils/assets/prost/api.action.rs +++ b/zellij-utils/assets/prost/api.action.rs @@ -475,6 +475,7 @@ pub enum ActionName { MouseEvent = 86, TogglePaneInGroup = 87, ToggleGroupMarking = 88, + NewStackedPane = 89, } impl ActionName { /// String value of the enum field names used in the ProtoBuf definition. @@ -569,6 +570,7 @@ impl ActionName { ActionName::MouseEvent => "MouseEvent", ActionName::TogglePaneInGroup => "TogglePaneInGroup", ActionName::ToggleGroupMarking => "ToggleGroupMarking", + ActionName::NewStackedPane => "NewStackedPane", } } /// Creates an enum from field names used in the ProtoBuf definition. @@ -660,6 +662,7 @@ impl ActionName { "MouseEvent" => Some(Self::MouseEvent), "TogglePaneInGroup" => Some(Self::TogglePaneInGroup), "ToggleGroupMarking" => Some(Self::ToggleGroupMarking), + "NewStackedPane" => Some(Self::NewStackedPane), _ => None, } } diff --git a/zellij-utils/src/cli.rs b/zellij-utils/src/cli.rs index 6a631f8b..164f5999 100644 --- a/zellij-utils/src/cli.rs +++ b/zellij-utils/src/cli.rs @@ -313,6 +313,15 @@ pub enum Sessions { /// Whether to pin a floating pane so that it is always on top #[clap(long, requires("floating"))] pinned: Option, + #[clap( + long, + conflicts_with("floating"), + conflicts_with("direction"), + value_parser, + default_value("false"), + takes_value(false) + )] + stacked: bool, }, /// Load a plugin #[clap(visible_alias = "p")] @@ -602,6 +611,15 @@ pub enum CliAction { /// Whether to pin a floating pane so that it is always on top #[clap(long, requires("floating"))] pinned: Option, + #[clap( + long, + conflicts_with("floating"), + conflicts_with("direction"), + value_parser, + default_value("false"), + takes_value(false) + )] + stacked: bool, }, /// Open the specified file in a new zellij pane with your default EDITOR Edit { diff --git a/zellij-utils/src/input/actions.rs b/zellij-utils/src/input/actions.rs index 7202f82f..38c46833 100644 --- a/zellij-utils/src/input/actions.rs +++ b/zellij-utils/src/input/actions.rs @@ -180,6 +180,8 @@ pub enum Action { /// Open a new pane in place of the focused one, suppressing it instead NewInPlacePane(Option, Option), // String is an // optional pane + NewStackedPane(Option, Option), // String is an + // optional pane // name /// Embed focused pane in tab if floating or float focused pane if embedded TogglePaneEmbedOrFloating, @@ -362,6 +364,7 @@ impl Action { width, height, pinned, + stacked, } => { let current_dir = get_current_dir(); // cwd should only be specified in a plugin alias if it was explicitly given to us, @@ -443,6 +446,8 @@ impl Action { )]) } else if in_place { Ok(vec![Action::NewInPlacePane(Some(run_command_action), name)]) + } else if stacked { + Ok(vec![Action::NewStackedPane(Some(run_command_action), name)]) } else { Ok(vec![Action::NewTiledPane( direction, @@ -459,6 +464,8 @@ impl Action { )]) } else if in_place { Ok(vec![Action::NewInPlacePane(None, name)]) + } else if stacked { + Ok(vec![Action::NewStackedPane(None, name)]) } else { Ok(vec![Action::NewTiledPane(direction, None, name)]) } diff --git a/zellij-utils/src/kdl/mod.rs b/zellij-utils/src/kdl/mod.rs index 09b6d957..724f52be 100644 --- a/zellij-utils/src/kdl/mod.rs +++ b/zellij-utils/src/kdl/mod.rs @@ -534,6 +534,8 @@ impl Action { "NewPane" => { if string.is_empty() { return Ok(Action::NewPane(None, None, false)); + } else if string == "stacked" { + return Ok(Action::NewStackedPane(None, None)); } else { let direction = Direction::from_str(string.as_str()).map_err(|_| { ConfigError::new_kdl_error( @@ -911,6 +913,48 @@ impl Action { } Some(node) }, + Action::NewStackedPane(run_command_action, name) => match run_command_action { + Some(run_command_action) => { + let mut node = KdlNode::new("Run"); + let mut node_children = KdlDocument::new(); + node.push(run_command_action.command.display().to_string()); + for arg in &run_command_action.args { + node.push(arg.clone()); + } + let mut stacked_node = KdlNode::new("stacked"); + stacked_node.push(KdlValue::Bool(true)); + node_children.nodes_mut().push(stacked_node); + if let Some(cwd) = &run_command_action.cwd { + let mut cwd_node = KdlNode::new("cwd"); + cwd_node.push(cwd.display().to_string()); + node_children.nodes_mut().push(cwd_node); + } + if run_command_action.hold_on_start { + let mut hos_node = KdlNode::new("hold_on_start"); + hos_node.push(KdlValue::Bool(true)); + node_children.nodes_mut().push(hos_node); + } + if !run_command_action.hold_on_close { + let mut hoc_node = KdlNode::new("hold_on_close"); + hoc_node.push(KdlValue::Bool(false)); + node_children.nodes_mut().push(hoc_node); + } + if let Some(name) = name { + let mut name_node = KdlNode::new("name"); + name_node.push(name.clone()); + node_children.nodes_mut().push(name_node); + } + if !node_children.nodes().is_empty() { + node.set_children(node_children); + } + Some(node) + }, + None => { + let mut node = KdlNode::new("NewPane"); + node.push("stacked"); + Some(node) + }, + }, Action::Detach => Some(KdlNode::new("Detach")), Action::LaunchOrFocusPlugin( run_plugin_or_alias, @@ -1557,6 +1601,9 @@ impl TryFrom<(&KdlNode, &Options)> for Action { let in_place = command_metadata .and_then(|c_m| kdl_child_bool_value_for_entry(c_m, "in_place")) .unwrap_or(false); + let stacked = command_metadata + .and_then(|c_m| kdl_child_bool_value_for_entry(c_m, "stacked")) + .unwrap_or(false); let run_command_action = RunCommandAction { command: PathBuf::from(command), args, @@ -1588,6 +1635,8 @@ impl TryFrom<(&KdlNode, &Options)> for Action { )) } else if in_place { Ok(Action::NewInPlacePane(Some(run_command_action), name)) + } else if stacked { + Ok(Action::NewStackedPane(Some(run_command_action), name)) } else { Ok(Action::NewTiledPane( direction, diff --git a/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__bare_config_from_default_assets_to_string.snap b/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__bare_config_from_default_assets_to_string.snap index b4f43c49..11f6e53d 100644 --- a/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__bare_config_from_default_assets_to_string.snap +++ b/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__bare_config_from_default_assets_to_string.snap @@ -24,6 +24,7 @@ keybinds clear-defaults=true { bind "p" { SwitchFocus; } bind "Ctrl p" { SwitchToMode "normal"; } bind "r" { NewPane "right"; SwitchToMode "normal"; } + bind "s" { NewPane "stacked"; SwitchToMode "normal"; } bind "w" { ToggleFloatingPanes; SwitchToMode "normal"; } bind "z" { TogglePaneFrames; SwitchToMode "normal"; } } diff --git a/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__bare_config_from_default_assets_to_string_with_comments.snap b/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__bare_config_from_default_assets_to_string_with_comments.snap index e8770241..7e26e85c 100644 --- a/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__bare_config_from_default_assets_to_string_with_comments.snap +++ b/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__bare_config_from_default_assets_to_string_with_comments.snap @@ -24,6 +24,7 @@ keybinds clear-defaults=true { bind "p" { SwitchFocus; } bind "Ctrl p" { SwitchToMode "normal"; } bind "r" { NewPane "right"; SwitchToMode "normal"; } + bind "s" { NewPane "stacked"; SwitchToMode "normal"; } bind "w" { ToggleFloatingPanes; SwitchToMode "normal"; } bind "z" { TogglePaneFrames; SwitchToMode "normal"; } } diff --git a/zellij-utils/src/plugin_api/action.proto b/zellij-utils/src/plugin_api/action.proto index 40a6481f..5bdd34e9 100644 --- a/zellij-utils/src/plugin_api/action.proto +++ b/zellij-utils/src/plugin_api/action.proto @@ -243,6 +243,7 @@ enum ActionName { MouseEvent = 86; TogglePaneInGroup = 87; ToggleGroupMarking = 88; + NewStackedPane = 89; } message Position { diff --git a/zellij-utils/src/plugin_api/action.rs b/zellij-utils/src/plugin_api/action.rs index 857bb385..d018ea1b 100644 --- a/zellij-utils/src/plugin_api/action.rs +++ b/zellij-utils/src/plugin_api/action.rs @@ -720,6 +720,10 @@ impl TryFrom for Action { plugin_id: None, }), }, + Some(ProtobufActionName::NewStackedPane) => match protobuf_action.optional_payload { + Some(_) => Err("NewStackedPane should not have a payload"), + None => Ok(Action::NewStackedPane(None, None)), + }, _ => Err("Unknown Action"), } } @@ -1254,6 +1258,10 @@ impl TryFrom for ProtobufAction { name: ProtobufActionName::ToggleGroupMarking as i32, optional_payload: None, }), + Action::NewStackedPane(..) => Ok(ProtobufAction { + name: ProtobufActionName::NewStackedPane as i32, + optional_payload: None, + }), Action::NoOp | Action::Confirm | Action::NewInPlacePane(..) 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 c29499cb..3dc47894 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 @@ -1339,6 +1339,20 @@ Config { Normal, ), ], + KeyWithModifier { + bare_key: Char( + 's', + ), + key_modifiers: {}, + }: [ + NewStackedPane( + None, + None, + ), + SwitchToMode( + Normal, + ), + ], KeyWithModifier { bare_key: Char( 's', 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 f92ee67f..f1f79aa4 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 @@ -1339,6 +1339,20 @@ Config { Normal, ), ], + KeyWithModifier { + bare_key: Char( + 's', + ), + key_modifiers: {}, + }: [ + NewStackedPane( + None, + None, + ), + SwitchToMode( + Normal, + ), + ], KeyWithModifier { bare_key: Char( 's', diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap index 2a416240..92fa7f7f 100644 --- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap +++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap @@ -1339,6 +1339,20 @@ Config { Normal, ), ], + KeyWithModifier { + bare_key: Char( + 's', + ), + key_modifiers: {}, + }: [ + NewStackedPane( + None, + None, + ), + SwitchToMode( + Normal, + ), + ], KeyWithModifier { bare_key: Char( 's', diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap index 766e7348..391cbea5 100644 --- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap +++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap @@ -1339,6 +1339,20 @@ Config { Normal, ), ], + KeyWithModifier { + bare_key: Char( + 's', + ), + key_modifiers: {}, + }: [ + NewStackedPane( + None, + None, + ), + SwitchToMode( + Normal, + ), + ], KeyWithModifier { bare_key: Char( 's',