use std::fmt;
use bitflags::bitflags;
bitflags! {
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Modifiers: u8 {
const CTRL = 0b0001;
const ALT = 0b0010;
const SHIFT = 0b0100;
}
}
use crossterm::event::KeyModifiers;
impl From<KeyModifiers> for Modifiers {
fn from(value: KeyModifiers) -> Self {
let mut mods = Modifiers::empty();
if value.contains(KeyModifiers::CONTROL) {
mods |= Modifiers::CTRL;
}
if value.contains(KeyModifiers::ALT) {
mods |= Modifiers::ALT;
}
if value.contains(KeyModifiers::SHIFT) {
mods |= Modifiers::SHIFT;
}
mods
}
}
impl fmt::Display for Modifiers {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut first = true;
if self.contains(Modifiers::CTRL) {
write!(f, "Ctrl")?;
first = false;
}
if self.contains(Modifiers::ALT) {
if !first {
write!(f, "+")?;
}
write!(f, "Alt")?;
first = false;
}
if self.contains(Modifiers::SHIFT) {
if !first {
write!(f, "+")?;
}
write!(f, "Shift")?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn from_empty() {
assert!(Modifiers::from(KeyModifiers::empty()).is_empty());
}
#[test]
fn from_ctrl() {
assert!(Modifiers::from(KeyModifiers::CONTROL).contains(Modifiers::CTRL));
}
#[test]
fn from_alt() {
assert!(Modifiers::from(KeyModifiers::ALT).contains(Modifiers::ALT));
}
#[test]
fn from_shift() {
assert!(Modifiers::from(KeyModifiers::SHIFT).contains(Modifiers::SHIFT));
}
#[test]
fn from_ctrl_does_not_set_alt_or_shift() {
let m = Modifiers::from(KeyModifiers::CONTROL);
assert!(!m.contains(Modifiers::ALT));
assert!(!m.contains(Modifiers::SHIFT));
}
#[test]
fn from_ctrl_alt() {
let m = Modifiers::from(KeyModifiers::CONTROL | KeyModifiers::ALT);
assert!(m.contains(Modifiers::CTRL));
assert!(m.contains(Modifiers::ALT));
assert!(!m.contains(Modifiers::SHIFT));
}
#[test]
fn from_ctrl_shift() {
let m = Modifiers::from(KeyModifiers::CONTROL | KeyModifiers::SHIFT);
assert!(m.contains(Modifiers::CTRL));
assert!(!m.contains(Modifiers::ALT));
assert!(m.contains(Modifiers::SHIFT));
}
#[test]
fn from_alt_shift() {
let m = Modifiers::from(KeyModifiers::ALT | KeyModifiers::SHIFT);
assert!(!m.contains(Modifiers::CTRL));
assert!(m.contains(Modifiers::ALT));
assert!(m.contains(Modifiers::SHIFT));
}
#[test]
fn from_all() {
let m = Modifiers::from(KeyModifiers::CONTROL | KeyModifiers::ALT | KeyModifiers::SHIFT);
assert!(m.contains(Modifiers::CTRL));
assert!(m.contains(Modifiers::ALT));
assert!(m.contains(Modifiers::SHIFT));
}
#[test]
fn display_empty() {
assert_eq!(Modifiers::empty().to_string(), "");
}
#[test]
fn display_ctrl() {
assert_eq!(Modifiers::CTRL.to_string(), "Ctrl");
}
#[test]
fn display_alt() {
assert_eq!(Modifiers::ALT.to_string(), "Alt");
}
#[test]
fn display_shift() {
assert_eq!(Modifiers::SHIFT.to_string(), "Shift");
}
#[test]
fn display_ctrl_alt() {
assert_eq!((Modifiers::CTRL | Modifiers::ALT).to_string(), "Ctrl+Alt");
}
#[test]
fn display_ctrl_shift() {
assert_eq!(
(Modifiers::CTRL | Modifiers::SHIFT).to_string(),
"Ctrl+Shift"
);
}
#[test]
fn display_alt_shift() {
assert_eq!(
(Modifiers::ALT | Modifiers::SHIFT).to_string(),
"Alt+Shift"
);
}
#[test]
fn display_all() {
assert_eq!(
(Modifiers::CTRL | Modifiers::ALT | Modifiers::SHIFT).to_string(),
"Ctrl+Alt+Shift"
);
}
#[test]
fn default_is_empty() {
assert!(Modifiers::default().is_empty());
}
}