use crossterm::event::KeyModifiers;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct ModifierKeysMask {
pub shift_key_state: KeyState,
pub ctrl_key_state: KeyState,
pub alt_key_state: KeyState,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum KeyState {
Pressed,
#[default]
NotPressed,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MatchResult {
Matches,
DoesNotMatch,
}
impl From<bool> for MatchResult {
fn from(other: bool) -> Self {
if other {
MatchResult::Matches
} else {
MatchResult::DoesNotMatch
}
}
}
impl ModifierKeysMask {
#[must_use]
pub fn with_shift(mut self) -> Self {
self.shift_key_state = KeyState::Pressed;
self
}
#[must_use]
pub fn with_ctrl(mut self) -> Self {
self.ctrl_key_state = KeyState::Pressed;
self
}
#[must_use]
pub fn with_alt(mut self) -> Self {
self.alt_key_state = KeyState::Pressed;
self
}
#[must_use]
pub fn new() -> Self {
ModifierKeysMask {
shift_key_state: KeyState::NotPressed,
ctrl_key_state: KeyState::NotPressed,
alt_key_state: KeyState::NotPressed,
}
}
pub fn matches(&self, arg_mask: impl Into<ModifierKeysMask>) -> MatchResult {
let other: ModifierKeysMask = arg_mask.into();
if *self == other {
MatchResult::Matches
} else {
MatchResult::DoesNotMatch
}
}
}
#[must_use]
pub fn try_convert_key_modifiers(modifiers: &KeyModifiers) -> Option<ModifierKeysMask> {
if modifiers.is_empty() {
None
} else {
Some(ModifierKeysMask::from(*modifiers))
}
}
impl From<KeyModifiers> for ModifierKeysMask {
fn from(other: KeyModifiers) -> ModifierKeysMask {
let mut it: ModifierKeysMask = ModifierKeysMask {
shift_key_state: KeyState::NotPressed,
ctrl_key_state: KeyState::NotPressed,
alt_key_state: KeyState::NotPressed,
};
if other.intersects(KeyModifiers::SHIFT) {
it.shift_key_state = KeyState::Pressed;
}
if other.intersects(KeyModifiers::CONTROL) {
it.ctrl_key_state = KeyState::Pressed;
}
if other.intersects(KeyModifiers::ALT) {
it.alt_key_state = KeyState::Pressed;
}
it
}
}
#[cfg(test)]
mod tests_modifier_keys_mask {
use super::*;
use crate::assert_eq2;
#[test]
fn test_empty_mask() {
let mask = ModifierKeysMask::new();
assert_eq2!(mask.shift_key_state, KeyState::NotPressed);
assert_eq2!(mask.ctrl_key_state, KeyState::NotPressed);
assert_eq2!(mask.alt_key_state, KeyState::NotPressed);
assert_eq2!(mask.matches(KeyModifiers::SHIFT), MatchResult::DoesNotMatch);
assert_eq2!(
mask.matches(KeyModifiers::CONTROL),
MatchResult::DoesNotMatch
);
assert_eq2!(mask.matches(KeyModifiers::ALT), MatchResult::DoesNotMatch);
}
#[test]
fn test_shift_mask() {
let mask = ModifierKeysMask::new().with_shift();
assert_eq2!(mask.shift_key_state, KeyState::Pressed);
assert_eq2!(mask.ctrl_key_state, KeyState::NotPressed);
assert_eq2!(mask.alt_key_state, KeyState::NotPressed);
assert_eq2!(mask.matches(KeyModifiers::SHIFT), MatchResult::Matches);
assert_eq2!(
mask.matches(KeyModifiers::CONTROL),
MatchResult::DoesNotMatch
);
assert_eq2!(mask.matches(KeyModifiers::ALT), MatchResult::DoesNotMatch);
}
#[test]
fn test_ctrl_mask() {
let mask = ModifierKeysMask::new().with_ctrl();
assert_eq2!(mask.shift_key_state, KeyState::NotPressed);
assert_eq2!(mask.ctrl_key_state, KeyState::Pressed);
assert_eq2!(mask.alt_key_state, KeyState::NotPressed);
assert_eq2!(mask.matches(KeyModifiers::SHIFT), MatchResult::DoesNotMatch);
assert_eq2!(mask.matches(KeyModifiers::CONTROL), MatchResult::Matches);
assert_eq2!(mask.matches(KeyModifiers::ALT), MatchResult::DoesNotMatch);
}
#[test]
fn test_alt_mask() {
let mask = ModifierKeysMask::new().with_alt();
assert_eq2!(mask.shift_key_state, KeyState::NotPressed);
assert_eq2!(mask.ctrl_key_state, KeyState::NotPressed);
assert_eq2!(mask.alt_key_state, KeyState::Pressed);
assert_eq2!(mask.matches(KeyModifiers::SHIFT), MatchResult::DoesNotMatch);
assert_eq2!(
mask.matches(KeyModifiers::CONTROL),
MatchResult::DoesNotMatch
);
assert_eq2!(mask.matches(KeyModifiers::ALT), MatchResult::Matches);
}
#[test]
fn test_shift_ctrl_mask() {
let mask = ModifierKeysMask::new().with_shift().with_ctrl();
assert_eq2!(mask.shift_key_state, KeyState::Pressed);
assert_eq2!(mask.ctrl_key_state, KeyState::Pressed);
assert_eq2!(mask.alt_key_state, KeyState::NotPressed);
assert_eq2!(
mask.matches(KeyModifiers::SHIFT | KeyModifiers::CONTROL),
MatchResult::Matches
);
assert_eq2!(mask.matches(KeyModifiers::SHIFT), MatchResult::DoesNotMatch);
assert_eq2!(
mask.matches(KeyModifiers::CONTROL),
MatchResult::DoesNotMatch
);
assert_eq2!(mask.matches(KeyModifiers::ALT), MatchResult::DoesNotMatch);
}
#[test]
fn test_shift_alt_mask() {
let mask = ModifierKeysMask::new().with_shift().with_alt();
assert_eq2!(mask.shift_key_state, KeyState::Pressed);
assert_eq2!(mask.ctrl_key_state, KeyState::NotPressed);
assert_eq2!(mask.alt_key_state, KeyState::Pressed);
assert_eq2!(mask.matches(KeyModifiers::SHIFT), MatchResult::DoesNotMatch);
assert_eq2!(
mask.matches(KeyModifiers::CONTROL),
MatchResult::DoesNotMatch
);
assert_eq2!(mask.matches(KeyModifiers::ALT), MatchResult::DoesNotMatch);
assert_eq2!(
mask.matches(KeyModifiers::SHIFT | KeyModifiers::ALT),
MatchResult::Matches
);
}
#[test]
fn test_ctrl_alt_mask() {
let mask = ModifierKeysMask::new().with_ctrl().with_alt();
assert_eq2!(mask.shift_key_state, KeyState::NotPressed);
assert_eq2!(mask.ctrl_key_state, KeyState::Pressed);
assert_eq2!(mask.alt_key_state, KeyState::Pressed);
assert_eq2!(mask.matches(KeyModifiers::SHIFT), MatchResult::DoesNotMatch);
assert_eq2!(
mask.matches(KeyModifiers::CONTROL),
MatchResult::DoesNotMatch
);
assert_eq2!(mask.matches(KeyModifiers::ALT), MatchResult::DoesNotMatch);
assert_eq2!(
mask.matches(KeyModifiers::CONTROL | KeyModifiers::ALT),
MatchResult::Matches
);
}
#[test]
fn test_shift_ctrl_alt_mask() {
let mask = ModifierKeysMask::new().with_shift().with_ctrl().with_alt();
assert_eq2!(mask.shift_key_state, KeyState::Pressed);
assert_eq2!(mask.ctrl_key_state, KeyState::Pressed);
assert_eq2!(mask.alt_key_state, KeyState::Pressed);
assert_eq2!(mask.matches(KeyModifiers::SHIFT), MatchResult::DoesNotMatch);
assert_eq2!(
mask.matches(KeyModifiers::CONTROL),
MatchResult::DoesNotMatch
);
assert_eq2!(mask.matches(KeyModifiers::ALT), MatchResult::DoesNotMatch);
assert_eq2!(
mask.matches(KeyModifiers::SHIFT | KeyModifiers::CONTROL | KeyModifiers::ALT),
MatchResult::Matches
);
}
}