aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoruser <user@clank>2026-08-12 15:18:33 +0200
committeruser <user@clank>2026-08-12 15:18:33 +0200
commit549f052ae5451d57b58f5de22de57b2a586e6d23 (patch)
treeb24bb9565eac6b068886328afbf0644d25b53e82
parentsl0p: serialise the pane status bar for resurrection (diff)
downloadsl0ppij-549f052ae5451d57b58f5de22de57b2a586e6d23.tar.gz
sl0ppij-549f052ae5451d57b58f5de22de57b2a586e6d23.tar.xz
sl0ppij-549f052ae5451d57b58f5de22de57b2a586e6d23.zip
sl0p: clickable action buttons in the pane status bar
Second slice of the status/action frame. A program declares buttons, and a click is reported back to it: printf '\033]5577;1;buttons;approve:Approve;reject:Reject\033\\' -> click -> program's stdin receives OSC 5577 ; 1 ; click ; approve ST The report is a FIXED format carrying only the id, never bytes the payload chose, and ids are restricted to [A-Za-z0-9_-]. The sequence that creates a button is in-band and untrusted -- `cat` of a hostile file emits it as readily as a cooperating program -- so a click that could send arbitrary bytes would let viewing a file inject into the stdin of whatever is running, a shell included. Labels are '%'-escaped since the wire format is ';'-separated, and both the button count and id length are capped because the list lives as long as the pane. Positions come from one layout_status_bar function that the renderer draws from and the hit-test resolves against. Computing that geometry twice is how the stacked-pane picker once selected the wrong pane; a test asserts every drawn column resolves back to the button drawn there, across 100 widths. Two things the drive caught that unit tests could not: - The first delivery path pushed onto grid.pending_messages_to_pty, which is only drained when the PANE produces output -- so a click on an idle program sat in the queue forever. The write now happens at the tab level, which owns the senders. - The hit-test derived the frame row from the pane's raw geometry, but this fork draws the frame inset by gap_offset, so with `gap 1` every click missed by one row. It now derives from the CONTENT rect, which is by definition the inside of the drawn frame and therefore the same columns the renderer lays out. Buttons serialise with the session like the status text, so a resurrected pane comes back with its buttons intact.
-rw-r--r--README.md19
-rw-r--r--zellij-server/src/panes/grid.rs24
-rw-r--r--zellij-server/src/panes/terminal_pane.rs54
-rw-r--r--zellij-server/src/panes/unit/grid_tests.rs77
-rw-r--r--zellij-server/src/screen.rs8
-rw-r--r--zellij-server/src/session_layout_metadata.rs6
-rw-r--r--zellij-server/src/tab/layout_applier.rs5
-rw-r--r--zellij-server/src/tab/mod.rs8
-rw-r--r--zellij-server/src/tab/mouse_handler.rs34
-rw-r--r--zellij-server/src/ui/pane_boundaries_frame.rs74
-rw-r--r--zellij-server/src/ui/pane_contents_and_ui.rs2
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_default_params.snap3
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_with_layout_string.snap4
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_with_layout_string_and_name.snap4
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_with_name_and_layout.snap4
-rw-r--r--zellij-utils/src/input/layout.rs190
-rw-r--r--zellij-utils/src/input/unit/layout_test.rs118
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__args_added_to_args_in_template.snap3
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__args_override_args_in_template.snap3
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__can_define_a_stack_with_an_expanded_pane.snap5
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__can_define_stacked_children_for_pane_node.snap4
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__can_define_stacked_children_for_pane_template.snap5
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__can_load_swap_layouts_from_a_different_file.snap36
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__children_not_as_first_child_of_pane_template.snap12
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__children_not_as_first_child_of_tab_template.snap12
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__close_on_exit_added_to_close_on_exit_in_template.snap3
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__close_on_exit_overrides_close_on_exit_in_template.snap3
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__combined_tab_and_pane_template_both_with_children.snap17
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__cwd_added_to_cwd_in_template.snap3
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__cwd_override_cwd_in_template.snap3
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__env_var_expansion.snap20
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_and_tab_cwd_prepended_to_panes_with_and_without_cwd.snap4
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_and_tab_cwd_prepended_to_panes_with_and_without_cwd_in_pane_templates.snap7
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_and_tab_cwd_prepended_to_panes_with_and_without_cwd_in_tab_templates.snap6
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_given_to_panes_without_cwd.snap6
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_passed_from_layout_constructor.snap3
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_passed_from_layout_constructor_overrides_global_cwd_in_layout_file.snap6
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_prepended_to_panes_with_cwd.snap6
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_with_tab_cwd_given_to_panes_without_cwd.snap4
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_command_panes_and_close_on_exit.snap2
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_command_panes_and_start_suspended.snap2
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_default_tab_template.snap20
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_nested_branched_pane_templates.snap11
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_nested_pane_templates.snap8
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_new_tab_template.snap11
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_pane_excluded_from_sync.snap2
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_pane_templates.snap22
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_tab_and_pane_templates.snap7
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_tabs_and_floating_panes.snap5
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_with_cwd_is_overriden_by_its_consumers_bare_cwd.snap4
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_with_cwd_overriden_by_its_consumers_command_cwd.snap4
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_with_cwd_remains_when_its_consumer_command_does_not_have_a_cwd.snap4
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_without_cwd_is_overriden_by_its_consumers_cwd.snap4
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_without_cwd_receives_its_consumers_bare_cwd.snap4
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_bare_cwd_overriden_by_its_consumers_bare_cwd.snap4
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_bare_propagated_to_its_consumer_command_with_cwd.snap4
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_bare_propagated_to_its_consumer_command_without_cwd.snap4
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_bare_propagated_to_its_consumer_edit.snap4
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_command_propagated_to_its_consumer_edit.snap4
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__tab_cwd_given_to_panes_without_cwd.snap4
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__tab_cwd_prepended_to_panes_with_cwd.snap4
-rw-r--r--zellij-utils/src/ipc/protobuf_conversion.rs1
-rw-r--r--zellij-utils/src/kdl/kdl_layout_parser.rs5
-rw-r--r--zellij-utils/src/plugin_api/action.rs1
-rw-r--r--zellij-utils/src/session_serialization.rs11
65 files changed, 928 insertions, 33 deletions
diff --git a/README.md b/README.md
index d2e1f6a8..dbc22e54 100644
--- a/README.md
+++ b/README.md
@@ -322,14 +322,27 @@ accepting them.
A program can put one row of its own text in its pane's bottom frame row:
```bash
-printf '\033]5577;1;status;building 3/7 · 12s elapsed\033\\' # set
-printf '\033]5577;1;clear\033\\' # remove
+printf '\033]5577;1;status;building 3/7 · 12s elapsed\033\\' # text
+printf '\033]5577;1;buttons;approve:Approve;reject:Reject\033\\' # buttons
+printf '\033]5577;1;clear\033\\' # remove both
```
```
-╰ building 3/7 · 12s elapsed ─────────────────────────────╯
+╰ awaiting review ──────────────────────────[Approve]─[Reject]╯
```
+Clicking a button writes a **fixed-format report** to the program's stdin:
+
+```
+OSC 5577 ; 1 ; click ; <id> ST
+```
+
+Button ids are restricted to `[A-Za-z0-9_-]` and labels are `%`-escaped on the
+wire (`%3B` for `;`). Positions come from one `layout_status_bar` function that
+both the renderer and the mouse hit-test read, so a button can never be drawn
+somewhere a click does not resolve. Buttons are right-aligned and get first call
+on the row: they are actionable, the text is informational and truncates.
+
Rendered **in the existing frame row**, not in reserved rows. Reserving a row
would shrink the pane's content area and so resize its PTY every time the bar
appeared or disappeared — firing SIGWINCH at the very program that asked for it.
diff --git a/zellij-server/src/panes/grid.rs b/zellij-server/src/panes/grid.rs
index b91fa2a7..40313f68 100644
--- a/zellij-server/src/panes/grid.rs
+++ b/zellij-server/src/panes/grid.rs
@@ -705,6 +705,8 @@ pub struct Grid {
/// OSC 5577. Persistent like `title` rather than drained, so it survives
/// re-renders, resizes and detach/reattach for as long as the pane lives.
pub status_bar: Option<String>,
+ /// Clickable buttons for this pane's status bar (OSC 5577 `buttons`).
+ pub status_bar_buttons: Vec<zellij_utils::input::layout::StatusBarButton>,
pub is_scrolled: bool,
pub link_handler: Rc<RefCell<LinkHandler>>,
pub ring_bell: bool,
@@ -1066,6 +1068,7 @@ impl Grid {
title_stack: vec![],
title: None,
status_bar: None,
+ status_bar_buttons: vec![],
changed_colors: None,
is_scrolled: false,
link_handler,
@@ -4107,8 +4110,14 @@ impl Perform for Grid {
// sl0p fork: per-pane status bar, rendered in the pane's bottom
// frame row.
//
- // OSC 5577 ; 1 ; status ; <text> set the text
- // OSC 5577 ; 1 ; clear remove it
+ // OSC 5577 ; 1 ; status ; <text> set the text
+ // OSC 5577 ; 1 ; buttons ; <id>:<label> ; ... set the buttons
+ // OSC 5577 ; 1 ; clear remove both
+ //
+ // Button labels are '%'-escaped because the wire format is
+ // ';'-separated; ids are restricted to [A-Za-z0-9_-] so a hostile
+ // payload cannot smuggle text into the click report we write to a
+ // program's stdin.
//
// Versioned from the start, and anything with an unknown version or
// verb is ignored, so later additions (buttons) cannot be
@@ -4133,8 +4142,19 @@ impl Perform for Grid {
let text = zellij_utils::input::layout::sanitize_status_bar_text(&text);
self.status_bar = if text.is_empty() { None } else { Some(text) };
},
+ Some(b"buttons") => {
+ let params: Vec<&str> = params[3..]
+ .iter()
+ .flat_map(|p| str::from_utf8(p))
+ .collect();
+ self.status_bar_buttons =
+ zellij_utils::input::layout::parse_status_bar_buttons(
+ params.into_iter(),
+ );
+ },
Some(b"clear") => {
self.status_bar = None;
+ self.status_bar_buttons.clear();
},
_ => {},
}
diff --git a/zellij-server/src/panes/terminal_pane.rs b/zellij-server/src/panes/terminal_pane.rs
index 59cb87a6..e663a314 100644
--- a/zellij-server/src/panes/terminal_pane.rs
+++ b/zellij-server/src/panes/terminal_pane.rs
@@ -19,6 +19,7 @@ use std::fmt::Debug;
use std::rc::Rc;
use std::time::{self, Instant};
use vte;
+use zellij_utils::input::layout::{layout_status_bar, StatusBarButton};
use zellij_utils::data::PaneContents;
use zellij_utils::input::command::RunCommand;
use zellij_utils::input::mouse::{MouseEvent, MouseEventType};
@@ -1244,6 +1245,54 @@ impl Pane for TerminalPane {
fn set_status_bar_text(&mut self, text: Option<String>) {
self.grid.status_bar = text;
}
+ fn status_bar_buttons(&self) -> Vec<StatusBarButton> {
+ self.grid.status_bar_buttons.clone()
+ }
+ /// Id of the status bar button at `position`, if any.
+ ///
+ /// Pure: the caller writes the report, because delivering it needs the tab's
+ /// senders. Pushing onto the grid's pending-messages queue looked tempting but
+ /// that queue is only drained when the PANE produces output, so a click on an
+ /// idle program would have sat there indefinitely.
+ ///
+ /// Derived from the CONTENT rect, not the pane's raw geometry.
+ ///
+ /// This fork draws the frame inset from the pane's allocated geometry by
+ /// `gap_offset`, so the raw geom's last row is not where the bottom border is
+ /// drawn -- with `gap 1` it was off by one and every click missed. The content
+ /// rect is by definition the inside of the drawn frame, which makes these the
+ /// same columns `render_status_bar_undertitle` lays out:
+ ///
+ /// bottom border row = content_y + content_rows
+ /// inner area = content_x .. content_x + content_cols
+ fn status_bar_button_at(&self, position: &Position) -> Option<String> {
+ if self.status_bar_is_empty() {
+ return None;
+ }
+ let inner_cols = self.get_content_columns();
+ if inner_cols == 0 {
+ return None;
+ }
+ let status_row = self.get_content_y() + self.get_content_rows();
+ if position.line() != status_row as isize {
+ return None;
+ }
+ let inner_start = self.get_content_x();
+ let column = position.column();
+ if column < inner_start || column >= inner_start + inner_cols {
+ return None;
+ }
+ layout_status_bar(
+ inner_cols,
+ self.grid.status_bar.as_deref(),
+ &self.grid.status_bar_buttons,
+ )
+ .button_at(column - inner_start)
+ .map(|id| id.to_owned())
+ }
+ fn set_status_bar_buttons(&mut self, buttons: Vec<StatusBarButton>) {
+ self.grid.status_bar_buttons = buttons;
+ }
fn stack_list_entry_label(&self) -> String {
// `hide_default_pane_names` does not reach current_title() any more, so
// this gets the "Pane #N" placeholder rather than an empty string. Kept
@@ -1458,7 +1507,10 @@ impl Pane for TerminalPane {
}
impl TerminalPane {
- /// True while nothing has named this pane, so its title is still the
+ fn status_bar_is_empty(&self) -> bool {
+ self.grid.status_bar.is_none() && self.grid.status_bar_buttons.is_empty()
+ }
+ /// True while nothing has named this pane, so its title is still the /// True while nothing has named this pane, so its title is still the
/// auto-generated "Pane #N". Inherent rather than part of the Pane trait:
/// only terminal panes have a placeholder title to hide.
fn has_placeholder_title(&self) -> bool {
diff --git a/zellij-server/src/panes/unit/grid_tests.rs b/zellij-server/src/panes/unit/grid_tests.rs
index ad85d142..3e5231d1 100644
--- a/zellij-server/src/panes/unit/grid_tests.rs
+++ b/zellij-server/src/panes/unit/grid_tests.rs
@@ -8414,3 +8414,80 @@ fn sl0p_osc_5577_text_is_length_capped() {
let len = grid.status_bar.as_deref().map(|t| t.chars().count()).unwrap_or(0);
assert!(len > 0 && len <= 512, "expected a capped length, got {}", len);
}
+
+#[test]
+fn sl0p_osc_5577_parses_buttons_and_clear_removes_both() {
+ let mut grid = grid_for_status_bar_tests();
+ feed(&mut grid, "\u{1b}]5577;1;status;waiting\u{1b}\\");
+ feed(
+ &mut grid,
+ "\u{1b}]5577;1;buttons;approve:Approve;reject:Reject\u{1b}\\",
+ );
+ let ids: Vec<&str> = grid
+ .status_bar_buttons
+ .iter()
+ .map(|b| b.id.as_str())
+ .collect();
+ let labels: Vec<&str> = grid
+ .status_bar_buttons
+ .iter()
+ .map(|b| b.label.as_str())
+ .collect();
+ assert_eq!(ids, vec!["approve", "reject"]);
+ assert_eq!(labels, vec!["Approve", "Reject"]);
+
+ feed(&mut grid, "\u{1b}]5577;1;clear\u{1b}\\");
+ assert!(grid.status_bar.is_none() && grid.status_bar_buttons.is_empty());
+}
+
+#[test]
+fn sl0p_osc_5577_button_labels_can_contain_escaped_separators() {
+ // The wire format is ';'-separated, so a label needs '%' escaping to carry
+ // one. Without this a label like "a;b" would silently become two buttons.
+ let mut grid = grid_for_status_bar_tests();
+ feed(&mut grid, "\u{1b}]5577;1;buttons;a:one%3Btwo\u{1b}\\");
+ assert_eq!(grid.status_bar_buttons.len(), 1);
+ assert_eq!(grid.status_bar_buttons[0].label, "one;two");
+}
+
+#[test]
+fn sl0p_osc_5577_rejects_unsafe_button_ids() {
+ // The id is echoed back into the program's stdin, so it must not be able to
+ // carry arbitrary text. A hostile sequence is emitted just as easily by `cat`
+ // of a file as by a cooperating program.
+ let mut grid = grid_for_status_bar_tests();
+ for hostile in [
+ "\u{1b}]5577;1;buttons;rm -rf /:Go\u{1b}\\",
+ "\u{1b}]5577;1;buttons;a$(id):Go\u{1b}\\",
+ "\u{1b}]5577;1;buttons;a;b:Go\u{1b}\\",
+ "\u{1b}]5577;1;buttons;:Go\u{1b}\\",
+ ] {
+ grid.status_bar_buttons.clear();
+ feed(&mut grid, hostile);
+ assert!(
+ grid.status_bar_buttons
+ .iter()
+ .all(|b| b.id.chars().all(|c| c.is_ascii_alphanumeric()
+ || c == '_'
+ || c == '-')),
+ "unsafe id accepted from {:?}: {:?}",
+ hostile,
+ grid.status_bar_buttons
+ );
+ }
+}
+
+#[test]
+fn sl0p_osc_5577_caps_the_number_of_buttons() {
+ let mut grid = grid_for_status_bar_tests();
+ let many: Vec<String> = (0..40).map(|i| format!("id{}:Label{}", i, i)).collect();
+ feed(
+ &mut grid,
+ &format!("\u{1b}]5577;1;buttons;{}\u{1b}\\", many.join(";")),
+ );
+ assert!(
+ grid.status_bar_buttons.len() <= 8,
+ "expected a cap, got {}",
+ grid.status_bar_buttons.len()
+ );
+}
diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs
index 81185f27..bad164c2 100644
--- a/zellij-server/src/screen.rs
+++ b/zellij-server/src/screen.rs
@@ -6945,6 +6945,10 @@ impl Screen {
default_fg,
default_bg,
p.status_bar_text(),
+ Some(zellij_utils::input::layout::serialize_status_bar_buttons(
+ &p.status_bar_buttons(),
+ ))
+ .filter(|s| !s.is_empty()),
)
})
.collect();
@@ -6987,6 +6991,10 @@ impl Screen {
default_fg,
default_bg,
p.status_bar_text(),
+ Some(zellij_utils::input::layout::serialize_status_bar_buttons(
+ &p.status_bar_buttons(),
+ ))
+ .filter(|s| !s.is_empty()),
)
})
.collect();
diff --git a/zellij-server/src/session_layout_metadata.rs b/zellij-server/src/session_layout_metadata.rs
index 20f557be..b652fff7 100644
--- a/zellij-server/src/session_layout_metadata.rs
+++ b/zellij-server/src/session_layout_metadata.rs
@@ -536,6 +536,7 @@ impl Into<PaneLayoutManifest> for PaneLayoutMetadata {
default_fg: self.default_fg,
default_bg: self.default_bg,
status_bar: self.status_bar,
+ status_bar_buttons: self.status_bar_buttons,
}
}
}
@@ -563,6 +564,7 @@ pub struct PaneLayoutMetadata {
default_fg: Option<String>,
default_bg: Option<String>,
status_bar: Option<String>,
+ status_bar_buttons: Option<String>,
}
impl PaneLayoutMetadata {
@@ -578,6 +580,7 @@ impl PaneLayoutMetadata {
default_fg: Option<String>,
default_bg: Option<String>,
status_bar: Option<String>,
+ status_bar_buttons: Option<String>,
) -> Self {
PaneLayoutMetadata {
id,
@@ -592,6 +595,7 @@ impl PaneLayoutMetadata {
default_fg,
default_bg,
status_bar,
+ status_bar_buttons,
}
}
fn to_pane_metadata(&self) -> PaneMetadata {
@@ -706,6 +710,7 @@ mod tests {
None,
None,
None,
+ None,
)
}
@@ -726,6 +731,7 @@ mod tests {
None,
None,
None,
+ None,
)
}
diff --git a/zellij-server/src/tab/layout_applier.rs b/zellij-server/src/tab/layout_applier.rs
index c796fa41..38dbe44c 100644
--- a/zellij-server/src/tab/layout_applier.rs
+++ b/zellij-server/src/tab/layout_applier.rs
@@ -744,6 +744,11 @@ impl<'a> LayoutApplier<'a> {
if layout.status_bar.is_some() {
new_pane.set_status_bar_text(layout.status_bar.clone());
}
+ if let Some(buttons) = layout.status_bar_buttons.as_deref() {
+ new_pane.set_status_bar_buttons(
+ zellij_utils::input::layout::parse_status_bar_buttons(buttons.split(';')),
+ );
+ }
if let Some(held_command) = hold_for_command {
new_pane.hold(None, true, held_command.clone());
}
diff --git a/zellij-server/src/tab/mod.rs b/zellij-server/src/tab/mod.rs
index 3727b2e2..8f049cad 100644
--- a/zellij-server/src/tab/mod.rs
+++ b/zellij-server/src/tab/mod.rs
@@ -21,6 +21,7 @@ use zellij_utils::data::{
PluginPermission, RegexHighlight, ResizeStrategy, Style, StyledText, WebSharing,
};
use zellij_utils::errors::prelude::*;
+use zellij_utils::input::layout::StatusBarButton;
use zellij_utils::input::theme::StackListStyle;
use zellij_utils::input::command::RunCommand;
use zellij_utils::input::mouse::MouseEvent;
@@ -891,6 +892,13 @@ pub trait Pane {
None
}
fn set_status_bar_text(&mut self, _text: Option<String>) {}
+ fn status_bar_buttons(&self) -> Vec<StatusBarButton> {
+ vec![]
+ }
+ fn set_status_bar_buttons(&mut self, _buttons: Vec<StatusBarButton>) {}
+ fn status_bar_button_at(&self, _position: &Position) -> Option<String> {
+ None
+ }
fn stack_list_entry_label(&self) -> String {
self.current_title()
}
diff --git a/zellij-server/src/tab/mouse_handler.rs b/zellij-server/src/tab/mouse_handler.rs
index b91ae67a..ab8b2383 100644
--- a/zellij-server/src/tab/mouse_handler.rs
+++ b/zellij-server/src/tab/mouse_handler.rs
@@ -407,11 +407,45 @@ impl MouseHandler {
if let Some(effect) = Self::intercept_stack_list_indicator_click(tab, event)? {
return Ok(effect);
}
+ if let Some(effect) = Self::intercept_status_bar_button_click(tab, event)? {
+ return Ok(effect);
+ }
let context = Self::gather_mouse_event_context(tab, event, client_id)?;
let action = Self::determine_mouse_action(event, &context)?;
Self::execute_mouse_action(tab, action, event, client_id)
}
+ /// A click on a pane's status bar button reports it to the program in that
+ /// pane.
+ ///
+ /// Intercepted before normal handling: the bottom frame row otherwise belongs
+ /// to border-drag resizing, and a button click there should not also start a
+ /// resize.
+ ///
+ /// The report is a FIXED format carrying only the button id, never bytes the
+ /// payload chose. The sequence that created the button arrives in-band and is
+ /// untrusted -- `cat` of a hostile file emits it just as readily -- so if a
+ /// click could send arbitrary bytes, viewing a file would be able to inject
+ /// into the stdin of whatever is running, a shell included.
+ fn intercept_status_bar_button_click(
+ tab: &mut Tab,
+ event: &MouseEvent,
+ ) -> Result<Option<MouseEffect>> {
+ if !(event.left && event.event_type == MouseEventType::Press) {
+ return Ok(None);
+ }
+ let Some(pane) = Self::get_pane_at(tab, &event.position, false)? else {
+ return Ok(None);
+ };
+ let pane_id = pane.pid();
+ let Some(button_id) = pane.status_bar_button_at(&event.position) else {
+ return Ok(None);
+ };
+ let report = format!("\u{1b}]5577;1;click;{}\u{1b}\\", button_id);
+ tab.write_to_pane_id_without_preprocessing(report.into_bytes(), pane_id)?;
+ Ok(Some(MouseEffect::state_changed()))
+ }
+
/// Clicking the picker's "+N more" / "- fewer" row toggles the stack's
/// expansion.
///
diff --git a/zellij-server/src/ui/pane_boundaries_frame.rs b/zellij-server/src/ui/pane_boundaries_frame.rs
index d2f1d887..0a3155c1 100644
--- a/zellij-server/src/ui/pane_boundaries_frame.rs
+++ b/zellij-server/src/ui/pane_boundaries_frame.rs
@@ -10,6 +10,7 @@ use crate::ui::hint_text::{
};
use crate::ClientId;
use zellij_utils::data::{client_id_to_colors, PaletteColor, PaneTitleAlignment, Style};
+use zellij_utils::input::layout::{layout_status_bar, StatusBarButton};
use zellij_utils::input::theme::StackListStyle;
use zellij_utils::errors::prelude::*;
use zellij_utils::pane_size::{Offset, PaneGeom, Viewport};
@@ -180,6 +181,7 @@ pub struct FrameParams {
pub show_help_text: bool,
/// Program-supplied text for the bottom frame row (OSC 5577).
pub status_bar: Option<String>,
+ pub status_bar_buttons: Vec<StatusBarButton>,
pub highlight_tooltip: Option<String>,
pub omit_title: bool,
pub frame_geom_override: Option<PaneGeom>,
@@ -214,6 +216,7 @@ pub struct PaneFrame {
is_selectable: bool,
show_help_text: bool,
status_bar: Option<String>,
+ status_bar_buttons: Vec<StatusBarButton>,
highlight_tooltip: Option<String>,
omit_title: bool,
stack_list_entry: Option<StackListEntry>,
@@ -253,6 +256,7 @@ impl PaneFrame {
is_selectable: frame_params.pane_is_selectable,
show_help_text: frame_params.show_help_text,
status_bar: frame_params.status_bar,
+ status_bar_buttons: frame_params.status_bar_buttons,
highlight_tooltip: frame_params.highlight_tooltip,
omit_title: frame_params.omit_title,
stack_list_entry: frame_params.stack_list_entry,
@@ -1297,40 +1301,57 @@ impl PaneFrame {
/// reserving would shrink the pane's content area and so resize its PTY every
/// time the bar appeared or disappeared, firing SIGWINCH at the program that
/// asked for it. The frame row costs nothing and is already a text surface.
- fn render_status_bar_undertitle(&self, text: &str) -> Result<Vec<TerminalCharacter>> {
+ /// Render the pane's status bar into its bottom frame row.
+ ///
+ /// Deliberately reuses the frame row rather than reserving a row of its own:
+ /// reserving would shrink the pane's content area and so resize its PTY every
+ /// time the bar appeared or disappeared, firing SIGWINCH at the program that
+ /// asked for it. The frame row costs nothing and is already a text surface.
+ ///
+ /// Positions come from `layout_status_bar`, the same function the mouse
+ /// hit-test uses, so a button can never be drawn somewhere a click does not
+ /// resolve.
+ fn render_status_bar_undertitle(&self) -> Result<Vec<TerminalCharacter>> {
let err_context = || "failed to render status bar undertitle";
- let max_undertitle_length = self.geom.cols.saturating_sub(2);
+ let inner_cols = self.geom.cols.saturating_sub(2);
+ let layout = layout_status_bar(
+ inner_cols,
+ self.status_bar.as_deref(),
+ &self.status_bar_buttons,
+ );
let mut left_boundary =
foreground_color(self.get_corner(boundary_type::BOTTOM_LEFT), self.color);
let mut right_boundary =
foreground_color(self.get_corner(boundary_type::BOTTOM_RIGHT), self.color);
- // one leading space so the text does not touch the corner glyph
- let label = format!(" {} ", text);
- let label = if label.width() > max_undertitle_length {
- let budget = max_undertitle_length.saturating_sub(2);
- let mut truncated = String::from(" ");
- for character in text.chars() {
- if truncated.width() + character.width().unwrap_or(0) > budget {
- break;
+ // build the inner row as a fill, then paint text and buttons into it
+ let fill = foreground_color(boundary_type::HORIZONTAL, self.color)
+ .pop()
+ .with_context(err_context)?;
+ let mut inner: Vec<TerminalCharacter> = vec![fill; inner_cols];
+ if !layout.text.is_empty() {
+ let text = format!(" {} ", layout.text);
+ for (i, character) in foreground_color(&text, self.color).into_iter().enumerate() {
+ if let Some(slot) = inner.get_mut(i) {
+ *slot = character;
}
- truncated.push(character);
}
- truncated.push('…');
- truncated
- } else {
- label
- };
- let label_len = label.width();
- let mut label_characters = foreground_color(&label, self.color);
+ }
+ let button_color = self.style.colors.text_unselected.emphasis_3;
+ for span in &layout.buttons {
+ for (i, character) in foreground_color(&span.rendered, Some(button_color))
+ .into_iter()
+ .enumerate()
+ {
+ if let Some(slot) = inner.get_mut(span.start + i) {
+ *slot = character;
+ }
+ }
+ }
+
let mut ret = vec![];
ret.append(&mut left_boundary);
- ret.append(&mut label_characters);
- for _ in label_len..max_undertitle_length {
- ret.push(foreground_color(boundary_type::HORIZONTAL, self.color)
- .pop()
- .with_context(err_context)?);
- }
+ ret.append(&mut inner);
ret.append(&mut right_boundary);
Ok(ret)
}
@@ -1553,11 +1574,11 @@ impl PaneFrame {
// The program's own status text wins over every hint we might
// put here: those are things the user can discover elsewhere,
// this was explicitly requested by what is running in the pane.
- if let Some(status_bar) = self.status_bar.as_deref() {
+ if self.status_bar.is_some() || !self.status_bar_buttons.is_empty() {
let x = self.geom.x;
let y = self.geom.y + row;
character_chunks.push(CharacterChunk::new(
- self.render_status_bar_undertitle(status_bar)
+ self.render_status_bar_undertitle()
.with_context(err_context)?,
x,
y,
@@ -1718,6 +1739,7 @@ mod tests {
pane_is_selectable: true,
show_help_text: true,
status_bar: None,
+ status_bar_buttons: vec![],
highlight_tooltip: None,
omit_title: false,
frame_geom_override: None,
diff --git a/zellij-server/src/ui/pane_contents_and_ui.rs b/zellij-server/src/ui/pane_contents_and_ui.rs
index d9f416e9..b5162536 100644
--- a/zellij-server/src/ui/pane_contents_and_ui.rs
+++ b/zellij-server/src/ui/pane_contents_and_ui.rs
@@ -395,6 +395,7 @@ impl<'a> PaneContentsAndUi<'a> {
pane_is_selectable,
show_help_text: self.show_help_text,
status_bar: self.pane.status_bar_text(),
+ status_bar_buttons: self.pane.status_bar_buttons(),
highlight_tooltip: highlight_tooltip.clone(),
omit_title: self.omit_title,
frame_geom_override: self.frame_geom_override,
@@ -424,6 +425,7 @@ impl<'a> PaneContentsAndUi<'a> {
pane_is_selectable,
show_help_text: self.show_help_text,
status_bar: self.pane.status_bar_text(),
+ status_bar_buttons: self.pane.status_bar_buttons(),
highlight_tooltip,
omit_title: self.omit_title,
frame_geom_override: self.frame_geom_override,
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_default_params.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_default_params.snap
index 066be143..a316c28c 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_default_params.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_default_params.snap
@@ -30,6 +30,7 @@ Some(
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -50,6 +51,7 @@ Some(
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -67,6 +69,7 @@ Some(
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
),
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_with_layout_string.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_with_layout_string.snap
index 501d6869..34c2794a 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_with_layout_string.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_with_layout_string.snap
@@ -33,6 +33,7 @@ NewTab(
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -57,6 +58,7 @@ NewTab(
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -81,6 +83,7 @@ NewTab(
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -102,6 +105,7 @@ NewTab(
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
),
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_with_layout_string_and_name.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_with_layout_string_and_name.snap
index 7e209dec..c813ab5d 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_with_layout_string_and_name.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_with_layout_string_and_name.snap
@@ -33,6 +33,7 @@ NewTab(
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -57,6 +58,7 @@ NewTab(
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -81,6 +83,7 @@ NewTab(
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -102,6 +105,7 @@ NewTab(
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
),
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_with_name_and_layout.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_with_name_and_layout.snap
index 33505e45..5a1e0c24 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_with_name_and_layout.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_tab_action_with_name_and_layout.snap
@@ -33,6 +33,7 @@ NewTab(
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -57,6 +58,7 @@ NewTab(
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -81,6 +83,7 @@ NewTab(
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -102,6 +105,7 @@ NewTab(
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
),
diff --git a/zellij-utils/src/input/layout.rs b/zellij-utils/src/input/layout.rs
index 2a461de3..6160bb21 100644
--- a/zellij-utils/src/input/layout.rs
+++ b/zellij-utils/src/input/layout.rs
@@ -85,6 +85,194 @@ pub fn sanitize_status_bar_text(raw: &str) -> String {
.to_owned()
}
+/// A clickable button in a pane's status bar (OSC 5577).
+#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
+pub struct StatusBarButton {
+ /// Echoed back to the program when clicked. Restricted to
+ /// `[A-Za-z0-9_-]` so a hostile payload cannot smuggle arbitrary text into
+ /// the report we write to a program's stdin.
+ pub id: String,
+ pub label: String,
+}
+
+/// Longest id we accept. Ids are opaque handles, not prose.
+const MAX_STATUS_BAR_ID: usize = 32;
+/// Most buttons we accept. A frame row cannot show more than a handful, and the
+/// list is retained for the life of the pane.
+const MAX_STATUS_BAR_BUTTONS: usize = 8;
+
+fn is_valid_status_bar_id(id: &str) -> bool {
+ !id.is_empty()
+ && id.len() <= MAX_STATUS_BAR_ID
+ && id
+ .chars()
+ .all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '-')
+}
+
+/// Decode one `%`-escaped wire field.
+///
+/// Labels are free text but the wire format is `;`-separated, so `;` and `%`
+/// itself are escaped. Anything else is passed through and then sanitised.
+fn decode_status_bar_field(raw: &str) -> String {
+ let mut out = String::with_capacity(raw.len());
+ let mut chars = raw.chars();
+ while let Some(c) = chars.next() {
+ if c != '%' {
+ out.push(c);
+ continue;
+ }
+ let hi = chars.next();
+ let lo = chars.next();
+ match (hi, lo) {
+ (Some(hi), Some(lo)) => {
+ match u8::from_str_radix(&format!("{}{}", hi, lo), 16) {
+ Ok(byte) => out.push(byte as char),
+ // not a valid escape: keep it literal rather than losing text
+ Err(_) => {
+ out.push('%');
+ out.push(hi);
+ out.push(lo);
+ },
+ }
+ },
+ _ => out.push('%'),
+ }
+ }
+ out
+}
+
+fn encode_status_bar_field(raw: &str) -> String {
+ raw.chars()
+ .flat_map(|c| match c {
+ '%' => "%25".chars().collect::<Vec<char>>(),
+ ';' => "%3B".chars().collect::<Vec<char>>(),
+ ':' => "%3A".chars().collect::<Vec<char>>(),
+ other => vec![other],
+ })
+ .collect()
+}
+
+/// Parse the `buttons` verb's params: each is `<id>:<label>`, label `%`-escaped.
+///
+/// Invalid entries are dropped rather than failing the whole list: a partially
+/// understood payload should still give the user the buttons that did make sense.
+pub fn parse_status_bar_buttons<'a, I: Iterator<Item = &'a str>>(params: I) -> Vec<StatusBarButton> {
+ params
+ .filter_map(|param| {
+ let (id, label) = param.split_once(':')?;
+ if !is_valid_status_bar_id(id) {
+ return None;
+ }
+ let label = sanitize_status_bar_text(&decode_status_bar_field(label));
+ if label.is_empty() {
+ return None;
+ }
+ Some(StatusBarButton {
+ id: id.to_owned(),
+ label,
+ })
+ })
+ .take(MAX_STATUS_BAR_BUTTONS)
+ .collect()
+}
+
+/// Serialise buttons back to the wire format, for the session layout.
+pub fn serialize_status_bar_buttons(buttons: &[StatusBarButton]) -> String {
+ buttons
+ .iter()
+ .map(|b| format!("{}:{}", b.id, encode_status_bar_field(&b.label)))
+ .collect::<Vec<String>>()
+ .join(";")
+}
+
+/// One button's position in the status bar row.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct StatusBarButtonSpan {
+ pub id: String,
+ pub rendered: String,
+ /// Column offset from the start of the row's inner area.
+ pub start: usize,
+ pub width: usize,
+}
+
+/// Everything needed to draw a status bar row, and to work out what a click hit.
+#[derive(Debug, Clone, PartialEq, Eq, Default)]
+pub struct StatusBarLayout {
+ /// Status text, already truncated to fit.
+ pub text: String,
+ pub buttons: Vec<StatusBarButtonSpan>,
+}
+
+/// Lay out a pane's status bar within `inner_cols` columns.
+///
+/// THE single definition of where things sit. The renderer draws from it and the
+/// mouse hit-test resolves clicks against it -- two consumers of one layout,
+/// because computing that geometry twice is exactly how the stacked-pane picker
+/// ended up selecting the wrong pane.
+///
+/// Buttons are right-aligned and get first call on the space: they are actionable,
+/// whereas the text is informational and can be truncated.
+pub fn layout_status_bar(
+ inner_cols: usize,
+ status: Option<&str>,
+ buttons: &[StatusBarButton],
+) -> StatusBarLayout {
+ let mut spans = vec![];
+ let mut buttons_width = 0;
+ for button in buttons {
+ // "[label]" plus a leading space to separate it from what precedes it
+ let rendered = format!("[{}]", button.label);
+ let width = rendered.chars().count() + 1;
+ if buttons_width + width > inner_cols {
+ break; // no room for this one or any after it
+ }
+ buttons_width += width;
+ spans.push(StatusBarButtonSpan {
+ id: button.id.clone(),
+ rendered,
+ start: 0, // filled in below, once the total width is known
+ width: width - 1,
+ });
+ }
+ let mut cursor = inner_cols.saturating_sub(buttons_width);
+ for span in spans.iter_mut() {
+ span.start = cursor + 1; // the separating space belongs before the button
+ cursor = span.start + span.width;
+ }
+
+ let text_budget = inner_cols.saturating_sub(buttons_width);
+ let text = match status {
+ Some(status) if text_budget > 2 => {
+ let budget = text_budget - 2; // one space each side
+ if status.chars().count() <= budget {
+ status.to_owned()
+ } else {
+ let mut truncated: String = status.chars().take(budget.saturating_sub(1)).collect();
+ truncated.push('…');
+ truncated
+ }
+ },
+ _ => String::new(),
+ };
+ StatusBarLayout {
+ text,
+ buttons: spans,
+ }
+}
+
+impl StatusBarLayout {
+ /// Id of the button covering `inner_col`, if any.
+ pub fn button_at(&self, inner_col: usize) -> Option<&str> {
+ self.buttons
+ .iter()
+ .find(|span| inner_col >= span.start && inner_col < span.start + span.width)
+ .map(|span| span.id.as_str())
+ }
+ pub fn is_empty(&self) -> bool {
+ self.text.is_empty() && self.buttons.is_empty()
+ }
+}
+
/// How a `children` placeholder arranges the panes that get inserted into it.
///
/// Without one, every inserted pane becomes a flat sibling, which is why a
@@ -975,6 +1163,8 @@ pub struct TiledPaneLayout {
/// Status bar text (OSC 5577) captured at serialisation, so a resurrected
/// pane comes back showing what it showed before.
pub status_bar: Option<String>,
+ /// Status bar buttons, in the same wire format the escape sequence uses.
+ pub status_bar_buttons: Option<String>,
/// How panes inserted at this node's `children` placeholder are arranged.
/// `None` keeps the historical behaviour: flat siblings.
///
diff --git a/zellij-utils/src/input/unit/layout_test.rs b/zellij-utils/src/input/unit/layout_test.rs
index 6c219b2b..41573e93 100644
--- a/zellij-utils/src/input/unit/layout_test.rs
+++ b/zellij-utils/src/input/unit/layout_test.rs
@@ -2785,3 +2785,121 @@ fn sl0p_with_content_replaced_by_falls_back_when_there_is_no_content_slot() {
result
);
}
+
+// --- sl0p: status bar layout -------------------------------------------------
+
+#[test]
+fn sl0p_status_bar_button_spans_are_where_they_are_drawn() {
+ // The renderer draws from this layout and the mouse hit-test resolves against
+ // it. Computing that geometry twice is exactly how the stacked-pane picker
+ // ended up selecting the wrong pane, so assert every drawn column resolves
+ // back to the button drawn there.
+ let buttons = vec![
+ StatusBarButton {
+ id: String::from("approve"),
+ label: String::from("Approve"),
+ },
+ StatusBarButton {
+ id: String::from("reject"),
+ label: String::from("Reject"),
+ },
+ ];
+ for inner_cols in 20..120usize {
+ let layout = layout_status_bar(inner_cols, Some("waiting for review"), &buttons);
+ for span in &layout.buttons {
+ assert!(
+ span.start + span.width <= inner_cols,
+ "{} cols: span {:?} runs past the row",
+ inner_cols,
+ span
+ );
+ for col in span.start..span.start + span.width {
+ assert_eq!(
+ layout.button_at(col),
+ Some(span.id.as_str()),
+ "{} cols: column {} draws {:?} but resolves elsewhere",
+ inner_cols,
+ col,
+ span.id
+ );
+ }
+ // just outside must not resolve to it
+ if span.start > 0 {
+ assert_ne!(layout.button_at(span.start - 1), Some(span.id.as_str()));
+ }
+ }
+ // buttons must never overlap each other
+ for a in &layout.buttons {
+ for b in &layout.buttons {
+ if a.id >= b.id {
+ continue;
+ }
+ assert!(
+ a.start + a.width <= b.start || b.start + b.width <= a.start,
+ "{} cols: {:?} overlaps {:?}",
+ inner_cols,
+ a,
+ b
+ );
+ }
+ }
+ }
+}
+
+#[test]
+fn sl0p_status_bar_drops_buttons_that_cannot_fit_rather_than_overflowing() {
+ // A narrow pane must not draw a half button, and must never report a click on
+ // one it did not draw.
+ let buttons: Vec<StatusBarButton> = (0..6)
+ .map(|i| StatusBarButton {
+ id: format!("id{}", i),
+ label: String::from("LongishLabel"),
+ })
+ .collect();
+ let layout = layout_status_bar(20, Some("status"), &buttons);
+ assert!(
+ layout.buttons.len() < buttons.len(),
+ "expected some buttons to be dropped at 20 cols, got {:?}",
+ layout.buttons
+ );
+ for span in &layout.buttons {
+ assert!(span.start + span.width <= 20);
+ }
+}
+
+#[test]
+fn sl0p_status_bar_text_yields_space_to_buttons() {
+ // Buttons are actionable, the text is informational -- so the text truncates
+ // rather than pushing a button off the row.
+ let buttons = vec![StatusBarButton {
+ id: String::from("go"),
+ label: String::from("Go"),
+ }];
+ let long = "x".repeat(200);
+ let layout = layout_status_bar(30, Some(&long), &buttons);
+ assert_eq!(layout.buttons.len(), 1, "the button must survive");
+ assert!(
+ layout.text.chars().count() < 30,
+ "text should have been truncated, got {} chars",
+ layout.text.chars().count()
+ );
+ assert!(layout.text.ends_with('…'), "truncation should be visible");
+}
+
+#[test]
+fn sl0p_status_bar_wire_format_round_trips() {
+ // Serialised into the session layout and parsed back on resurrection.
+ let buttons = vec![
+ StatusBarButton {
+ id: String::from("a-1"),
+ label: String::from("semi;colon"),
+ },
+ StatusBarButton {
+ id: String::from("b_2"),
+ label: String::from("percent%and:colon"),
+ },
+ ];
+ let wire = serialize_status_bar_buttons(&buttons);
+ let parsed = parse_status_bar_buttons(wire.split(';'));
+ assert_eq!(parsed, buttons, "wire form: {}", wire);
+}
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__args_added_to_args_in_template.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__args_added_to_args_in_template.snap
index 2e5ed9c3..5ffcf17c 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__args_added_to_args_in_template.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__args_added_to_args_in_template.snap
@@ -42,6 +42,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -77,6 +78,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -94,6 +96,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__args_override_args_in_template.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__args_override_args_in_template.snap
index cd3d88cf..92c90a5a 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__args_override_args_in_template.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__args_override_args_in_template.snap
@@ -45,6 +45,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -80,6 +81,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -97,6 +99,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__can_define_a_stack_with_an_expanded_pane.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__can_define_a_stack_with_an_expanded_pane.snap
index b665cfae..1b11ca76 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__can_define_a_stack_with_an_expanded_pane.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__can_define_a_stack_with_an_expanded_pane.snap
@@ -34,6 +34,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -54,6 +55,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -74,6 +76,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -91,6 +94,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -108,6 +112,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__can_define_stacked_children_for_pane_node.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__can_define_stacked_children_for_pane_node.snap
index 29673103..15ad6e8e 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__can_define_stacked_children_for_pane_node.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__can_define_stacked_children_for_pane_node.snap
@@ -34,6 +34,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -54,6 +55,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -71,6 +73,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -88,6 +91,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__can_define_stacked_children_for_pane_template.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__can_define_stacked_children_for_pane_template.snap
index 7d0bfb96..9077d5b0 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__can_define_stacked_children_for_pane_template.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__can_define_stacked_children_for_pane_template.snap
@@ -38,6 +38,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -58,6 +59,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -75,6 +77,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -92,6 +95,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -109,6 +113,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__can_load_swap_layouts_from_a_different_file.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__can_load_swap_layouts_from_a_different_file.snap
index 59f5430c..9fedd5e3 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__can_load_swap_layouts_from_a_different_file.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__can_load_swap_layouts_from_a_different_file.snap
@@ -30,6 +30,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -47,6 +48,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -103,6 +105,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -131,6 +134,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -153,6 +157,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -170,6 +175,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -187,6 +193,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -230,6 +237,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -247,6 +255,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
MaxPanes(
@@ -296,6 +305,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -326,6 +336,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -350,6 +361,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -370,6 +382,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -390,6 +403,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -410,6 +424,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -427,6 +442,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -444,6 +460,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -461,6 +478,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -504,6 +522,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -521,6 +540,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
MaxPanes(
@@ -570,6 +590,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -600,6 +621,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -624,6 +646,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -644,6 +667,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -664,6 +688,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -684,6 +709,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -701,6 +727,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -725,6 +752,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -745,6 +773,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -765,6 +794,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -785,6 +815,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -802,6 +833,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -819,6 +851,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -836,6 +869,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -879,6 +913,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -896,6 +931,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
},
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__children_not_as_first_child_of_pane_template.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__children_not_as_first_child_of_pane_template.snap
index 44f06d4f..91f605a7 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__children_not_as_first_child_of_pane_template.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__children_not_as_first_child_of_pane_template.snap
@@ -40,6 +40,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -64,6 +65,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -84,6 +86,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -101,6 +104,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -118,6 +122,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -138,6 +143,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -155,6 +161,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -183,6 +190,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -202,6 +210,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -222,6 +231,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -239,6 +249,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -256,6 +267,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__children_not_as_first_child_of_tab_template.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__children_not_as_first_child_of_tab_template.snap
index 46e5f0a4..e48b7d0f 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__children_not_as_first_child_of_tab_template.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__children_not_as_first_child_of_tab_template.snap
@@ -35,6 +35,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -59,6 +60,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -79,6 +81,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -96,6 +99,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -113,6 +117,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -133,6 +138,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -150,6 +156,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -182,6 +189,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -201,6 +209,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -221,6 +230,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -238,6 +248,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -264,6 +275,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__close_on_exit_added_to_close_on_exit_in_template.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__close_on_exit_added_to_close_on_exit_in_template.snap
index 5fa239d1..6e297357 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__close_on_exit_added_to_close_on_exit_in_template.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__close_on_exit_added_to_close_on_exit_in_template.snap
@@ -42,6 +42,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -74,6 +75,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -91,6 +93,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__close_on_exit_overrides_close_on_exit_in_template.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__close_on_exit_overrides_close_on_exit_in_template.snap
index 2fa63fbc..2b4ed08e 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__close_on_exit_overrides_close_on_exit_in_template.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__close_on_exit_overrides_close_on_exit_in_template.snap
@@ -42,6 +42,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -74,6 +75,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -91,6 +93,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__combined_tab_and_pane_template_both_with_children.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__combined_tab_and_pane_template_both_with_children.snap
index 4fc7d427..f9d8f070 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__combined_tab_and_pane_template_both_with_children.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__combined_tab_and_pane_template_both_with_children.snap
@@ -35,6 +35,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -61,6 +62,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -78,6 +80,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -98,6 +101,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -115,6 +119,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -139,6 +144,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -159,6 +165,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -176,6 +183,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -193,6 +201,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -225,6 +234,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -251,6 +261,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -268,6 +279,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -288,6 +300,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -305,6 +318,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -325,6 +339,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -342,6 +357,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -368,6 +384,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__cwd_added_to_cwd_in_template.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__cwd_added_to_cwd_in_template.snap
index a8510eb3..5c1e41e0 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__cwd_added_to_cwd_in_template.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__cwd_added_to_cwd_in_template.snap
@@ -42,6 +42,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -76,6 +77,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -93,6 +95,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__cwd_override_cwd_in_template.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__cwd_override_cwd_in_template.snap
index 965a0864..1aaaedde 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__cwd_override_cwd_in_template.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__cwd_override_cwd_in_template.snap
@@ -44,6 +44,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -78,6 +79,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -95,6 +97,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__env_var_expansion.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__env_var_expansion.snap
index 62a937bf..c7fc13e9 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__env_var_expansion.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__env_var_expansion.snap
@@ -33,6 +33,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -57,6 +58,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -81,6 +83,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -105,6 +108,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -139,6 +143,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -167,6 +172,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -195,6 +201,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -229,6 +236,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -257,6 +265,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -278,6 +287,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -312,6 +322,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -336,6 +347,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -360,6 +372,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -384,6 +397,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -418,6 +432,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -446,6 +461,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -474,6 +490,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -508,6 +525,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -536,6 +554,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -557,6 +576,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_and_tab_cwd_prepended_to_panes_with_and_without_cwd.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_and_tab_cwd_prepended_to_panes_with_and_without_cwd.snap
index 4cc5900d..c79bbe9f 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_and_tab_cwd_prepended_to_panes_with_and_without_cwd.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_and_tab_cwd_prepended_to_panes_with_and_without_cwd.snap
@@ -33,6 +33,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -67,6 +68,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -88,6 +90,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -114,6 +117,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_and_tab_cwd_prepended_to_panes_with_and_without_cwd_in_pane_templates.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_and_tab_cwd_prepended_to_panes_with_and_without_cwd_in_pane_templates.snap
index 28a4a86e..e7c98160 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_and_tab_cwd_prepended_to_panes_with_and_without_cwd_in_pane_templates.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_and_tab_cwd_prepended_to_panes_with_and_without_cwd_in_pane_templates.snap
@@ -37,6 +37,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -71,6 +72,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -99,6 +101,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -120,6 +123,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -141,6 +145,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -162,6 +167,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -188,6 +194,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_and_tab_cwd_prepended_to_panes_with_and_without_cwd_in_tab_templates.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_and_tab_cwd_prepended_to_panes_with_and_without_cwd_in_tab_templates.snap
index 7adc51a4..74274346 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_and_tab_cwd_prepended_to_panes_with_and_without_cwd_in_tab_templates.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_and_tab_cwd_prepended_to_panes_with_and_without_cwd_in_tab_templates.snap
@@ -33,6 +33,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -67,6 +68,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -95,6 +97,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -116,6 +119,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -137,6 +141,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -163,6 +168,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_given_to_panes_without_cwd.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_given_to_panes_without_cwd.snap
index 7cd11303..5d4168c2 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_given_to_panes_without_cwd.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_given_to_panes_without_cwd.snap
@@ -33,6 +33,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -67,6 +68,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -88,6 +90,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -122,6 +125,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -156,6 +160,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -177,6 +182,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_passed_from_layout_constructor.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_passed_from_layout_constructor.snap
index 96f37cf8..0bdcafe2 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_passed_from_layout_constructor.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_passed_from_layout_constructor.snap
@@ -34,6 +34,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -68,6 +69,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -89,6 +91,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_passed_from_layout_constructor_overrides_global_cwd_in_layout_file.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_passed_from_layout_constructor_overrides_global_cwd_in_layout_file.snap
index c1b63252..9c1e7463 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_passed_from_layout_constructor_overrides_global_cwd_in_layout_file.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_passed_from_layout_constructor_overrides_global_cwd_in_layout_file.snap
@@ -33,6 +33,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -67,6 +68,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -88,6 +90,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -122,6 +125,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -156,6 +160,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -177,6 +182,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_prepended_to_panes_with_cwd.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_prepended_to_panes_with_cwd.snap
index 788695ff..90afd3da 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_prepended_to_panes_with_cwd.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_prepended_to_panes_with_cwd.snap
@@ -33,6 +33,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -67,6 +68,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -88,6 +90,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -122,6 +125,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -156,6 +160,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -177,6 +182,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_with_tab_cwd_given_to_panes_without_cwd.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_with_tab_cwd_given_to_panes_without_cwd.snap
index 1f0425f7..41795b1b 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_with_tab_cwd_given_to_panes_without_cwd.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__global_cwd_with_tab_cwd_given_to_panes_without_cwd.snap
@@ -33,6 +33,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -67,6 +68,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -88,6 +90,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -114,6 +117,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_command_panes_and_close_on_exit.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_command_panes_and_close_on_exit.snap
index a47af210..eb1150dc 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_command_panes_and_close_on_exit.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_command_panes_and_close_on_exit.snap
@@ -42,6 +42,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -59,6 +60,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_command_panes_and_start_suspended.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_command_panes_and_start_suspended.snap
index a6bb7670..05e71efb 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_command_panes_and_start_suspended.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_command_panes_and_start_suspended.snap
@@ -42,6 +42,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -59,6 +60,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_default_tab_template.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_default_tab_template.snap
index cb3274bc..6759e5f7 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_default_tab_template.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_default_tab_template.snap
@@ -31,6 +31,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -55,6 +56,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -75,6 +77,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -92,6 +95,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -112,6 +116,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -129,6 +134,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -159,6 +165,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -183,6 +190,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -203,6 +211,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -220,6 +229,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -240,6 +250,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -257,6 +268,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -285,6 +297,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -305,6 +318,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -325,6 +339,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -342,6 +357,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -372,6 +388,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -392,6 +409,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -412,6 +430,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -429,6 +448,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_nested_branched_pane_templates.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_nested_branched_pane_templates.snap
index 9c7a4f5b..be114113 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_nested_branched_pane_templates.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_nested_branched_pane_templates.snap
@@ -34,6 +34,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -54,6 +55,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -78,6 +80,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -98,6 +101,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -115,6 +119,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -139,6 +144,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -159,6 +165,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -179,6 +186,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -196,6 +204,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -213,6 +222,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -230,6 +240,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_nested_pane_templates.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_nested_pane_templates.snap
index 180386a4..e6b561ee 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_nested_pane_templates.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_nested_pane_templates.snap
@@ -34,6 +34,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -54,6 +55,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -78,6 +80,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -98,6 +101,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -115,6 +119,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -135,6 +140,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -152,6 +158,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -169,6 +176,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_new_tab_template.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_new_tab_template.snap
index 032b396a..2af0bc1c 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_new_tab_template.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_new_tab_template.snap
@@ -31,6 +31,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -51,6 +52,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -68,6 +70,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -98,6 +101,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -118,6 +122,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -135,6 +140,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -159,6 +165,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -193,6 +200,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -213,6 +221,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -230,6 +239,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -247,6 +257,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_pane_excluded_from_sync.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_pane_excluded_from_sync.snap
index 8c9000a1..15b9702c 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_pane_excluded_from_sync.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_pane_excluded_from_sync.snap
@@ -32,6 +32,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -49,6 +50,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_pane_templates.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_pane_templates.snap
index 2ce37e0f..bafe8ddb 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_pane_templates.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_pane_templates.snap
@@ -34,6 +34,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -58,6 +59,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -75,6 +77,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -95,6 +98,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -112,6 +116,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -136,6 +141,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -160,6 +166,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -180,6 +187,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -197,6 +205,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -217,6 +226,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -234,6 +244,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -258,6 +269,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -282,6 +294,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -302,6 +315,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -319,6 +333,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -339,6 +354,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -356,6 +372,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -380,6 +397,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -400,6 +418,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -420,6 +439,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -437,6 +457,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -454,6 +475,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_tab_and_pane_templates.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_tab_and_pane_templates.snap
index 65dbbfae..f37702e9 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_tab_and_pane_templates.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_tab_and_pane_templates.snap
@@ -33,6 +33,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -69,6 +70,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -86,6 +88,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -106,6 +109,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -123,6 +127,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -140,6 +145,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -166,6 +172,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_tabs_and_floating_panes.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_tabs_and_floating_panes.snap
index 9d442677..9e8c4416 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_tabs_and_floating_panes.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__layout_with_tabs_and_floating_panes.snap
@@ -29,6 +29,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -46,6 +47,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[
@@ -91,6 +93,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -108,6 +111,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[
@@ -167,6 +171,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_with_cwd_is_overriden_by_its_consumers_bare_cwd.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_with_cwd_is_overriden_by_its_consumers_bare_cwd.snap
index 1c1d6224..d53bea42 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_with_cwd_is_overriden_by_its_consumers_bare_cwd.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_with_cwd_is_overriden_by_its_consumers_bare_cwd.snap
@@ -43,6 +43,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -64,6 +65,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -108,6 +110,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -129,6 +132,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_with_cwd_overriden_by_its_consumers_command_cwd.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_with_cwd_overriden_by_its_consumers_command_cwd.snap
index 7716b9a6..eeaa402f 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_with_cwd_overriden_by_its_consumers_command_cwd.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_with_cwd_overriden_by_its_consumers_command_cwd.snap
@@ -43,6 +43,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -64,6 +65,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -108,6 +110,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -129,6 +132,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_with_cwd_remains_when_its_consumer_command_does_not_have_a_cwd.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_with_cwd_remains_when_its_consumer_command_does_not_have_a_cwd.snap
index 2f291be0..1fabddca 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_with_cwd_remains_when_its_consumer_command_does_not_have_a_cwd.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_with_cwd_remains_when_its_consumer_command_does_not_have_a_cwd.snap
@@ -43,6 +43,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -64,6 +65,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -108,6 +110,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -129,6 +132,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_without_cwd_is_overriden_by_its_consumers_cwd.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_without_cwd_is_overriden_by_its_consumers_cwd.snap
index 9f13788c..82e52f5f 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_without_cwd_is_overriden_by_its_consumers_cwd.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_without_cwd_is_overriden_by_its_consumers_cwd.snap
@@ -43,6 +43,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -64,6 +65,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -108,6 +110,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -129,6 +132,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_without_cwd_receives_its_consumers_bare_cwd.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_without_cwd_receives_its_consumers_bare_cwd.snap
index d12e7975..d319e472 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_without_cwd_receives_its_consumers_bare_cwd.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_command_without_cwd_receives_its_consumers_bare_cwd.snap
@@ -43,6 +43,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -64,6 +65,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -108,6 +110,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -129,6 +132,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_bare_cwd_overriden_by_its_consumers_bare_cwd.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_bare_cwd_overriden_by_its_consumers_bare_cwd.snap
index 33d7e388..c2866ca8 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_bare_cwd_overriden_by_its_consumers_bare_cwd.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_bare_cwd_overriden_by_its_consumers_bare_cwd.snap
@@ -33,6 +33,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -54,6 +55,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -88,6 +90,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -109,6 +112,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_bare_propagated_to_its_consumer_command_with_cwd.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_bare_propagated_to_its_consumer_command_with_cwd.snap
index 60b17528..f005e61a 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_bare_propagated_to_its_consumer_command_with_cwd.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_bare_propagated_to_its_consumer_command_with_cwd.snap
@@ -43,6 +43,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -64,6 +65,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -108,6 +110,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -129,6 +132,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_bare_propagated_to_its_consumer_command_without_cwd.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_bare_propagated_to_its_consumer_command_without_cwd.snap
index 85ab2c29..19a37c78 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_bare_propagated_to_its_consumer_command_without_cwd.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_bare_propagated_to_its_consumer_command_without_cwd.snap
@@ -43,6 +43,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -64,6 +65,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -108,6 +110,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -129,6 +132,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_bare_propagated_to_its_consumer_edit.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_bare_propagated_to_its_consumer_edit.snap
index d17d5524..0134ce53 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_bare_propagated_to_its_consumer_edit.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_bare_propagated_to_its_consumer_edit.snap
@@ -37,6 +37,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -58,6 +59,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -96,6 +98,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -117,6 +120,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_command_propagated_to_its_consumer_edit.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_command_propagated_to_its_consumer_edit.snap
index 7a8ad8e4..7f3fb61d 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_command_propagated_to_its_consumer_edit.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_command_propagated_to_its_consumer_edit.snap
@@ -37,6 +37,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -58,6 +59,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -96,6 +98,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -117,6 +120,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__tab_cwd_given_to_panes_without_cwd.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__tab_cwd_given_to_panes_without_cwd.snap
index cef9310b..3800b839 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__tab_cwd_given_to_panes_without_cwd.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__tab_cwd_given_to_panes_without_cwd.snap
@@ -33,6 +33,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -67,6 +68,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -88,6 +90,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -114,6 +117,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__tab_cwd_prepended_to_panes_with_cwd.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__tab_cwd_prepended_to_panes_with_cwd.snap
index 103e37cf..ab914f9b 100644
--- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__tab_cwd_prepended_to_panes_with_cwd.snap
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__tab_cwd_prepended_to_panes_with_cwd.snap
@@ -33,6 +33,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
TiledPaneLayout {
@@ -67,6 +68,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
],
@@ -88,6 +90,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
@@ -114,6 +117,7 @@ Layout {
default_fg: None,
default_bg: None,
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
},
[],
diff --git a/zellij-utils/src/ipc/protobuf_conversion.rs b/zellij-utils/src/ipc/protobuf_conversion.rs
index f8034ba9..0c26165b 100644
--- a/zellij-utils/src/ipc/protobuf_conversion.rs
+++ b/zellij-utils/src/ipc/protobuf_conversion.rs
@@ -4521,6 +4521,7 @@ impl TryFrom<crate::client_server_contract::client_server_contract::TiledPaneLay
// no protobuf representation, same as default_fg/default_bg
// no protobuf representation, same as children_arrangement
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
})
}
diff --git a/zellij-utils/src/kdl/kdl_layout_parser.rs b/zellij-utils/src/kdl/kdl_layout_parser.rs
index 1032ee35..643d268e 100644
--- a/zellij-utils/src/kdl/kdl_layout_parser.rs
+++ b/zellij-utils/src/kdl/kdl_layout_parser.rs
@@ -110,6 +110,7 @@ impl<'a> KdlLayoutParser<'a> {
|| property_name == "default_bg"
|| property_name == "arrangement"
|| property_name == "status_bar"
+ || property_name == "status_bar_buttons"
}
fn is_a_valid_floating_pane_property(&self, property_name: &str) -> bool {
property_name == "borderless"
@@ -579,6 +580,9 @@ impl<'a> KdlLayoutParser<'a> {
let status_bar = kdl_get_string_property_or_child_value_with_error!(kdl_node, "status_bar")
.map(|s| crate::input::layout::sanitize_status_bar_text(s))
.filter(|s| !s.is_empty());
+ let status_bar_buttons =
+ kdl_get_string_property_or_child_value_with_error!(kdl_node, "status_bar_buttons")
+ .map(|s| s.to_string());
let children_arrangement =
match kdl_get_string_property_or_child_value_with_error!(kdl_node, "arrangement") {
Some(raw) => match PaneArrangement::from_str(raw) {
@@ -638,6 +642,7 @@ impl<'a> KdlLayoutParser<'a> {
default_fg,
default_bg,
status_bar,
+ status_bar_buttons,
children_arrangement,
..Default::default()
})
diff --git a/zellij-utils/src/plugin_api/action.rs b/zellij-utils/src/plugin_api/action.rs
index 3ee610d4..edc9ce66 100644
--- a/zellij-utils/src/plugin_api/action.rs
+++ b/zellij-utils/src/plugin_api/action.rs
@@ -3116,6 +3116,7 @@ impl TryFrom<ProtobufTiledPaneLayout> for TiledPaneLayout {
// no protobuf representation, same as default_fg/default_bg above
// no protobuf representation, same as children_arrangement
status_bar: None,
+ status_bar_buttons: None,
children_arrangement: None,
})
}
diff --git a/zellij-utils/src/session_serialization.rs b/zellij-utils/src/session_serialization.rs
index 279dfde5..a611569d 100644
--- a/zellij-utils/src/session_serialization.rs
+++ b/zellij-utils/src/session_serialization.rs
@@ -39,6 +39,7 @@ pub struct PaneLayoutManifest {
pub default_fg: Option<String>,
pub default_bg: Option<String>,
pub status_bar: Option<String>,
+ pub status_bar_buttons: Option<String>,
}
pub fn serialize_session_layout(
@@ -200,6 +201,11 @@ fn serialize_tiled_pane(
.entries_mut()
.push(KdlEntry::new_prop("status_bar", status_bar.to_owned()));
}
+ if let Some(ref buttons) = layout.status_bar_buttons {
+ tiled_pane_node
+ .entries_mut()
+ .push(KdlEntry::new_prop("status_bar_buttons", buttons.to_owned()));
+ }
let has_child_attributes = !layout.children.is_empty()
|| layout.external_children_index.is_some()
|| !args.is_empty()
@@ -748,6 +754,7 @@ fn tiled_pane_layout_from_manifest(
default_fg,
default_bg,
status_bar,
+ status_bar_buttons,
) = manifest
.map(|g| {
let mut run = g.run.clone();
@@ -768,9 +775,10 @@ fn tiled_pane_layout_from_manifest(
g.default_fg.clone(),
g.default_bg.clone(),
g.status_bar.clone(),
+ g.status_bar_buttons.clone(),
)
})
- .unwrap_or((None, None, false, None, None, None, None, None, None));
+ .unwrap_or((None, None, false, None, None, None, None, None, None, None));
TiledPaneLayout {
split_size,
run,
@@ -782,6 +790,7 @@ fn tiled_pane_layout_from_manifest(
default_fg,
default_bg,
status_bar,
+ status_bar_buttons,
..Default::default()
}
}