diff --git a/Cargo.lock b/Cargo.lock index 8acc243..2669eeb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1191,7 +1191,7 @@ dependencies = [ [[package]] name = "otree" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "base64", diff --git a/Cargo.toml b/Cargo.toml index f793d60..2fb515f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "otree" -version = "0.7.0" +version = "0.7.1" edition = "2021" build = "build.rs" license = "MIT" diff --git a/src/config/keys.rs b/src/config/keys.rs index 630aab8..09a889a 100644 --- a/src/config/keys.rs +++ b/src/config/keys.rs @@ -1,7 +1,7 @@ use std::collections::HashSet; use anyhow::{bail, Context, Result}; -use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; +use crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers}; use serde::{Deserialize, Serialize}; macro_rules! generate_keys_default { @@ -361,6 +361,12 @@ pub struct KeyAction { impl Keys { pub fn get_key_action(&self, event: KeyEvent) -> Option { + // Windows emits both press and release key events. Treating release as + // an action would make each key press run twice. + if matches!(event.kind, KeyEventKind::Release) { + return None; + } + let event_key = Key::from_event(event)?; let mut current_action = None; for (keys, action) in &self.actions { @@ -376,3 +382,44 @@ impl Keys { }) } } + +#[cfg(test)] +mod tests { + use super::*; + + fn parsed_keys() -> Keys { + let mut keys = Keys::default(); + keys.parse().unwrap(); + keys + } + + #[test] + fn key_press_events_are_mapped() { + let keys = parsed_keys(); + let event = KeyEvent::new_with_kind(KeyCode::Up, KeyModifiers::NONE, KeyEventKind::Press); + + let action = keys.get_key_action(event).unwrap(); + + assert_eq!(action.key, Key::Up); + assert!(matches!(action.action, Some(Action::MoveUp))); + } + + #[test] + fn key_repeat_events_are_mapped() { + let keys = parsed_keys(); + let event = KeyEvent::new_with_kind(KeyCode::Up, KeyModifiers::NONE, KeyEventKind::Repeat); + + let action = keys.get_key_action(event).unwrap(); + + assert_eq!(action.key, Key::Up); + assert!(matches!(action.action, Some(Action::MoveUp))); + } + + #[test] + fn key_release_events_are_ignored() { + let keys = parsed_keys(); + let event = KeyEvent::new_with_kind(KeyCode::Up, KeyModifiers::NONE, KeyEventKind::Release); + + assert!(keys.get_key_action(event).is_none()); + } +}