diff options
| author | Aram Drevekenin <aram@poor.dev> | 2025-12-23 13:41:56 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-12-23 13:41:56 +0100 |
| commit | 3fe48a972c55537502128779116d38d8f8aedb7e (patch) | |
| tree | 350386442db2a46e1d8ba3d9d4dd0c7d53b34c13 /zellij-utils/src/plugin_api | |
| parent | Read only web tokens (#4551) (diff) | |
| download | sl0ppij-3fe48a972c55537502128779116d38d8f8aedb7e.tar.gz sl0ppij-3fe48a972c55537502128779116d38d8f8aedb7e.tar.xz sl0ppij-3fe48a972c55537502128779116d38d8f8aedb7e.zip | |
Feature: allow overriding a layout for a currently running tab (change layout at runtime) (#4566)
* add tests for LayoutApplier
* initial untested implementation of override functions
* add override-layout cli action with stub in screen
* filter run instructions to ignore
* implement override-layout roundtrip through plugin and pty threads
* initial full-cycle working override implementation
* fix some bugs (eg. actually start new terminals)
* fix some bugs with focus after override
* fix floating pane matching bug in layout applier
* formatting
* use first tab, error on more than 1 tab
* fix some floating_panes ordering and shell issues
* get new tab name to work
* respect swap layouts
* allow specifying tab properties on main layout node if we just have one tab
* add tests for new override methods
* start work on retaining panes, hard-coded things, kind of working but broken in many places
* fixed most tiled pane override bugs
* reset viewport before reapplying
* revert constraint system changes
* retain-existing-terminal-panes flag
* add retain terminal panes tests
* add retain plugin panes flag
* add keybind
* add retain plugin panes tests
* add override-layout e2e test
* refactor: layout_applier
* style: rustfmt
* some cleanups
* fix cli flags
* no crashy
* formatting and artifacts
* moar cleanups
* fix: respect expanded in stack when overriding
* docs(changelog): add PR
Diffstat (limited to 'zellij-utils/src/plugin_api')
| -rw-r--r-- | zellij-utils/src/plugin_api/action.proto | 12 | ||||
| -rw-r--r-- | zellij-utils/src/plugin_api/action.rs | 101 |
2 files changed, 113 insertions, 0 deletions
diff --git a/zellij-utils/src/plugin_api/action.proto b/zellij-utils/src/plugin_api/action.proto index c29884af..de8ef44f 100644 --- a/zellij-utils/src/plugin_api/action.proto +++ b/zellij-utils/src/plugin_api/action.proto @@ -162,6 +162,16 @@ message NewTabPayload { optional UnblockCondition first_pane_unblock_condition = 9; } +message OverrideLayoutPayload { + optional TiledPaneLayout tiled_layout = 1; + repeated FloatingPaneLayout floating_layouts = 2; + repeated SwapTiledLayout swap_tiled_layouts = 3; + repeated SwapFloatingLayout swap_floating_layouts = 4; + optional string tab_name = 5; + bool retain_existing_terminal_panes = 10; + bool retain_existing_plugin_panes = 11; +} + message Action { ActionName name = 1; oneof optional_payload { @@ -213,6 +223,7 @@ message Action { NewBlockingPanePayload new_blocking_pane_payload = 50; NewTabPayload new_tab_payload = 51; NewInPlacePanePayload new_in_place_pane_payload = 52; + OverrideLayoutPayload override_layout_payload = 53; } } @@ -429,6 +440,7 @@ enum ActionName { SwitchSession = 90; NewBlockingPane = 91; NewInPlacePane = 92; + OverrideLayout = 93; } message Position { diff --git a/zellij-utils/src/plugin_api/action.rs b/zellij-utils/src/plugin_api/action.rs index f8de7b76..860b090b 100644 --- a/zellij-utils/src/plugin_api/action.rs +++ b/zellij-utils/src/plugin_api/action.rs @@ -37,6 +37,7 @@ pub use super::generated_api::api::{ NewPluginPanePayload, NewTabPayload, NewTiledPanePayload, + OverrideLayoutPayload, PaneId as ProtobufPaneId, PaneIdAndShouldFloat, PaneRun as ProtobufPaneRun, @@ -720,6 +721,55 @@ impl TryFrom<ProtobufAction> for Action { Some(_) => Err("NextSwapLayout should not have a payload"), None => Ok(Action::NextSwapLayout), }, + Some(ProtobufActionName::OverrideLayout) => match protobuf_action.optional_payload { + Some(OptionalPayload::OverrideLayoutPayload(payload)) => { + let tiled_layout = payload.tiled_layout.map(|l| l.try_into()).transpose()?; + + let floating_layouts = payload + .floating_layouts + .into_iter() + .map(|l| l.try_into()) + .collect::<Result<Vec<_>, _>>()?; + + let swap_tiled_layouts = if payload.swap_tiled_layouts.is_empty() { + None + } else { + Some( + payload + .swap_tiled_layouts + .into_iter() + .map(|l| l.try_into()) + .collect::<Result<Vec<_>, _>>()?, + ) + }; + + let swap_floating_layouts = if payload.swap_floating_layouts.is_empty() { + None + } else { + Some( + payload + .swap_floating_layouts + .into_iter() + .map(|l| l.try_into()) + .collect::<Result<Vec<_>, _>>()?, + ) + }; + + let tab_name = payload.tab_name.filter(|s| !s.is_empty()); + + Ok(Action::OverrideLayout { + tiled_layout, + floating_layouts, + swap_tiled_layouts, + swap_floating_layouts, + tab_name, + retain_existing_terminal_panes: payload.retain_existing_terminal_panes, + retain_existing_plugin_panes: payload.retain_existing_plugin_panes, + }) + }, + Some(_) => Err("Mismatched payload for OverrideLayout"), + None => Err("Missing payload for OverrideLayout"), + }, Some(ProtobufActionName::QueryTabNames) => match protobuf_action.optional_payload { Some(_) => Err("QueryTabNames should not have a payload"), None => Ok(Action::QueryTabNames), @@ -1505,6 +1555,57 @@ impl TryFrom<Action> for ProtobufAction { name: ProtobufActionName::NextSwapLayout as i32, optional_payload: None, }), + Action::OverrideLayout { + tiled_layout, + floating_layouts, + swap_tiled_layouts, + swap_floating_layouts, + tab_name, + retain_existing_terminal_panes, + retain_existing_plugin_panes, + } => { + let protobuf_tiled_layout = tiled_layout.map(|l| l.try_into()).transpose()?; + + let protobuf_floating_layouts = floating_layouts + .into_iter() + .map(|l| l.try_into()) + .collect::<Result<Vec<_>, _>>()?; + + let protobuf_swap_tiled_layouts = swap_tiled_layouts + .map(|layouts| { + layouts + .into_iter() + .map(|l| l.try_into()) + .collect::<Result<Vec<_>, _>>() + }) + .transpose()? + .unwrap_or_default(); + + let protobuf_swap_floating_layouts = swap_floating_layouts + .map(|layouts| { + layouts + .into_iter() + .map(|l| l.try_into()) + .collect::<Result<Vec<_>, _>>() + }) + .transpose()? + .unwrap_or_default(); + + Ok(ProtobufAction { + name: ProtobufActionName::OverrideLayout as i32, + optional_payload: Some(OptionalPayload::OverrideLayoutPayload( + OverrideLayoutPayload { + tiled_layout: protobuf_tiled_layout, + floating_layouts: protobuf_floating_layouts, + swap_tiled_layouts: protobuf_swap_tiled_layouts, + swap_floating_layouts: protobuf_swap_floating_layouts, + tab_name: tab_name.clone(), + retain_existing_terminal_panes, + retain_existing_plugin_panes, + }, + )), + }) + }, Action::QueryTabNames => Ok(ProtobufAction { name: ProtobufActionName::QueryTabNames as i32, optional_payload: None, |
