use std::collections::HashMap;
use crossterm::event::{KeyCode, KeyModifiers};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct InputStr(pub String);
impl From<crossterm::event::KeyEvent> for InputStr {
fn from(event: crossterm::event::KeyEvent) -> Self {
let mut s = String::new();
let is_char = |e: crossterm::event::KeyEvent| matches!(e.code, KeyCode::Char(_));
if event.modifiers & KeyModifiers::CONTROL != KeyModifiers::NONE {
s.push_str("C-");
}
if event.modifiers & KeyModifiers::SHIFT != KeyModifiers::NONE && !is_char(event) {
s.push_str("S-");
}
if event.modifiers & KeyModifiers::ALT != KeyModifiers::NONE {
s.push_str("A-");
}
use KeyCode::*;
match event.code {
Char(c) => {
s.push(c);
}
other => s.push_str(&format!("{:?}", other).to_lowercase()),
}
InputStr(s)
}
}
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct Shortcuts(pub HashMap<InputStr, crate::command::Command>);
impl Shortcuts {
pub fn new(map: HashMap<InputStr, crate::command::Command>) -> Self {
Self(map)
}
pub fn get_from_event(
&self,
event: crossterm::event::KeyEvent,
) -> Option<crate::command::Command> {
self.0.get(&event.into()).cloned()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyEventState, KeyModifiers};
fn key_event(modifiers: KeyModifiers, code: KeyCode) -> KeyEvent {
KeyEvent {
code,
modifiers,
kind: KeyEventKind::Press,
state: KeyEventState::NONE,
}
}
#[test]
fn test_input_str() {
assert_eq!(
InputStr::from(key_event(KeyModifiers::NONE, KeyCode::Char('a'))),
InputStr("a".into())
);
assert_eq!(
InputStr::from(key_event(KeyModifiers::CONTROL, KeyCode::Char('a'))),
InputStr("C-a".into())
);
assert_eq!(
InputStr::from(key_event(KeyModifiers::SHIFT, KeyCode::Char('B'))),
InputStr("B".into())
);
assert_eq!(
InputStr::from(key_event(
KeyModifiers::CONTROL | KeyModifiers::SHIFT,
KeyCode::Char('!')
)),
InputStr("C-!".into())
);
assert_eq!(
InputStr::from(key_event(KeyModifiers::ALT, KeyCode::Enter)),
InputStr("A-enter".into())
);
assert_eq!(
InputStr::from(key_event(
KeyModifiers::CONTROL | KeyModifiers::SHIFT,
KeyCode::Tab
)),
InputStr("C-S-tab".into())
);
}
}