kbt 2.0.3

Keyboard tester in terminal
use std::sync::{mpsc::Sender, Arc, Mutex};

use device_query_revamped::{CallbackGuard, DeviceEvents, DeviceState, Keycode};

use crate::{
    key::Key,
    model::{AppEvent, KeyEventType},
};

pub struct GenericKeyBackend;

type KeycodeCallback = Box<dyn Fn(&Keycode) + Send + Sync + 'static>;
type KeyStreamGuard = CallbackGuard<KeycodeCallback>;

impl GenericKeyBackend {
    pub fn subscribe(sender: &Sender<AppEvent>) -> (KeyStreamGuard, KeyStreamGuard) {
        let device_state = DeviceState::new();
        let shared_sender = Arc::new(Mutex::new(sender.clone()));

        let key_up_guard: KeyStreamGuard = device_state.on_key_up(Box::new(move |keycode| {
            let _ = shared_sender
                .lock()
                .unwrap()
                .send(AppEvent::KeyEvent(KeyEventType::KeyReleased(map_keycode(
                    keycode,
                ))))
                .map_err(|err| log::error!("Key down channel died {}", err));
        }));

        let shared_sender = Arc::new(Mutex::new(sender.clone()));

        let key_down_guard: KeyStreamGuard = device_state.on_key_down(Box::new(move |keycode| {
            let _ = shared_sender
                .lock()
                .unwrap()
                .send(AppEvent::KeyEvent(KeyEventType::KeyPressed(map_keycode(
                    keycode,
                ))))
                .map_err(|err| log::error!("Key down channel died {}", err));
        }));

        (key_up_guard, key_down_guard)
    }
}

fn map_keycode(keycode: &Keycode) -> Key {
    match keycode {
        Keycode::Key0 => Key::Zero,
        Keycode::Key1 => Key::One,
        Keycode::Key2 => Key::Two,
        Keycode::Key3 => Key::Three,
        Keycode::Key4 => Key::Four,
        Keycode::Key5 => Key::Five,
        Keycode::Key6 => Key::Six,
        Keycode::Key7 => Key::Seven,
        Keycode::Key8 => Key::Eight,
        Keycode::Key9 => Key::Nine,
        Keycode::A => Key::A,
        Keycode::B => Key::B,
        Keycode::C => Key::C,
        Keycode::D => Key::D,
        Keycode::E => Key::E,
        Keycode::F => Key::F,
        Keycode::G => Key::G,
        Keycode::H => Key::H,
        Keycode::I => Key::I,
        Keycode::J => Key::J,
        Keycode::K => Key::K,
        Keycode::L => Key::L,
        Keycode::M => Key::M,
        Keycode::N => Key::N,
        Keycode::O => Key::O,
        Keycode::P => Key::P,
        Keycode::Q => Key::Q,
        Keycode::R => Key::R,
        Keycode::S => Key::S,
        Keycode::T => Key::T,
        Keycode::U => Key::U,
        Keycode::V => Key::V,
        Keycode::W => Key::W,
        Keycode::X => Key::X,
        Keycode::Y => Key::Y,
        Keycode::Z => Key::Z,
        Keycode::F1 => Key::F1,
        Keycode::F2 => Key::F2,
        Keycode::F3 => Key::F3,
        Keycode::F4 => Key::F4,
        Keycode::F5 => Key::F5,
        Keycode::F6 => Key::F6,
        Keycode::F7 => Key::F7,
        Keycode::F8 => Key::F8,
        Keycode::F9 => Key::F9,
        Keycode::F10 => Key::F10,
        Keycode::F11 => Key::F11,
        Keycode::F12 => Key::F12,
        Keycode::Escape => Key::Esc,
        Keycode::Space => Key::Spacebar,
        Keycode::LControl => Key::LeftCtrl,
        Keycode::RControl => Key::RightCtrl,
        Keycode::LShift => Key::LeftShift,
        Keycode::RShift => Key::RightShift,
        Keycode::LAlt => Key::LeftAlt,
        Keycode::RAlt => Key::RightAlt,
        Keycode::Command => Key::Command,
        Keycode::LMeta => Key::LeftSuper,
        Keycode::RMeta => Key::RightSuper,
        Keycode::Enter => Key::Return,
        Keycode::Up => Key::ArrowUp,
        Keycode::Down => Key::ArrowDown,
        Keycode::Left => Key::ArrowLeft,
        Keycode::Right => Key::ArrowRight,
        Keycode::Backspace => Key::Backspace,
        Keycode::CapsLock => Key::CapsLock,
        Keycode::Tab => Key::Tab,
        Keycode::Home => Key::Home,
        Keycode::End => Key::End,
        Keycode::PageUp => Key::PgUp,
        Keycode::PageDown => Key::PgDown,
        Keycode::Insert => Key::Insert,
        Keycode::Delete => Key::Delete,
        Keycode::Grave => Key::Grave,
        Keycode::Minus => Key::Hyphen,
        Keycode::Equal => Key::Equal,
        Keycode::LeftBracket => Key::LeftBracket,
        Keycode::RightBracket => Key::RightBracket,
        Keycode::BackSlash => Key::Backslash,
        Keycode::Semicolon => Key::SemiColon,
        Keycode::Apostrophe => Key::Apostrophe,
        Keycode::Comma => Key::Comma,
        Keycode::Dot => Key::Period,
        Keycode::Slash => Key::QuestionMark,
        Keycode::NumpadDivide => Key::Div,
        Keycode::NumpadMultiply => Key::Mul,
        Keycode::NumpadSubtract => Key::Minus,
        Keycode::NumpadAdd => Key::Plus,
        Keycode::Numpad0 => Key::NumpadZero,
        Keycode::Numpad1 => Key::NumpadOne,
        Keycode::Numpad2 => Key::NumpadTwo,
        Keycode::Numpad3 => Key::NumpadThree,
        Keycode::Numpad4 => Key::NumpadFour,
        Keycode::Numpad5 => Key::NumpadFive,
        Keycode::Numpad6 => Key::NumpadSix,
        Keycode::Numpad7 => Key::NumpadSeven,
        Keycode::Numpad8 => Key::NumpadEight,
        Keycode::Numpad9 => Key::NumpadNine,
        Keycode::Numlock => Key::NumLock,
        Keycode::NumpadDecimal => Key::Decimal,
        Keycode::NumpadEnter => Key::NumpadEnter,
        Keycode::Scroll => Key::ScrollLock,
        Keycode::Print => Key::PrintScreen,
        Keycode::Pause => Key::PauseBreak,
    }
}