aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTruffle <truffleagent@gmail.com>2026-07-10 03:07:19 -0700
committerGitHub <noreply@github.com>2026-07-10 12:07:19 +0200
commit0871f5d2b6f2fed36c6818bc9871bbbb5703dabe (patch)
tree2b3874f3dd3b1ae9ede273e9c47f68efb6272033
parentAllow creating panes/tabs from the CLI without changing focus to them (#5346) (diff)
downloadsl0ppij-0871f5d2b6f2fed36c6818bc9871bbbb5703dabe.tar.gz
sl0ppij-0871f5d2b6f2fed36c6818bc9871bbbb5703dabe.tar.xz
sl0ppij-0871f5d2b6f2fed36c6818bc9871bbbb5703dabe.zip
fix(config): allow binding theme actions in config.kdl (#5302)
* fix(config): allow binding theme actions in config.kdl ToggleTheme, SetDarkTheme and SetLightTheme work from the CLI (`zellij action toggle-theme`) but the keybinding parser rejected them with "Unsupported action", so they could not be bound in config.kdl. The inner `parse_kdl_action_arguments!` macro already knew these actions, but the main `match action_name` arm that dispatches to it had no entry for them, so they fell through to the unsupported-action error. Add the missing parse arms, and the matching `to_kdl` serialization arms so the bindings round-trip. Closes #5297 * add actions to round trip tests * add pr --------- Co-authored-by: Aram Drevekenin <aram@poor.dev>
-rw-r--r--CHANGELOG.md1
-rw-r--r--zellij-utils/src/ipc/tests/roundtrip_tests.rs18
-rw-r--r--zellij-utils/src/kdl/mod.rs63
3 files changed, 82 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e21895f6..39008b5b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
* fix(windows): backslashes dropped when quoting arguments passed to spawned processes (https://github.com/zellij-org/zellij/pull/5336)
* fix: occasional high resource utilization and sluggishness on machines with tens of thousands of concurent processes (https://github.com/zellij-org/zellij/pull/5324)
* feat: allow opening panes/tabs from the CLI without changing focus (https://github.com/zellij-org/zellij/pull/5346)
+* feat: allow binding `SetDarkTheme`, `SetLightTheme` and `ToggleTheme` as direct keybinding actions (https://github.com/zellij-org/zellij/pull/5302)
## [0.44.3] - 2026-05-13
* fix(windows): bump windows-sys to 0.59 to align manifest with code, fixing source builds via `cargo install`/`cargo binstall` (https://github.com/zellij-org/zellij/pull/5139)
diff --git a/zellij-utils/src/ipc/tests/roundtrip_tests.rs b/zellij-utils/src/ipc/tests/roundtrip_tests.rs
index db0b8fc1..eb8a06de 100644
--- a/zellij-utils/src/ipc/tests/roundtrip_tests.rs
+++ b/zellij-utils/src/ipc/tests/roundtrip_tests.rs
@@ -2279,6 +2279,24 @@ fn test_client_messages() {
is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
+ action: Action::SetDarkTheme,
+ terminal_id: Some(1),
+ client_id: Some(100),
+ is_cli_client: true,
+ });
+ test_client_roundtrip!(ClientToServerMsg::Action {
+ action: Action::SetLightTheme,
+ terminal_id: Some(1),
+ client_id: Some(100),
+ is_cli_client: true,
+ });
+ test_client_roundtrip!(ClientToServerMsg::Action {
+ action: Action::ToggleTheme,
+ terminal_id: Some(1),
+ client_id: Some(100),
+ is_cli_client: true,
+ });
+ test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::LaunchOrFocusPlugin {
plugin: RunPluginOrAlias::RunPlugin(RunPlugin::default()),
should_float: true,
diff --git a/zellij-utils/src/kdl/mod.rs b/zellij-utils/src/kdl/mod.rs
index 94848e63..5a8e1b34 100644
--- a/zellij-utils/src/kdl/mod.rs
+++ b/zellij-utils/src/kdl/mod.rs
@@ -1347,6 +1347,9 @@ impl Action {
Action::TogglePanePinned => Some(KdlNode::new("TogglePanePinned")),
Action::TogglePaneInGroup => Some(KdlNode::new("TogglePaneInGroup")),
Action::ToggleGroupMarking => Some(KdlNode::new("ToggleGroupMarking")),
+ Action::SetDarkTheme => Some(KdlNode::new("SetDarkTheme")),
+ Action::SetLightTheme => Some(KdlNode::new("SetLightTheme")),
+ Action::ToggleTheme => Some(KdlNode::new("ToggleTheme")),
_ => None,
}
}
@@ -1614,6 +1617,15 @@ impl TryFrom<(&KdlNode, &Options)> for Action {
parse_kdl_action_arguments!(action_name, action_arguments, kdl_action)
},
"Detach" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
+ "SetDarkTheme" => {
+ parse_kdl_action_arguments!(action_name, action_arguments, kdl_action)
+ },
+ "SetLightTheme" => {
+ parse_kdl_action_arguments!(action_name, action_arguments, kdl_action)
+ },
+ "ToggleTheme" => {
+ parse_kdl_action_arguments!(action_name, action_arguments, kdl_action)
+ },
"SwitchSession" => {
let name = kdl_get_string_property_or_child_value!(kdl_action, "name")
.map(|s| s.to_string())
@@ -6721,6 +6733,57 @@ fn keybinds_to_string_with_multiple_actions() {
}
#[test]
+fn can_bind_theme_actions() {
+ // Regression test for https://github.com/zellij-org/zellij/issues/5297
+ // SetDarkTheme / SetLightTheme / ToggleTheme work via the CLI but used to be
+ // rejected by the keybinding parser with "Unsupported action".
+ let fake_config = r#"
+ keybinds {
+ normal {
+ bind "Ctrl t" { ToggleTheme; }
+ bind "Ctrl d" { SetDarkTheme; }
+ bind "Ctrl l" { SetLightTheme; }
+ }
+ }"#;
+ let document: KdlDocument = fake_config.parse().unwrap();
+ let deserialized = Keybinds::from_kdl(
+ document.get("keybinds").unwrap(),
+ Default::default(),
+ &Default::default(),
+ )
+ .unwrap();
+ let ctrl_t = KeyWithModifier::new(BareKey::Char('t')).with_ctrl_modifier();
+ assert_eq!(
+ deserialized.get_actions_for_key_in_mode(&InputMode::Normal, &ctrl_t),
+ Some(&vec![Action::ToggleTheme])
+ );
+ let ctrl_d = KeyWithModifier::new(BareKey::Char('d')).with_ctrl_modifier();
+ assert_eq!(
+ deserialized.get_actions_for_key_in_mode(&InputMode::Normal, &ctrl_d),
+ Some(&vec![Action::SetDarkTheme])
+ );
+ let ctrl_l = KeyWithModifier::new(BareKey::Char('l')).with_ctrl_modifier();
+ assert_eq!(
+ deserialized.get_actions_for_key_in_mode(&InputMode::Normal, &ctrl_l),
+ Some(&vec![Action::SetLightTheme])
+ );
+ // The bindings must also survive a serialize -> deserialize round-trip.
+ let serialized = Keybinds::to_kdl(&deserialized, true);
+ let deserialized_from_serialized = Keybinds::from_kdl(
+ serialized
+ .to_string()
+ .parse::<KdlDocument>()
+ .unwrap()
+ .get("keybinds")
+ .unwrap(),
+ Default::default(),
+ &Default::default(),
+ )
+ .unwrap();
+ assert_eq!(deserialized, deserialized_from_serialized);
+}
+
+#[test]
fn keybinds_to_string_with_all_actions() {
let fake_config = r#"
keybinds {