use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(transparent)]
pub struct KeyTableName(pub String);
impl Default for KeyTableName {
fn default() -> Self {
Self::root()
}
}
impl KeyTableName {
pub fn root() -> Self {
Self("root".into())
}
pub fn prefix() -> Self {
Self("prefix".into())
}
pub fn copy() -> Self {
Self("copy".into())
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(transparent)]
pub struct KeyChord(pub String);
impl KeyChord {
pub fn from_tmux(s: &str) -> Self {
let mut parts: Vec<String> = Vec::new();
let mut key = String::new();
for seg in s.split('-') {
match seg {
"C" | "c" => parts.push("ctrl".into()),
"M" | "m" => parts.push("alt".into()),
"S" | "s" => parts.push("shift".into()),
"D" | "d" => parts.push("super".into()),
other => key = other.to_ascii_lowercase(),
}
}
parts.push(key);
Self(parts.join("+"))
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "kebab-case")]
pub enum Action {
SplitPane { direction: crate::Direction },
SendKeys { keys: String },
Command { cmd: String },
SelectPane { direction: crate::Direction },
NextWindow,
PreviousWindow,
NewWindow,
KillPane,
KillWindow,
KillSession,
Detach,
ReloadConfig,
EnterTable { table: KeyTableName },
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct KeyBind {
pub chord: KeyChord,
pub action: Action,
#[serde(default)]
pub note: String,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct KeyTable {
pub name: KeyTableName,
pub bindings: Vec<KeyBind>,
}
pub type KeyTableMap = BTreeMap<KeyTableName, KeyTable>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn from_tmux_normalises_chord_shorthand() {
assert_eq!(KeyChord::from_tmux("C-a").0, "ctrl+a");
assert_eq!(KeyChord::from_tmux("M-Left").0, "alt+left");
assert_eq!(KeyChord::from_tmux("C-M-x").0, "ctrl+alt+x");
}
}