aboutsummaryrefslogtreecommitdiff
path: root/src/config/model.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/config/model.rs')
-rw-r--r--src/config/model.rs43
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"),