aboutsummaryrefslogtreecommitdiffstats
path: root/zellij-utils/src/kdl
diff options
context:
space:
mode:
authorKarl Bunch <karlbunch@users.noreply.github.com>2026-03-04 08:26:26 -0500
committerGitHub <noreply@github.com>2026-03-04 14:26:26 +0100
commitf77cdec298576164f34baf0456e4b986bde269e6 (patch)
treeaf9fb93cfc6edf465378952c0aff38d48820e142 /zellij-utils/src/kdl
parentdocs(changelog): native Windows support (!!) (diff)
downloadsl0ppij-f77cdec298576164f34baf0456e4b986bde269e6.tar.gz
sl0ppij-f77cdec298576164f34baf0456e4b986bde269e6.tar.xz
sl0ppij-f77cdec298576164f34baf0456e4b986bde269e6.zip
feat: add per-pane default foreground/background color support (#4737)
* feat: add per-pane default foreground/background color support Add per-pane default foreground and background colors, configurable through four surfaces: - OSC 10/11 escape sequences (set/query) and OSC 110/111 (reset) - CLI action: zellij action set-pane-color --pane-id <id> --fg/--bg - Layout config: default_fg/default_bg properties on pane nodes - Plugin API: set_pane_color() SDK function and PaneInfo read-side Colors are applied at render time as a fallback when cells have no explicit foreground/background, without mutating stored grid data. Closes #4712 * refactor: address review feedback for pane color support - Extract adjust_styles_for_custom_bg_fg in output/mod.rs - Move color parsing (xparse_color) from tab into Grid - Move color serialization (ansi_code_to_color_string) into Grid - Pane trait now uses Option<String> for color getters/setters - Add colors to session serialization (dump-layout) - Add default_fg/default_bg to protobuf IPC schema to fix layout-in-session color loss - Update example layout with tab-bar and status-bar * fix stack overflow and ordering * rustfmt * update e2e snapshots --------- Co-authored-by: Karl Bunch <karl@karlbunch.com> Co-authored-by: Aram Drevekenin <aram@poor.dev>
Diffstat (limited to 'zellij-utils/src/kdl')
-rw-r--r--zellij-utils/src/kdl/kdl_layout_parser.rs16
-rw-r--r--zellij-utils/src/kdl/mod.rs6
2 files changed, 22 insertions, 0 deletions
diff --git a/zellij-utils/src/kdl/kdl_layout_parser.rs b/zellij-utils/src/kdl/kdl_layout_parser.rs
index 6e1e2c76..ff7fcfe3 100644
--- a/zellij-utils/src/kdl/kdl_layout_parser.rs
+++ b/zellij-utils/src/kdl/kdl_layout_parser.rs
@@ -106,6 +106,8 @@ impl<'a> KdlLayoutParser<'a> {
|| property_name == "expanded"
|| property_name == "exclude_from_sync"
|| property_name == "contents_file"
+ || property_name == "default_fg"
+ || property_name == "default_bg"
}
fn is_a_valid_floating_pane_property(&self, property_name: &str) -> bool {
property_name == "borderless"
@@ -124,6 +126,8 @@ impl<'a> KdlLayoutParser<'a> {
|| property_name == "height"
|| property_name == "pinned"
|| property_name == "contents_file"
+ || property_name == "default_fg"
+ || property_name == "default_bg"
}
fn is_a_valid_tab_property(&self, property_name: &str) -> bool {
property_name == "focus"
@@ -563,6 +567,10 @@ impl<'a> KdlLayoutParser<'a> {
kdl_node.span().len(),
));
}
+ let default_fg = kdl_get_string_property_or_child_value_with_error!(kdl_node, "default_fg")
+ .map(|s| s.to_string());
+ let default_bg = kdl_get_string_property_or_child_value_with_error!(kdl_node, "default_bg")
+ .map(|s| s.to_string());
self.assert_no_mixed_children_and_properties(kdl_node)?;
let pane_initial_contents = contents_file.and_then(|contents_file| {
self.file_name
@@ -585,6 +593,8 @@ impl<'a> KdlLayoutParser<'a> {
children_are_stacked,
is_expanded_in_stack,
pane_initial_contents,
+ default_fg,
+ default_bg,
..Default::default()
})
}
@@ -605,6 +615,10 @@ impl<'a> KdlLayoutParser<'a> {
.map(|name| name.to_string());
let contents_file =
kdl_get_string_property_or_child_value_with_error!(kdl_node, "contents_file");
+ let default_fg = kdl_get_string_property_or_child_value_with_error!(kdl_node, "default_fg")
+ .map(|s| s.to_string());
+ let default_bg = kdl_get_string_property_or_child_value_with_error!(kdl_node, "default_bg")
+ .map(|s| s.to_string());
self.assert_no_mixed_children_and_properties(kdl_node)?;
let pane_initial_contents = contents_file.and_then(|contents_file| {
self.file_name
@@ -625,6 +639,8 @@ impl<'a> KdlLayoutParser<'a> {
pinned,
borderless,
pane_initial_contents,
+ default_fg,
+ default_bg,
..Default::default()
})
}
diff --git a/zellij-utils/src/kdl/mod.rs b/zellij-utils/src/kdl/mod.rs
index 12eadff6..9fcb3113 100644
--- a/zellij-utils/src/kdl/mod.rs
+++ b/zellij-utils/src/kdl/mod.rs
@@ -5927,6 +5927,8 @@ impl PaneInfo {
plugin_url,
is_selectable,
index_in_pane_group: Default::default(), // we don't serialize this
+ default_fg: None,
+ default_bg: None,
};
Ok((tab_position, pane_info))
}
@@ -6075,6 +6077,8 @@ fn serialize_and_deserialize_session_info_with_data() {
plugin_url: None,
is_selectable: true,
index_in_pane_group: Default::default(), // we don't serialize this
+ default_fg: None,
+ default_bg: None,
},
PaneInfo {
id: 1,
@@ -6100,6 +6104,8 @@ fn serialize_and_deserialize_session_info_with_data() {
plugin_url: Some("i_am_a_fake_plugin".to_owned()),
is_selectable: true,
index_in_pane_group: Default::default(), // we don't serialize this
+ default_fg: None,
+ default_bg: None,
},
];
let mut panes = HashMap::new();