KeyEvent case normalizing equality (#541)
This commit is contained in:
parent
58f580eaad
commit
92f62ba86f
82
src/event.rs
82
src/event.rs
@ -73,6 +73,7 @@
|
||||
//! them (`event-*`).
|
||||
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::time::Duration;
|
||||
|
||||
use bitflags::bitflags;
|
||||
@ -385,7 +386,7 @@ bitflags! {
|
||||
|
||||
/// Represents a key event.
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
|
||||
#[derive(Debug, PartialOrd, Clone, Copy)]
|
||||
pub struct KeyEvent {
|
||||
/// The key itself.
|
||||
pub code: KeyCode,
|
||||
@ -397,6 +398,23 @@ impl KeyEvent {
|
||||
pub fn new(code: KeyCode, modifiers: KeyModifiers) -> KeyEvent {
|
||||
KeyEvent { code, modifiers }
|
||||
}
|
||||
|
||||
// modifies the KeyEvent,
|
||||
// so that KeyModifiers::SHIFT is present iff
|
||||
// an uppercase char is present.
|
||||
fn normalize_case(mut self) -> KeyEvent {
|
||||
let c = match self.code {
|
||||
KeyCode::Char(c) => c,
|
||||
_ => return self,
|
||||
};
|
||||
|
||||
if c.is_ascii_uppercase() {
|
||||
self.modifiers.insert(KeyModifiers::SHIFT);
|
||||
} else if self.modifiers.contains(KeyModifiers::SHIFT) {
|
||||
self.code = KeyCode::Char(c.to_ascii_uppercase())
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl From<KeyCode> for KeyEvent {
|
||||
@ -408,6 +426,30 @@ impl From<KeyCode> for KeyEvent {
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for KeyEvent {
|
||||
fn eq(&self, other: &KeyEvent) -> bool {
|
||||
let KeyEvent {
|
||||
code: lhs_code,
|
||||
modifiers: lhs_modifiers,
|
||||
} = self.normalize_case();
|
||||
let KeyEvent {
|
||||
code: rhs_code,
|
||||
modifiers: rhs_modifiers,
|
||||
} = other.normalize_case();
|
||||
(lhs_code == rhs_code) && (lhs_modifiers == rhs_modifiers)
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for KeyEvent {}
|
||||
|
||||
impl Hash for KeyEvent {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
let KeyEvent { code, modifiers } = self.normalize_case();
|
||||
code.hash(state);
|
||||
modifiers.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a key.
|
||||
#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
@ -466,3 +508,41 @@ pub(crate) enum InternalEvent {
|
||||
#[cfg(unix)]
|
||||
CursorPosition(u16, u16),
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
use super::{KeyCode, KeyEvent, KeyModifiers};
|
||||
|
||||
#[test]
|
||||
fn test_equality() {
|
||||
let lowercase_d_with_shift = KeyEvent::new(KeyCode::Char('d'), KeyModifiers::SHIFT);
|
||||
let uppercase_d_with_shift = KeyEvent::new(KeyCode::Char('D'), KeyModifiers::SHIFT);
|
||||
let uppercase_d = KeyEvent::new(KeyCode::Char('D'), KeyModifiers::NONE);
|
||||
assert_eq!(lowercase_d_with_shift, uppercase_d_with_shift);
|
||||
assert_eq!(uppercase_d, uppercase_d_with_shift);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hash() {
|
||||
let lowercase_d_with_shift_hash = {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
KeyEvent::new(KeyCode::Char('d'), KeyModifiers::SHIFT).hash(&mut hasher);
|
||||
hasher.finish()
|
||||
};
|
||||
let uppercase_d_with_shift_hash = {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
KeyEvent::new(KeyCode::Char('D'), KeyModifiers::SHIFT).hash(&mut hasher);
|
||||
hasher.finish()
|
||||
};
|
||||
let uppercase_d_hash = {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
KeyEvent::new(KeyCode::Char('D'), KeyModifiers::NONE).hash(&mut hasher);
|
||||
hasher.finish()
|
||||
};
|
||||
assert_eq!(lowercase_d_with_shift_hash, uppercase_d_with_shift_hash);
|
||||
assert_eq!(uppercase_d_hash, uppercase_d_with_shift_hash);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user