diff options
| author | DawidPietrykowski <53954695+DawidPietrykowski@users.noreply.github.com> | 2026-06-25 18:12:51 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-06-25 18:12:51 +0200 |
| commit | ebd731b0ff12737a6e2160a255280534ef3991bd (patch) | |
| tree | 4313963a269205391aa519fd090ea1de2b7cc4af /zellij-utils/src | |
| parent | tests: add more integration tests (#5308) (diff) | |
| download | sl0ppij-ebd731b0ff12737a6e2160a255280534ef3991bd.tar.gz sl0ppij-ebd731b0ff12737a6e2160a255280534ef3991bd.tar.xz sl0ppij-ebd731b0ff12737a6e2160a255280534ef3991bd.zip | |
feat(panes): `FocusLastPane` action (#4241)
* feat(panes): focus last pane (#4142)
* add tests
* add client id parameter to `add_floating_pane`
* add action for floating panes
* add tests for floating panes
* add keybinds to configs
* rebase fixes
* simplify focus logic when adding stacked pane
* formatting fix
* formatting fix 2
* fix: make sure expanding pane always focuses it for all clients in stack
* add pr
* fix rebase
---------
Co-authored-by: Aram Drevekenin <aram@poor.dev>
Diffstat (limited to 'zellij-utils/src')
| -rw-r--r-- | zellij-utils/src/cli.rs | 2 | ||||
| -rw-r--r-- | zellij-utils/src/client_server_contract/common_types.proto | 2 | ||||
| -rw-r--r-- | zellij-utils/src/data.rs | 1 | ||||
| -rw-r--r-- | zellij-utils/src/errors.rs | 1 | ||||
| -rw-r--r-- | zellij-utils/src/input/actions.rs | 3 | ||||
| -rw-r--r-- | zellij-utils/src/ipc/protobuf_conversion.rs | 5 | ||||
| -rw-r--r-- | zellij-utils/src/kdl/mod.rs | 6 | ||||
| -rw-r--r-- | zellij-utils/src/kdl/snapshots/zellij_utils__kdl__keybinds_to_string_with_all_actions.snap | 3 | ||||
| -rw-r--r-- | zellij-utils/src/plugin_api/action.proto | 1 | ||||
| -rw-r--r-- | zellij-utils/src/plugin_api/action.rs | 8 | ||||
| -rw-r--r-- | zellij-utils/src/plugin_api/plugin_command.proto | 1 | ||||
| -rw-r--r-- | zellij-utils/src/plugin_api/plugin_command.rs | 10 |
12 files changed, 41 insertions, 2 deletions
diff --git a/zellij-utils/src/cli.rs b/zellij-utils/src/cli.rs index 5b169170..a00c4d05 100644 --- a/zellij-utils/src/cli.rs +++ b/zellij-utils/src/cli.rs @@ -765,6 +765,8 @@ pub enum CliAction { /// The pane_id of the pane, eg. terminal_1, plugin_2 or 3 pane_id: String, }, + /// Change focus to the last focused frame + FocusLastPane, /// Move the focused pane in the specified direction. [right|left|up|down] MoveFocus { direction: Direction, diff --git a/zellij-utils/src/client_server_contract/common_types.proto b/zellij-utils/src/client_server_contract/common_types.proto index 1dfc3994..718cc279 100644 --- a/zellij-utils/src/client_server_contract/common_types.proto +++ b/zellij-utils/src/client_server_contract/common_types.proto @@ -278,6 +278,7 @@ message Action { SetLightThemeAction set_light_theme = 138; ToggleThemeAction toggle_theme = 139; ToggleMobileModeAction toggle_mobile_mode = 140; + FocusLastPaneAction focus_last_pane = 141; } } @@ -287,6 +288,7 @@ message Action { message QuitAction {} message FocusNextPaneAction {} message FocusPreviousPaneAction {} +message FocusLastPaneAction {} message SwitchFocusAction {} message MovePaneBackwardsAction {} message ClearScreenAction {} diff --git a/zellij-utils/src/data.rs b/zellij-utils/src/data.rs index 16ff560e..c11f777f 100644 --- a/zellij-utils/src/data.rs +++ b/zellij-utils/src/data.rs @@ -3384,6 +3384,7 @@ pub enum PluginCommand { ResizeWithDirection(ResizeStrategy), FocusNextPane, FocusPreviousPane, + FocusLastPane, MoveFocus(Direction), MoveFocusOrTab(Direction), Detach, diff --git a/zellij-utils/src/errors.rs b/zellij-utils/src/errors.rs index 8e4bc66c..c9e8e25f 100644 --- a/zellij-utils/src/errors.rs +++ b/zellij-utils/src/errors.rs @@ -246,6 +246,7 @@ pub enum ScreenContext { SwitchFocus, FocusNextPane, FocusPreviousPane, + FocusLastPane, FocusPaneAt, MoveFocusLeft, MoveFocusLeftOrPreviousTab, diff --git a/zellij-utils/src/input/actions.rs b/zellij-utils/src/input/actions.rs index cf5fc448..40158b8b 100644 --- a/zellij-utils/src/input/actions.rs +++ b/zellij-utils/src/input/actions.rs @@ -158,6 +158,8 @@ pub enum Action { /// Switch focus to next pane in specified direction. FocusNextPane, FocusPreviousPane, + /// Switch focus to the last focused pane. + FocusLastPane, /// Move the focus pane in specified direction. SwitchFocus, MoveFocus { @@ -828,6 +830,7 @@ impl Action { ))?; Ok(vec![Action::FocusPaneByPaneId { pane_id }]) }, + CliAction::FocusLastPane => Ok(vec![Action::FocusLastPane]), CliAction::MoveFocus { direction } => Ok(vec![Action::MoveFocus { direction }]), CliAction::MoveFocusOrTab { direction } => { Ok(vec![Action::MoveFocusOrTab { direction }]) diff --git a/zellij-utils/src/ipc/protobuf_conversion.rs b/zellij-utils/src/ipc/protobuf_conversion.rs index d1bfb7d4..c4941676 100644 --- a/zellij-utils/src/ipc/protobuf_conversion.rs +++ b/zellij-utils/src/ipc/protobuf_conversion.rs @@ -915,6 +915,7 @@ impl From<crate::input::actions::Action> EditFileAction, EditScrollbackAction, EditScrollbackByPaneIdAction, + FocusLastPaneAction, FocusNextPaneAction, FocusPaneByPaneIdAction, FocusPluginPaneWithIdAction, @@ -1090,6 +1091,9 @@ impl From<crate::input::actions::Action> crate::input::actions::Action::FocusPreviousPane => { ActionType::FocusPreviousPane(FocusPreviousPaneAction {}) }, + crate::input::actions::Action::FocusLastPane => { + ActionType::FocusLastPane(FocusLastPaneAction {}) + }, crate::input::actions::Action::SwitchFocus => { ActionType::SwitchFocus(SwitchFocusAction {}) }, @@ -1961,6 +1965,7 @@ impl TryFrom<crate::client_server_contract::client_server_contract::Action> ActionType::FocusPreviousPane(_) => { Ok(crate::input::actions::Action::FocusPreviousPane) }, + ActionType::FocusLastPane(_) => Ok(crate::input::actions::Action::FocusLastPane), ActionType::SwitchFocus(_) => Ok(crate::input::actions::Action::SwitchFocus), ActionType::MoveFocus(move_focus_action) => { Ok(crate::input::actions::Action::MoveFocus { diff --git a/zellij-utils/src/kdl/mod.rs b/zellij-utils/src/kdl/mod.rs index 0164ef92..14695f68 100644 --- a/zellij-utils/src/kdl/mod.rs +++ b/zellij-utils/src/kdl/mod.rs @@ -48,6 +48,7 @@ macro_rules! parse_kdl_action_arguments { "Quit" => Ok(Action::Quit), "FocusNextPane" => Ok(Action::FocusNextPane), "FocusPreviousPane" => Ok(Action::FocusPreviousPane), + "FocusLastPane" => Ok(Action::FocusLastPane), "SwitchFocus" => Ok(Action::SwitchFocus), "EditScrollback" => Ok(Action::EditScrollback { ansi: false }), "ScrollUp" => Ok(Action::ScrollUp), @@ -660,6 +661,7 @@ impl Action { }, Action::FocusNextPane => Some(KdlNode::new("FocusNextPane")), Action::FocusPreviousPane => Some(KdlNode::new("FocusPreviousPane")), + Action::FocusLastPane => Some(KdlNode::new("FocusLastPane")), Action::SwitchFocus => Some(KdlNode::new("SwitchFocus")), Action::MoveFocus { direction } => { let mut node = KdlNode::new("MoveFocus"); @@ -1512,6 +1514,9 @@ impl TryFrom<(&KdlNode, &Options)> for Action { "FocusPreviousPane" => { parse_kdl_action_arguments!(action_name, action_arguments, kdl_action) }, + "FocusLastPane" => { + parse_kdl_action_arguments!(action_name, action_arguments, kdl_action) + }, "SwitchFocus" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action), "EditScrollback" => { let ansi = crate::kdl_get_bool_property_or_child_value!(kdl_action, "ansi") @@ -6729,6 +6734,7 @@ fn keybinds_to_string_with_all_actions() { config_key_2 "config_value_2"; }; } + bind "Ctrl Alt k" { FocusLastPane; } } }"#; let document: KdlDocument = fake_config.parse().unwrap(); diff --git a/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__keybinds_to_string_with_all_actions.snap b/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__keybinds_to_string_with_all_actions.snap index 43e85faa..b0119a63 100644 --- a/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__keybinds_to_string_with_all_actions.snap +++ b/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__keybinds_to_string_with_all_actions.snap @@ -1,6 +1,5 @@ --- source: zellij-utils/src/kdl/mod.rs -assertion_line: 2731 expression: serialized.to_string() --- keybinds clear-defaults=true { @@ -47,6 +46,7 @@ keybinds clear-defaults=true { } bind "Alt j" { GoToPreviousTab; } bind "Ctrl k" { MovePane "right"; } + bind "Ctrl Alt k" { FocusLastPane; } bind "Alt k" { CloseTab; } bind "Ctrl l" { MovePaneBackwards; } bind "Alt l" { GoToTab 1; } @@ -127,4 +127,3 @@ keybinds clear-defaults=true { bind "Alt z" { SearchInput 0; } } } - diff --git a/zellij-utils/src/plugin_api/action.proto b/zellij-utils/src/plugin_api/action.proto index 7eedf393..68c859b8 100644 --- a/zellij-utils/src/plugin_api/action.proto +++ b/zellij-utils/src/plugin_api/action.proto @@ -493,6 +493,7 @@ enum ActionName { SetDarkTheme = 101; SetLightTheme = 102; ToggleTheme = 103; + FocusLastPane = 104; } message Position { diff --git a/zellij-utils/src/plugin_api/action.rs b/zellij-utils/src/plugin_api/action.rs index 34b3adce..f4e35d84 100644 --- a/zellij-utils/src/plugin_api/action.rs +++ b/zellij-utils/src/plugin_api/action.rs @@ -168,6 +168,10 @@ impl TryFrom<ProtobufAction> for Action { Some(_) => Err("FocusPreviousPane should not have a payload"), None => Ok(Action::FocusPreviousPane), }, + Some(ProtobufActionName::FocusLastPane) => match protobuf_action.optional_payload { + Some(_) => Err("FocusLastPane should not have a payload"), + None => Ok(Action::FocusLastPane), + }, Some(ProtobufActionName::SwitchFocus) => match protobuf_action.optional_payload { Some(_) => Err("SwitchFocus should not have a payload"), None => Ok(Action::SwitchFocus), @@ -1173,6 +1177,10 @@ impl TryFrom<Action> for ProtobufAction { name: ProtobufActionName::FocusPreviousPane as i32, optional_payload: None, }), + Action::FocusLastPane => Ok(ProtobufAction { + name: ProtobufActionName::FocusLastPane as i32, + optional_payload: None, + }), Action::SwitchFocus => Ok(ProtobufAction { name: ProtobufActionName::SwitchFocus as i32, optional_payload: None, diff --git a/zellij-utils/src/plugin_api/plugin_command.proto b/zellij-utils/src/plugin_api/plugin_command.proto index c65bcbfd..82f4d835 100644 --- a/zellij-utils/src/plugin_api/plugin_command.proto +++ b/zellij-utils/src/plugin_api/plugin_command.proto @@ -213,6 +213,7 @@ enum CommandName { NewTabUnfocused = 220; NewTiledPaneInTab = 221; ExitMobileMode = 222; + FocusLastPane = 223; } message PluginCommand { diff --git a/zellij-utils/src/plugin_api/plugin_command.rs b/zellij-utils/src/plugin_api/plugin_command.rs index 42b0774f..546c3586 100644 --- a/zellij-utils/src/plugin_api/plugin_command.rs +++ b/zellij-utils/src/plugin_api/plugin_command.rs @@ -980,6 +980,12 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand { } Ok(PluginCommand::FocusPreviousPane) }, + Some(CommandName::FocusLastPane) => { + if protobuf_plugin_command.payload.is_some() { + return Err("FocusLastPane should not have a payload"); + } + Ok(PluginCommand::FocusLastPane) + }, Some(CommandName::MoveFocus) => match protobuf_plugin_command.payload { Some(Payload::MoveFocusPayload(move_payload)) => match move_payload.direction { Some(direction) => Ok(PluginCommand::MoveFocus(direction.try_into()?)), @@ -3005,6 +3011,10 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand { name: CommandName::FocusPreviousPane as i32, payload: None, }), + PluginCommand::FocusLastPane => Ok(ProtobufPluginCommand { + name: CommandName::FocusLastPane as i32, + payload: None, + }), PluginCommand::MoveFocus(direction) => Ok(ProtobufPluginCommand { name: CommandName::MoveFocus as i32, payload: Some(Payload::MoveFocusPayload(MovePayload { |
