aboutsummaryrefslogtreecommitdiff
path: root/src/config.rs
diff options
context:
space:
mode:
authorJJ Liebig <jonathan.liebig@gmail.com>2026-09-28 11:58:09 +0200
committerGitHub <noreply@github.com>2026-09-28 11:58:09 +0200
commit7f89b11a11160874ba89f3be7c64b29960bd2df3 (patch)
tree0e875b3fbbe5a701cfb0182bda0ce0994267584c /src/config.rs
parent0d5d6f1f317e238c8297076bc6ab5c3a0cd56283 (diff)
feat: support multiple prefix keys (#4653)
* feat: support multiple prefix keys keys.prefix accepts an array in addition to a single string so one config can define several prefix keys. Every configured prefix enters the same prefix mode, and the help panel lists them all. Published keybinding profiles keep the primary prefix as a scalar and carry the rest in an optional extra_prefixes field so older clients keep working with the primary prefix. * fix: reject an empty prefix list on reload An explicitly empty keys.prefix array now stays empty through config parsing so validation rejects it and a reload keeps the current keybindings instead of silently falling back to ctrl+b.
Diffstat (limited to 'src/config.rs')
-rw-r--r--src/config.rs45
1 files changed, 40 insertions, 5 deletions
diff --git a/src/config.rs b/src/config.rs
index 60a22a1e..8550097d 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -17,9 +17,9 @@ pub use self::{
upsert_section_value,
},
keybinds::{
- format_key_combo, normalize_key_combo, terminal_key_matches_combo, ActionKeybinds,
+ format_prefix_combos, normalize_key_combo, terminal_key_matches_combo, ActionKeybinds,
BindingConfig, CommandKeybindConfig, CustomCommandAction, CustomCommandKeybind,
- IndexedKeybind, Keybinds, LiveKeybindConfig,
+ IndexedKeybind, KeyCombo, Keybinds, LiveKeybindConfig,
},
model::{
validated_sidebar_bounds, AgentPanelSortConfig, Config, ConfigReloadReport,
@@ -102,7 +102,7 @@ impl Config {
.unwrap_or(true)
}
- pub fn prefix_key(&self) -> (KeyCode, KeyModifiers) {
+ pub fn prefix_keys(&self) -> Vec<(KeyCode, KeyModifiers)> {
self.validated_keybinds().1
}
@@ -182,7 +182,7 @@ impl Config {
}
let mut keys = self.keys.local_profile(&self.keybinds());
- keys.set_prefix(format_key_combo(self.prefix_key()));
+ keys.set_prefixes(&self.prefix_keys());
toml::to_string_pretty(&KeysProfile { keys })
}
}
@@ -239,7 +239,42 @@ prefix = "ctrl+"
let keybinds = keybindings_from_profile_toml(&profile).unwrap();
assert!(profile.contains("prefix = \"ctrl+b\""));
- assert_eq!(keybinds.prefix, config.prefix_key());
+ assert_eq!(keybinds.prefix, config.prefix_keys());
+ }
+
+ #[test]
+ fn local_keybindings_profile_publishes_additional_prefixes_for_old_clients() {
+ let config: Config = toml::from_str(
+ r#"
+[keys]
+prefix = ["ctrl+space", "ctrl+s"]
+"#,
+ )
+ .unwrap();
+
+ let profile = config.local_keybindings_profile_toml().unwrap();
+
+ // Generation-1 clients parse `prefix` as a single string; the extra
+ // prefixes ride in the optional `extra_prefixes` field they ignore.
+ assert!(profile.contains("prefix = \"ctrl+space\""));
+ assert!(!profile.contains("prefix = ["));
+ assert!(profile.contains("extra_prefixes = [\"ctrl+s\"]"));
+
+ let keybinds = keybindings_from_profile_toml(&profile).unwrap();
+ assert_eq!(keybinds.prefix, config.prefix_keys());
+ }
+
+ #[test]
+ fn local_keybindings_profile_omits_extra_prefixes_for_a_single_prefix() {
+ let config: Config = toml::from_str(
+ r#"
+[keys]
+prefix = "ctrl+b"
+"#,
+ )
+ .unwrap();
+ let profile = config.local_keybindings_profile_toml().unwrap();
+ assert!(!profile.contains("extra_prefixes"));
}
#[test]