keyboard-codes 0.2.0

Cross-platform keyboard key code mapping and conversion
Documentation
use lazy_static::lazy_static;
use std::collections::HashMap;

lazy_static! {
    /// Modifier alias mapping (alias -> standard name)
    pub static ref MODIFIER_ALIASES: HashMap<&'static str, &'static str> = {
        let mut map = HashMap::new();

        // Control aliases
        map.insert("ctrl", "Control");
        map.insert("ctl", "Control");

        // Shift aliases
        map.insert("shft", "Shift");

        // Alt aliases
        map.insert("altgr", "Alt");
        map.insert("opt", "Alt");
        map.insert("option", "Alt");

        // Meta aliases (cross-platform compatibility)
        map.insert("win", "Meta");
        map.insert("windows", "Meta");
        map.insert("cmd", "Meta");
        map.insert("command", "Meta");
        map.insert("super", "Meta");

        // Left modifier aliases
        map.insert("lctrl", "LeftControl");
        map.insert("lctl", "LeftControl");
        map.insert("lshift", "LeftShift");
        map.insert("lshft", "LeftShift");
        map.insert("lalt", "LeftAlt");
        map.insert("lopt", "LeftAlt");
        map.insert("loption", "LeftAlt");
        map.insert("lmeta", "LeftMeta");
        map.insert("lwin", "LeftMeta");
        map.insert("lcmd", "LeftMeta");
        map.insert("lcommand", "LeftMeta");

        // Right modifier aliases
        map.insert("rctrl", "RightControl");
        map.insert("rctl", "RightControl");
        map.insert("rshift", "RightShift");
        map.insert("rshft", "RightShift");
        map.insert("ralt", "RightAlt");
        map.insert("ropt", "RightAlt");
        map.insert("roption", "RightAlt");
        map.insert("rmeta", "RightMeta");
        map.insert("rwin", "RightMeta");
        map.insert("rcmd", "RightMeta");
        map.insert("rcommand", "RightMeta");

        map
    };

    /// Key alias mapping (alias -> standard name)
    pub static ref KEY_ALIASES: HashMap<&'static str, &'static str> = {
        let mut map = HashMap::new();

        // Function key aliases
        map.insert("esc", "Escape");
        map.insert("return", "Enter");
        map.insert("back", "Backspace");
        map.insert("bs", "Backspace");
        map.insert("del", "Delete");
        map.insert("ins", "Insert");

        // Navigation key aliases
        map.insert("pgup", "PageUp");
        map.insert("pgdn", "PageDown");
        map.insert("pagedown", "PageDown");

        // Arrow key aliases
        map.insert("left", "ArrowLeft");
        map.insert("right", "ArrowRight");
        map.insert("up", "ArrowUp");
        map.insert("down", "ArrowDown");

        // Digit key aliases
        map.insert("0", "D0");
        map.insert("1", "D1");
        map.insert("2", "D2");
        map.insert("3", "D3");
        map.insert("4", "D4");
        map.insert("5", "D5");
        map.insert("6", "D6");
        map.insert("7", "D7");
        map.insert("8", "D8");
        map.insert("9", "D9");

        map
    };
}

/// Normalize modifier name using alias mapping
pub fn normalize_modifier_name(input: &str) -> &str {
    let input_lower = input.to_lowercase();
    MODIFIER_ALIASES
        .get(input_lower.as_str())
        .copied()
        .unwrap_or(input)
}

/// Normalize key name using alias mapping
pub fn normalize_key_name(input: &str) -> &str {
    let input_lower = input.to_lowercase();
    KEY_ALIASES
        .get(input_lower.as_str())
        .copied()
        .unwrap_or(input)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_normalize_modifier_name() {
        assert_eq!(normalize_modifier_name("ctrl"), "Control");
        assert_eq!(normalize_modifier_name("Cmd"), "Meta");
        assert_eq!(normalize_modifier_name("unknown"), "unknown");
    }

    #[test]
    fn test_normalize_key_name() {
        assert_eq!(normalize_key_name("esc"), "Escape");
        assert_eq!(normalize_key_name("return"), "Enter");
        assert_eq!(normalize_key_name("left"), "ArrowLeft");
        assert_eq!(normalize_key_name("0"), "D0");
    }
}