use serde::Deserialize; use std::collections::HashMap; #[derive(Debug, Clone, Deserialize)] pub struct KeymapEntry { pub scancode: u8, pub normal: char, pub shifted: char, #[serde(default)] pub altgr: char, #[serde(default)] pub altgr_shifted: char, } #[derive(Debug, Clone, Deserialize)] pub struct ComposeEntry { pub sequence: String, pub result: char, } #[derive(Debug, Clone, Deserialize)] pub struct DeadKeyEntry { pub dead_key: char, pub base: char, pub composed: char, } #[derive(Debug, Clone)] pub struct Keymap { pub name: String, pub entries: HashMap, pub compose: Vec, pub dead_keys: Vec, } impl Keymap { pub fn get_char(&self, scancode: u8, shift: bool, altgr: bool) -> char { if let Some(entry) = self.entries.get(&scancode) { if altgr && shift && entry.altgr_shifted != '\0' { return entry.altgr_shifted; } if altgr && entry.altgr != '\0' { return entry.altgr; } if shift { return entry.shifted; } return entry.normal; } '\0' } pub fn compose(&self, base: char, dead_key: char) -> char { for entry in &self.dead_keys { if entry.dead_key == dead_key && entry.base == base { return entry.composed; } } base } pub fn lookup_compose(&self, sequence: &str) -> Option { for entry in &self.compose { if entry.sequence == sequence { return Some(entry.result); } } None } pub fn from_json(name: &str, json_str: &str) -> Result { #[derive(Deserialize)] struct KeymapFile { #[serde(default)] entries: Vec, #[serde(default)] compose: Vec, #[serde(default)] dead_keys: Vec, } let file: KeymapFile = serde_json::from_str(json_str).map_err(|e| format!("parse error: {}", e))?; let mut map = HashMap::new(); for entry in file.entries { map.insert(entry.scancode, entry); } Ok(Keymap { name: name.to_string(), entries: map, compose: file.compose, dead_keys: file.dead_keys, }) } } pub struct BuiltinKeymaps { pub us: Keymap, pub gb: Keymap, pub dvorak: Keymap, pub azerty: Keymap, pub bepo: Keymap, pub it: Keymap, } impl BuiltinKeymaps { pub fn new() -> Self { BuiltinKeymaps { us: Self::make_us(), gb: Self::make_gb(), dvorak: Self::make_dvorak(), azerty: Self::make_azerty(), bepo: Self::make_bepo(), it: Self::make_it(), } } fn common_dead_keys() -> Vec { vec![ DeadKeyEntry { dead_key: '`', base: 'a', composed: 'à', }, DeadKeyEntry { dead_key: '`', base: 'e', composed: 'è', }, DeadKeyEntry { dead_key: '`', base: 'i', composed: 'ì', }, DeadKeyEntry { dead_key: '`', base: 'o', composed: 'ò', }, DeadKeyEntry { dead_key: '`', base: 'u', composed: 'ù', }, DeadKeyEntry { dead_key: '`', base: 'A', composed: 'À', }, DeadKeyEntry { dead_key: '`', base: 'E', composed: 'È', }, DeadKeyEntry { dead_key: '`', base: 'I', composed: 'Ì', }, DeadKeyEntry { dead_key: '`', base: 'O', composed: 'Ò', }, DeadKeyEntry { dead_key: '`', base: 'U', composed: 'Ù', }, DeadKeyEntry { dead_key: '\'', base: 'a', composed: 'á', }, DeadKeyEntry { dead_key: '\'', base: 'e', composed: 'é', }, DeadKeyEntry { dead_key: '\'', base: 'i', composed: 'í', }, DeadKeyEntry { dead_key: '\'', base: 'o', composed: 'ó', }, DeadKeyEntry { dead_key: '\'', base: 'u', composed: 'ú', }, DeadKeyEntry { dead_key: '\'', base: 'A', composed: 'Á', }, DeadKeyEntry { dead_key: '\'', base: 'E', composed: 'É', }, DeadKeyEntry { dead_key: '\'', base: 'I', composed: 'Í', }, DeadKeyEntry { dead_key: '\'', base: 'O', composed: 'Ó', }, DeadKeyEntry { dead_key: '\'', base: 'U', composed: 'Ú', }, DeadKeyEntry { dead_key: '^', base: 'a', composed: 'â', }, DeadKeyEntry { dead_key: '^', base: 'e', composed: 'ê', }, DeadKeyEntry { dead_key: '^', base: 'i', composed: 'î', }, DeadKeyEntry { dead_key: '^', base: 'o', composed: 'ô', }, DeadKeyEntry { dead_key: '^', base: 'u', composed: 'û', }, DeadKeyEntry { dead_key: '^', base: 'A', composed: 'Â', }, DeadKeyEntry { dead_key: '^', base: 'E', composed: 'Ê', }, DeadKeyEntry { dead_key: '^', base: 'I', composed: 'Î', }, DeadKeyEntry { dead_key: '^', base: 'O', composed: 'Ô', }, DeadKeyEntry { dead_key: '^', base: 'U', composed: 'Û', }, DeadKeyEntry { dead_key: '"', base: 'a', composed: 'ä', }, DeadKeyEntry { dead_key: '"', base: 'e', composed: 'ë', }, DeadKeyEntry { dead_key: '"', base: 'i', composed: 'ï', }, DeadKeyEntry { dead_key: '"', base: 'o', composed: 'ö', }, DeadKeyEntry { dead_key: '"', base: 'u', composed: 'ü', }, DeadKeyEntry { dead_key: '"', base: 'A', composed: 'Ä', }, DeadKeyEntry { dead_key: '"', base: 'E', composed: 'Ë', }, DeadKeyEntry { dead_key: '"', base: 'I', composed: 'Ï', }, DeadKeyEntry { dead_key: '"', base: 'O', composed: 'Ö', }, DeadKeyEntry { dead_key: '"', base: 'U', composed: 'Ü', }, DeadKeyEntry { dead_key: '~', base: 'a', composed: 'ã', }, DeadKeyEntry { dead_key: '~', base: 'n', composed: 'ñ', }, DeadKeyEntry { dead_key: '~', base: 'o', composed: 'õ', }, DeadKeyEntry { dead_key: '~', base: 'A', composed: 'Ã', }, DeadKeyEntry { dead_key: '~', base: 'N', composed: 'Ñ', }, DeadKeyEntry { dead_key: '~', base: 'O', composed: 'Õ', }, ] } fn make_us() -> Keymap { let mut entries = HashMap::new(); let bindings: &[(u8, char, char)] = &[ (0x01, '\x1B', '\x1B'), (0x02, '1', '!'), (0x03, '2', '@'), (0x04, '3', '#'), (0x05, '4', '$'), (0x06, '5', '%'), (0x07, '6', '^'), (0x08, '7', '&'), (0x09, '8', '*'), (0x0A, '9', '('), (0x0B, '0', ')'), (0x0C, '-', '_'), (0x0D, '=', '+'), (0x0E, '\x7F', '\x7F'), (0x0F, '\t', '\t'), (0x10, 'q', 'Q'), (0x11, 'w', 'W'), (0x12, 'e', 'E'), (0x13, 'r', 'R'), (0x14, 't', 'T'), (0x15, 'y', 'Y'), (0x16, 'u', 'U'), (0x17, 'i', 'I'), (0x18, 'o', 'O'), (0x19, 'p', 'P'), (0x1A, '[', '{'), (0x1B, ']', '}'), (0x1C, '\n', '\n'), (0x1E, 'a', 'A'), (0x1F, 's', 'S'), (0x20, 'd', 'D'), (0x21, 'f', 'F'), (0x22, 'g', 'G'), (0x23, 'h', 'H'), (0x24, 'j', 'J'), (0x25, 'k', 'K'), (0x26, 'l', 'L'), (0x27, ';', ':'), (0x28, '\'', '"'), (0x29, '`', '~'), (0x2B, '\\', '|'), (0x2C, 'z', 'Z'), (0x2D, 'x', 'X'), (0x2E, 'c', 'C'), (0x2F, 'v', 'V'), (0x30, 'b', 'B'), (0x31, 'n', 'N'), (0x32, 'm', 'M'), (0x33, ',', '<'), (0x34, '.', '>'), (0x35, '/', '?'), (0x39, ' ', ' '), ]; for &(sc, normal, shifted) in bindings { entries.insert( sc, KeymapEntry { scancode: sc, normal, shifted, altgr: '\0', altgr_shifted: '\0', }, ); } let dead_keys = Self::common_dead_keys(); Keymap { name: "us".into(), entries, compose: Vec::new(), dead_keys, } } fn make_gb() -> Keymap { let mut km = Self::make_us(); km.name = "gb".into(); if let Some(e) = km.entries.get_mut(&0x29) { e.shifted = '¬'; } if let Some(e) = km.entries.get_mut(&0x2B) { e.normal = '#'; e.shifted = '~'; } km } fn make_dvorak() -> Keymap { let mut entries = HashMap::new(); let remap: &[(u8, char, char)] = &[ (0x01, '\x1B', '\x1B'), (0x02, '1', '!'), (0x03, '2', '@'), (0x04, '3', '#'), (0x05, '4', '$'), (0x06, '5', '%'), (0x07, '6', '^'), (0x08, '7', '&'), (0x09, '8', '*'), (0x0A, '9', '('), (0x0B, '0', ')'), (0x0C, '[', '{'), (0x0D, ']', '}'), (0x0E, '\x7F', '\x7F'), (0x0F, '\t', '\t'), (0x10, '\'', '"'), (0x11, ',', '<'), (0x12, '.', '>'), (0x13, 'p', 'P'), (0x14, 'y', 'Y'), (0x15, 'f', 'F'), (0x16, 'g', 'G'), (0x17, 'c', 'C'), (0x18, 'r', 'R'), (0x19, 'l', 'L'), (0x1A, '/', '?'), (0x1B, '=', '+'), (0x1C, '\n', '\n'), (0x1E, 'a', 'A'), (0x1F, 'o', 'O'), (0x20, 'e', 'E'), (0x21, 'u', 'U'), (0x22, 'i', 'I'), (0x23, 'd', 'D'), (0x24, 'h', 'H'), (0x25, 't', 'T'), (0x26, 'n', 'N'), (0x27, 's', 'S'), (0x28, '-', '_'), (0x29, '`', '~'), (0x2B, '\\', '|'), (0x2C, ';', ':'), (0x2D, 'q', 'Q'), (0x2E, 'j', 'J'), (0x2F, 'k', 'K'), (0x30, 'x', 'X'), (0x31, 'b', 'B'), (0x32, 'm', 'M'), (0x33, 'w', 'W'), (0x34, 'v', 'V'), (0x35, 'z', 'Z'), (0x39, ' ', ' '), ]; for &(sc, normal, shifted) in remap { entries.insert( sc, KeymapEntry { scancode: sc, normal, shifted, altgr: '\0', altgr_shifted: '\0', }, ); } Keymap { name: "dvorak".into(), entries, compose: Vec::new(), dead_keys: Self::common_dead_keys(), } } fn make_azerty() -> Keymap { let mut entries = HashMap::new(); let bindings: &[(u8, char, char)] = &[ (0x01, '\x1B', '\x1B'), (0x02, '&', '1'), (0x03, 'é', '2'), (0x04, '"', '3'), (0x05, '\'', '4'), (0x06, '(', '5'), (0x07, '-', '6'), (0x08, 'è', '7'), (0x09, '_', '8'), (0x0A, 'ç', '9'), (0x0B, 'à', '0'), (0x0C, ')', '°'), (0x0D, '=', '+'), (0x0E, '\x7F', '\x7F'), (0x0F, '\t', '\t'), (0x10, 'a', 'A'), (0x11, 'z', 'Z'), (0x12, 'e', 'E'), (0x13, 'r', 'R'), (0x14, 't', 'T'), (0x15, 'y', 'Y'), (0x16, 'u', 'U'), (0x17, 'i', 'I'), (0x18, 'o', 'O'), (0x19, 'p', 'P'), (0x1A, '^', '¨'), (0x1B, '$', '£'), (0x1C, '\n', '\n'), (0x1E, 'q', 'Q'), (0x1F, 's', 'S'), (0x20, 'd', 'D'), (0x21, 'f', 'F'), (0x22, 'g', 'G'), (0x23, 'h', 'H'), (0x24, 'j', 'J'), (0x25, 'k', 'K'), (0x26, 'l', 'L'), (0x27, 'm', 'M'), (0x28, 'ù', '%'), (0x29, '²', '~'), (0x2B, '*', 'µ'), (0x2C, 'w', 'W'), (0x2D, 'x', 'X'), (0x2E, 'c', 'C'), (0x2F, 'v', 'V'), (0x30, 'b', 'B'), (0x31, 'n', 'N'), (0x32, ',', '?'), (0x33, ';', '.'), (0x34, ':', '/'), (0x35, '!', '§'), (0x39, ' ', ' '), ]; for &(sc, normal, shifted) in bindings { entries.insert( sc, KeymapEntry { scancode: sc, normal, shifted, altgr: '\0', altgr_shifted: '\0', }, ); } let mut dead_keys = Self::common_dead_keys(); dead_keys.push(DeadKeyEntry { dead_key: '^', base: ' ', composed: '^', }); dead_keys.push(DeadKeyEntry { dead_key: '¨', base: ' ', composed: '¨', }); Keymap { name: "azerty".into(), entries, compose: Vec::new(), dead_keys, } } fn make_bepo() -> Keymap { let mut entries = HashMap::new(); let bindings: &[(u8, char, char)] = &[ (0x01, '\x1B', '\x1B'), (0x02, '"', '1'), (0x03, '«', '2'), (0x04, '»', '3'), (0x05, '(', '4'), (0x06, ')', '5'), (0x07, '@', '6'), (0x08, '+', '7'), (0x09, '-', '8'), (0x0A, '/', '9'), (0x0B, '*', '0'), (0x0C, '=', '°'), (0x0D, '%', '`'), (0x0E, '\x7F', '\x7F'), (0x0F, '\t', '\t'), (0x10, 'b', 'B'), (0x11, 'é', 'É'), (0x12, 'p', 'P'), (0x13, 'o', 'O'), (0x14, 'è', 'È'), (0x15, '^', '!'), (0x16, 'v', 'V'), (0x17, 'd', 'D'), (0x18, 'l', 'L'), (0x19, 'j', 'J'), (0x1A, 'z', 'Z'), (0x1B, 'w', 'W'), (0x1C, '\n', '\n'), (0x1E, 'a', 'A'), (0x1F, 'u', 'U'), (0x20, 'i', 'I'), (0x21, 'e', 'E'), (0x22, ',', ';'), (0x23, 'c', 'C'), (0x24, 't', 'T'), (0x25, 's', 'S'), (0x26, 'r', 'R'), (0x27, 'n', 'N'), (0x28, 'm', 'M'), (0x29, 'ç', 'Ç'), (0x2B, '\'', '?'), (0x2C, 'x', 'X'), (0x2D, 'f', 'F'), (0x2E, 'h', 'H'), (0x2F, 'q', 'Q'), (0x30, 'g', 'G'), (0x31, 'y', 'Y'), (0x32, 'k', 'K'), (0x33, '.', ':'), (0x34, '/', '§'), (0x35, 'g', 'G'), (0x39, ' ', ' '), ]; for &(sc, normal, shifted) in bindings { entries.insert( sc, KeymapEntry { scancode: sc, normal, shifted, altgr: '\0', altgr_shifted: '\0', }, ); } let mut dead_keys = Self::common_dead_keys(); dead_keys.push(DeadKeyEntry { dead_key: '^', base: ' ', composed: '^', }); Keymap { name: "bepo".into(), entries, compose: Vec::new(), dead_keys, } } fn make_it() -> Keymap { let mut km = Self::make_us(); km.name = "it".into(); if let Some(e) = km.entries.get_mut(&0x29) { e.normal = '\\'; e.shifted = '|'; } if let Some(e) = km.entries.get_mut(&0x0C) { e.normal = '\''; e.shifted = '?'; } if let Some(e) = km.entries.get_mut(&0x0D) { e.normal = 'ì'; e.shifted = '^'; } if let Some(e) = km.entries.get_mut(&0x1A) { e.normal = 'è'; e.shifted = 'é'; } if let Some(e) = km.entries.get_mut(&0x1B) { e.normal = '+'; e.shifted = '*'; } if let Some(e) = km.entries.get_mut(&0x27) { e.normal = 'ò'; e.shifted = 'ç'; } if let Some(e) = km.entries.get_mut(&0x28) { e.normal = 'à'; e.shifted = '°'; } if let Some(e) = km.entries.get_mut(&0x2B) { e.normal = 'ù'; e.shifted = '§'; } km } }