diff options
Diffstat (limited to 'src/config/model.rs')
| -rw-r--r-- | src/config/model.rs | 43 |
1 files changed, 36 insertions, 7 deletions
diff --git a/src/config/model.rs b/src/config/model.rs index ce59eb2e..0e2e57ce 100644 --- a/src/config/model.rs +++ b/src/config/model.rs @@ -334,8 +334,9 @@ pub struct LoadedConfig { #[derive(Debug, Clone, Serialize)] pub struct KeysConfig { - /// Prefix key to enter prefix mode (e.g. "ctrl+b", "f12", "esc"). - pub prefix: String, + /// Prefix key(s) to enter prefix mode (e.g. "ctrl+b", "f12", "esc", or an + /// array to accept several). + pub prefix: BindingConfig, /// Open keybinding help. Default: "prefix+?" pub help: BindingConfig, /// Open settings. Default: "prefix+s" @@ -467,7 +468,12 @@ pub struct KeysConfig { #[serde(default)] pub(crate) struct KeysConfigOverlay { #[serde(skip_serializing_if = "Option::is_none")] - prefix: Option<String>, + prefix: Option<BindingConfig>, + /// Additional prefix keys published for cross-version compatibility. + /// Older clients parse `prefix` as a single string and ignore this field; + /// new clients merge it into the effective prefix list. + #[serde(skip_serializing_if = "Option::is_none")] + extra_prefixes: Option<BindingConfig>, #[serde(skip_serializing_if = "Option::is_none")] help: Option<BindingConfig>, #[serde(skip_serializing_if = "Option::is_none")] @@ -592,8 +598,13 @@ pub(crate) struct KeysConfigOverlay { } impl KeysConfigOverlay { - pub(crate) fn set_prefix(&mut self, prefix: String) { - self.prefix = Some(prefix); + pub(crate) fn set_prefixes(&mut self, prefixes: &[super::keybinds::KeyCombo]) { + let mut labels = prefixes + .iter() + .map(|combo| super::keybinds::format_key_combo(*combo)); + self.prefix = Some(BindingConfig::One(labels.next().unwrap_or_default())); + let extra: Vec<String> = labels.collect(); + self.extra_prefixes = (!extra.is_empty()).then_some(BindingConfig::Many(extra)); } } @@ -605,6 +616,25 @@ impl<'de> Deserialize<'de> for KeysConfig { let input = KeysConfigOverlay::deserialize(deserializer)?; let mut keys = KeysConfig::default(); + let prefix_was_supplied = input.prefix.is_some() || input.extra_prefixes.is_some(); + let mut prefix_values = Vec::new(); + if let Some(prefix) = input.prefix { + prefix_values.extend(prefix.into_values()); + } + if let Some(extra) = input.extra_prefixes { + prefix_values.extend(extra.into_values()); + } + if prefix_was_supplied { + // An explicitly empty list stays empty so prefix validation rejects + // it and a reload keeps the current keybindings. + keys.prefix = match prefix_values.len() { + 0 => BindingConfig::Many(Vec::new()), + 1 => BindingConfig::One(prefix_values.remove(0)), + _ => BindingConfig::Many(prefix_values), + }; + keys.user_fields.insert("prefix"); + } + macro_rules! apply_field { ($field:ident) => { if let Some(value) = input.$field { @@ -614,7 +644,6 @@ impl<'de> Deserialize<'de> for KeysConfig { }; } - apply_field!(prefix); apply_field!(help); apply_field!(settings); apply_field!(new_workspace); @@ -1088,7 +1117,7 @@ pub struct ExperimentalConfig { impl Default for KeysConfig { fn default() -> Self { Self { - prefix: "ctrl+b".into(), + prefix: BindingConfig::one("ctrl+b"), help: BindingConfig::one("prefix+?"), settings: BindingConfig::one("prefix+s"), new_workspace: BindingConfig::one("prefix+shift+n"), |
