use reovim_driver_input::{KeyCode, KeyEvent, KeySequence, Modifiers};
#[must_use]
#[cfg_attr(coverage_nightly, coverage(off))]
pub fn key_to_notation(key: &KeyEvent) -> String {
let has_ctrl = key.modifiers.contains(Modifiers::CTRL);
let has_alt = key.modifiers.contains(Modifiers::ALT);
let has_shift = key.modifiers.contains(Modifiers::SHIFT);
let has_any_mod = has_ctrl || has_alt || has_shift;
let mut prefix = String::new();
if has_ctrl {
prefix.push_str("C-");
}
if has_alt {
prefix.push_str("A-");
}
if has_shift {
prefix.push_str("S-");
}
match key.code {
KeyCode::Char(c) => {
if has_any_mod {
format!("<{prefix}{c}>")
} else if c == '<' {
"<lt>".to_string()
} else if c == '>' {
"<gt>".to_string()
} else {
c.to_string()
}
}
KeyCode::Escape => format!("<{prefix}Esc>"),
KeyCode::Enter => format!("<{prefix}Enter>"),
KeyCode::Tab => format!("<{prefix}Tab>"),
KeyCode::Backspace => format!("<{prefix}BS>"),
KeyCode::Delete => format!("<{prefix}Del>"),
KeyCode::Up => format!("<{prefix}Up>"),
KeyCode::Down => format!("<{prefix}Down>"),
KeyCode::Left => format!("<{prefix}Left>"),
KeyCode::Right => format!("<{prefix}Right>"),
KeyCode::Home => format!("<{prefix}Home>"),
KeyCode::End => format!("<{prefix}End>"),
KeyCode::PageUp => format!("<{prefix}PageUp>"),
KeyCode::PageDown => format!("<{prefix}PageDown>"),
KeyCode::F(n) => format!("<{prefix}F{n}>"),
KeyCode::BackTab => "<S-Tab>".to_string(),
_ => "<?>".to_string(),
}
}
#[must_use]
pub fn keys_to_notation(keys: &[KeyEvent]) -> String {
keys.iter().map(key_to_notation).collect()
}
#[must_use]
pub fn notation_to_keys(notation: &str) -> Option<Vec<KeyEvent>> {
let seq = KeySequence::parse(notation)?;
Some(seq.as_slice().to_vec())
}
#[derive(Debug, Clone, Default)]
pub struct MacroContent {
pub keys: Vec<KeyEvent>,
}
impl MacroContent {
#[must_use]
pub const fn new(keys: Vec<KeyEvent>) -> Self {
Self { keys }
}
#[must_use]
pub const fn empty() -> Self {
Self { keys: Vec::new() }
}
#[must_use]
#[allow(clippy::missing_const_for_fn)] pub fn is_empty(&self) -> bool {
self.keys.is_empty()
}
#[must_use]
#[allow(clippy::missing_const_for_fn)] pub fn len(&self) -> usize {
self.keys.len()
}
#[must_use]
pub fn to_notation(&self) -> String {
keys_to_notation(&self.keys)
}
#[must_use]
pub fn from_notation(notation: &str) -> Option<Self> {
notation_to_keys(notation).map(Self::new)
}
}
impl std::fmt::Display for MacroContent {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.to_notation())
}
}