[console] Fix definition of unreachability for remapped keys

The AltGr remapping table is constructed to include only keys that are
not reachable after applying the basic remapping table.  The logic
currently fails to include keys that are omitted entirely from the
basic remapping table since they would map to a non-ASCII character.

Fix this logic by allowing the remapping tables to include null
mappings, which are then elided only at the point of constructing the
C code fragment.

Reported-by: Christian Nilsson <nikize@gmail.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
pull/591/head
Michael Brown 2022-02-15 16:41:19 +00:00
parent 4a37b05008
commit 419b2e71da
19 changed files with 137 additions and 23 deletions

View File

@ -37,10 +37,15 @@ static struct keymap_key al_basic[] = {
/** "al" AltGr remapping */ /** "al" AltGr remapping */
static struct keymap_key al_altgr[] = { static struct keymap_key al_altgr[] = {
{ 0x21, 0x7e }, /* '!' => '~' */
{ 0x26, 0x60 }, /* '&' => '`' */
{ 0x30, 0x7e }, /* '0' => '~' */ { 0x30, 0x7e }, /* '0' => '~' */
{ 0x31, 0x7e }, /* '1' => '~' */ { 0x31, 0x7e }, /* '1' => '~' */
{ 0x34, 0x7e }, /* '4' => '~' */ { 0x34, 0x7e }, /* '4' => '~' */
{ 0x37, 0x60 }, /* '7' => '`' */ { 0x37, 0x60 }, /* '7' => '`' */
{ 0x3a, 0x7e }, /* ':' => '~' */
{ 0x56, 0x60 }, /* 'V' => '`' */
{ 0x7c, 0x7e }, /* '|' => '~' */
{ 0, 0 } { 0, 0 }
}; };

View File

@ -33,6 +33,7 @@ static struct keymap_key cf_altgr[] = {
{ 0x27, 0x7b }, /* '\'' => '{' */ { 0x27, 0x7b }, /* '\'' => '{' */
{ 0x32, 0x40 }, /* '2' => '@' */ { 0x32, 0x40 }, /* '2' => '@' */
{ 0x3b, 0x7e }, /* ';' => '~' */ { 0x3b, 0x7e }, /* ';' => '~' */
{ 0x5c, 0x7d }, /* '\\' => '}' */
{ 0x60, 0x5c }, /* '`' => '\\' */ { 0x60, 0x5c }, /* '`' => '\\' */
{ 0, 0 } { 0, 0 }
}; };

View File

@ -50,6 +50,9 @@ static struct keymap_key cz_basic[] = {
/** "cz" AltGr remapping */ /** "cz" AltGr remapping */
static struct keymap_key cz_altgr[] = { static struct keymap_key cz_altgr[] = {
{ 0x21, 0x7e }, /* '!' => '~' */
{ 0x24, 0x7e }, /* '$' => '~' */
{ 0x29, 0x7e }, /* ')' => '~' */
{ 0x2c, 0x3c }, /* ',' => '<' */ { 0x2c, 0x3c }, /* ',' => '<' */
{ 0x2e, 0x3e }, /* '.' => '>' */ { 0x2e, 0x3e }, /* '.' => '>' */
{ 0x2f, 0x2a }, /* '/' => '*' */ { 0x2f, 0x2a }, /* '/' => '*' */
@ -60,10 +63,15 @@ static struct keymap_key cz_altgr[] = {
{ 0x37, 0x26 }, /* '7' => '&' */ { 0x37, 0x26 }, /* '7' => '&' */
{ 0x38, 0x2a }, /* '8' => '*' */ { 0x38, 0x2a }, /* '8' => '*' */
{ 0x39, 0x7b }, /* '9' => '{' */ { 0x39, 0x7b }, /* '9' => '{' */
{ 0x3a, 0x7e }, /* ':' => '~' */
{ 0x3b, 0x24 }, /* ';' => '$' */ { 0x3b, 0x24 }, /* ';' => '$' */
{ 0x4b, 0x26 }, /* 'K' => '&' */
{ 0x58, 0x3e }, /* 'X' => '>' */
{ 0x5a, 0x3c }, /* 'Z' => '<' */
{ 0x61, 0x7e }, /* 'a' => '~' */ { 0x61, 0x7e }, /* 'a' => '~' */
{ 0x62, 0x7b }, /* 'b' => '{' */ { 0x62, 0x7b }, /* 'b' => '{' */
{ 0x63, 0x26 }, /* 'c' => '&' */ { 0x63, 0x26 }, /* 'c' => '&' */
{ 0x66, 0x5b }, /* 'f' => '[' */
{ 0x67, 0x5d }, /* 'g' => ']' */ { 0x67, 0x5d }, /* 'g' => ']' */
{ 0x6e, 0x7d }, /* 'n' => '}' */ { 0x6e, 0x7d }, /* 'n' => '}' */
{ 0x76, 0x40 }, /* 'v' => '@' */ { 0x76, 0x40 }, /* 'v' => '@' */

View File

@ -47,8 +47,13 @@ static struct keymap_key de_basic[] = {
static struct keymap_key de_altgr[] = { static struct keymap_key de_altgr[] = {
{ 0x2d, 0x5c }, /* '-' => '\\' */ { 0x2d, 0x5c }, /* '-' => '\\' */
{ 0x30, 0x7d }, /* '0' => '}' */ { 0x30, 0x7d }, /* '0' => '}' */
{ 0x37, 0x7b }, /* '7' => '{' */
{ 0x38, 0x5b }, /* '8' => '[' */
{ 0x39, 0x5d }, /* '9' => ']' */ { 0x39, 0x5d }, /* '9' => ']' */
{ 0x3b, 0x7e }, /* ';' => '~' */
{ 0x5d, 0x7e }, /* ']' => '~' */
{ 0x71, 0x40 }, /* 'q' => '@' */ { 0x71, 0x40 }, /* 'q' => '@' */
{ 0x7c, 0x7e }, /* '|' => '~' */
{ 0xdc, 0x7c }, /* Pseudo-'\\' => '|' */ { 0xdc, 0x7c }, /* Pseudo-'\\' => '|' */
{ 0, 0 } { 0, 0 }
}; };

View File

@ -39,7 +39,14 @@ static struct keymap_key dk_basic[] = {
static struct keymap_key dk_altgr[] = { static struct keymap_key dk_altgr[] = {
{ 0x30, 0x7d }, /* '0' => '}' */ { 0x30, 0x7d }, /* '0' => '}' */
{ 0x32, 0x40 }, /* '2' => '@' */ { 0x32, 0x40 }, /* '2' => '@' */
{ 0x34, 0x24 }, /* '4' => '$' */
{ 0x37, 0x7b }, /* '7' => '{' */
{ 0x38, 0x5b }, /* '8' => '[' */
{ 0x39, 0x5d }, /* '9' => ']' */
{ 0x3a, 0x7e }, /* ':' => '~' */
{ 0x3d, 0x7c }, /* '=' => '|' */ { 0x3d, 0x7c }, /* '=' => '|' */
{ 0x5c, 0x7e }, /* '\\' => '~' */
{ 0x5d, 0x7e }, /* ']' => '~' */
{ 0x71, 0x40 }, /* 'q' => '@' */ { 0x71, 0x40 }, /* 'q' => '@' */
{ 0, 0 } { 0, 0 }
}; };

View File

@ -37,14 +37,27 @@ static struct keymap_key es_basic[] = {
/** "es" AltGr remapping */ /** "es" AltGr remapping */
static struct keymap_key es_altgr[] = { static struct keymap_key es_altgr[] = {
{ 0x22, 0x7b }, /* '"' => '{' */
{ 0x27, 0x7b }, /* '\'' => '{' */ { 0x27, 0x7b }, /* '\'' => '{' */
{ 0x2b, 0x7e }, /* '+' => '~' */
{ 0x2d, 0x5c }, /* '-' => '\\' */
{ 0x30, 0x7d }, /* '0' => '}' */ { 0x30, 0x7d }, /* '0' => '}' */
{ 0x31, 0x7c }, /* '1' => '|' */
{ 0x32, 0x40 }, /* '2' => '@' */ { 0x32, 0x40 }, /* '2' => '@' */
{ 0x33, 0x23 }, /* '3' => '#' */
{ 0x34, 0x7e }, /* '4' => '~' */
{ 0x37, 0x7b }, /* '7' => '{' */ { 0x37, 0x7b }, /* '7' => '{' */
{ 0x38, 0x5b }, /* '8' => '[' */ { 0x38, 0x5b }, /* '8' => '[' */
{ 0x39, 0x5d }, /* '9' => ']' */ { 0x39, 0x5d }, /* '9' => ']' */
{ 0x3a, 0x7e }, /* ':' => '~' */
{ 0x3b, 0x7e }, /* ';' => '~' */
{ 0x3d, 0x7e }, /* '=' => '~' */
{ 0x5c, 0x7d }, /* '\\' => '}' */ { 0x5c, 0x7d }, /* '\\' => '}' */
{ 0x60, 0x5c }, /* '`' => '\\' */
{ 0x71, 0x40 }, /* 'q' => '@' */ { 0x71, 0x40 }, /* 'q' => '@' */
{ 0x7c, 0x7e }, /* '|' => '~' */
{ 0x7e, 0x5c }, /* '~' => '\\' */
{ 0xdc, 0x7c }, /* Pseudo-'\\' => '|' */
{ 0, 0 } { 0, 0 }
}; };

View File

@ -35,8 +35,18 @@ static struct keymap_key et_basic[] = {
/** "et" AltGr remapping */ /** "et" AltGr remapping */
static struct keymap_key et_altgr[] = { static struct keymap_key et_altgr[] = {
{ 0x26, 0x7b }, /* '&' => '{' */
{ 0x28, 0x5d }, /* '(' => ']' */
{ 0x29, 0x7d }, /* ')' => '}' */
{ 0x2a, 0x5b }, /* '*' => '[' */
{ 0x2d, 0x5c }, /* '-' => '\\' */ { 0x2d, 0x5c }, /* '-' => '\\' */
{ 0x30, 0x7d }, /* '0' => '}' */
{ 0x32, 0x40 }, /* '2' => '@' */ { 0x32, 0x40 }, /* '2' => '@' */
{ 0x34, 0x24 }, /* '4' => '$' */
{ 0x37, 0x7b }, /* '7' => '{' */
{ 0x38, 0x5b }, /* '8' => '[' */
{ 0x39, 0x5d }, /* '9' => ']' */
{ 0x5f, 0x5c }, /* '_' => '\\' */
{ 0xdc, 0x7c }, /* Pseudo-'\\' => '|' */ { 0xdc, 0x7c }, /* Pseudo-'\\' => '|' */
{ 0, 0 } { 0, 0 }
}; };

View File

@ -38,6 +38,12 @@ static struct keymap_key fi_altgr[] = {
{ 0x2d, 0x5c }, /* '-' => '\\' */ { 0x2d, 0x5c }, /* '-' => '\\' */
{ 0x30, 0x7d }, /* '0' => '}' */ { 0x30, 0x7d }, /* '0' => '}' */
{ 0x32, 0x40 }, /* '2' => '@' */ { 0x32, 0x40 }, /* '2' => '@' */
{ 0x34, 0x24 }, /* '4' => '$' */
{ 0x37, 0x7b }, /* '7' => '{' */
{ 0x38, 0x5b }, /* '8' => '[' */
{ 0x39, 0x5d }, /* '9' => ']' */
{ 0x49, 0x7c }, /* 'I' => '|' */
{ 0x5d, 0x7e }, /* ']' => '~' */
{ 0xdc, 0x7c }, /* Pseudo-'\\' => '|' */ { 0xdc, 0x7c }, /* Pseudo-'\\' => '|' */
{ 0, 0 } { 0, 0 }
}; };

View File

@ -68,9 +68,15 @@ static struct keymap_key fr_altgr[] = {
{ 0x2d, 0x5d }, /* '-' => ']' */ { 0x2d, 0x5d }, /* '-' => ']' */
{ 0x30, 0x40 }, /* '0' => '@' */ { 0x30, 0x40 }, /* '0' => '@' */
{ 0x33, 0x23 }, /* '3' => '#' */ { 0x33, 0x23 }, /* '3' => '#' */
{ 0x34, 0x7b }, /* '4' => '{' */
{ 0x35, 0x5b }, /* '5' => '[' */ { 0x35, 0x5b }, /* '5' => '[' */
{ 0x36, 0x7c }, /* '6' => '|' */
{ 0x37, 0x60 }, /* '7' => '`' */
{ 0x38, 0x5c }, /* '8' => '\\' */ { 0x38, 0x5c }, /* '8' => '\\' */
{ 0x3d, 0x7d }, /* '=' => '}' */
{ 0x5c, 0x60 }, /* '\\' => '`' */
{ 0x61, 0x40 }, /* 'a' => '@' */ { 0x61, 0x40 }, /* 'a' => '@' */
{ 0xdc, 0x7c }, /* Pseudo-'\\' => '|' */
{ 0, 0 } { 0, 0 }
}; };

View File

@ -37,18 +37,36 @@ static struct keymap_key hu_basic[] = {
/** "hu" AltGr remapping */ /** "hu" AltGr remapping */
static struct keymap_key hu_altgr[] = { static struct keymap_key hu_altgr[] = {
{ 0x21, 0x7e }, /* '!' => '~' */
{ 0x23, 0x5e }, /* '#' => '^' */
{ 0x26, 0x60 }, /* '&' => '`' */
{ 0x2c, 0x3b }, /* ',' => ';' */
{ 0x2e, 0x3e }, /* '.' => '>' */ { 0x2e, 0x3e }, /* '.' => '>' */
{ 0x2f, 0x2a }, /* '/' => '*' */ { 0x2f, 0x2a }, /* '/' => '*' */
{ 0x30, 0x7e }, /* '0' => '~' */
{ 0x31, 0x7e }, /* '1' => '~' */
{ 0x32, 0x5e }, /* '2' => '^' */ { 0x32, 0x5e }, /* '2' => '^' */
{ 0x33, 0x5e }, /* '3' => '^' */ { 0x33, 0x5e }, /* '3' => '^' */
{ 0x34, 0x7e }, /* '4' => '~' */
{ 0x37, 0x60 }, /* '7' => '`' */ { 0x37, 0x60 }, /* '7' => '`' */
{ 0x3b, 0x24 }, /* ';' => '$' */ { 0x3b, 0x24 }, /* ';' => '$' */
{ 0x4b, 0x26 }, /* 'K' => '&' */
{ 0x58, 0x3e }, /* 'X' => '>' */
{ 0x5a, 0x3c }, /* 'Z' => '<' */
{ 0x62, 0x7b }, /* 'b' => '{' */
{ 0x63, 0x26 }, /* 'c' => '&' */ { 0x63, 0x26 }, /* 'c' => '&' */
{ 0x66, 0x5b }, /* 'f' => '[' */
{ 0x67, 0x5d }, /* 'g' => ']' */
{ 0x6d, 0x3c }, /* 'm' => '<' */ { 0x6d, 0x3c }, /* 'm' => '<' */
{ 0x6e, 0x7d }, /* 'n' => '}' */
{ 0x71, 0x5c }, /* 'q' => '\\' */
{ 0x76, 0x40 }, /* 'v' => '@' */ { 0x76, 0x40 }, /* 'v' => '@' */
{ 0x77, 0x7c }, /* 'w' => '|' */
{ 0x78, 0x23 }, /* 'x' => '#' */ { 0x78, 0x23 }, /* 'x' => '#' */
{ 0x7a, 0x3e }, /* 'z' => '>' */ { 0x7a, 0x3e }, /* 'z' => '>' */
{ 0x7c, 0x7e }, /* '|' => '~' */
{ 0xdc, 0x3c }, /* Pseudo-'\\' => '<' */ { 0xdc, 0x3c }, /* Pseudo-'\\' => '<' */
{ 0xfc, 0x3e }, /* Pseudo-'|' => '>' */
{ 0, 0 } { 0, 0 }
}; };

View File

@ -37,13 +37,19 @@ static struct keymap_key it_basic[] = {
/** "it" AltGr remapping */ /** "it" AltGr remapping */
static struct keymap_key it_altgr[] = { static struct keymap_key it_altgr[] = {
{ 0x23, 0x7e }, /* '#' => '~' */
{ 0x27, 0x23 }, /* '\'' => '#' */
{ 0x2d, 0x60 }, /* '-' => '`' */ { 0x2d, 0x60 }, /* '-' => '`' */
{ 0x30, 0x7d }, /* '0' => '}' */ { 0x30, 0x7d }, /* '0' => '}' */
{ 0x37, 0x7b }, /* '7' => '{' */
{ 0x38, 0x5b }, /* '8' => '[' */
{ 0x39, 0x5d }, /* '9' => ']' */ { 0x39, 0x5d }, /* '9' => ']' */
{ 0x3b, 0x40 }, /* ';' => '@' */ { 0x3b, 0x40 }, /* ';' => '@' */
{ 0x3d, 0x7e }, /* '=' => '~' */ { 0x3d, 0x7e }, /* '=' => '~' */
{ 0x40, 0x7e }, /* '@' => '~' */
{ 0x5c, 0x60 }, /* '\\' => '`' */ { 0x5c, 0x60 }, /* '\\' => '`' */
{ 0x71, 0x40 }, /* 'q' => '@' */ { 0x71, 0x40 }, /* 'q' => '@' */
{ 0x7c, 0x7e }, /* '|' => '~' */
{ 0, 0 } { 0, 0 }
}; };

View File

@ -17,6 +17,10 @@ static struct keymap_key lt_basic[] = {
/** "lt" AltGr remapping */ /** "lt" AltGr remapping */
static struct keymap_key lt_altgr[] = { static struct keymap_key lt_altgr[] = {
{ 0x22, 0x5e }, /* '"' => '^' */
{ 0x27, 0x5e }, /* '\'' => '^' */
{ 0x4b, 0x26 }, /* 'K' => '&' */
{ 0x71, 0x40 }, /* 'q' => '@' */
{ 0, 0 } { 0, 0 }
}; };

View File

@ -22,6 +22,11 @@ static struct keymap_key mt_basic[] = {
/** "mt" AltGr remapping */ /** "mt" AltGr remapping */
static struct keymap_key mt_altgr[] = { static struct keymap_key mt_altgr[] = {
{ 0x30, 0x7d }, /* '0' => '}' */
{ 0x37, 0x7b }, /* '7' => '{' */
{ 0x38, 0x5b }, /* '8' => '[' */
{ 0x39, 0x5d }, /* '9' => ']' */
{ 0x5c, 0x60 }, /* '\\' => '`' */
{ 0, 0 } { 0, 0 }
}; };

View File

@ -39,10 +39,15 @@ static struct keymap_key no_latin1_basic[] = {
/** "no-latin1" AltGr remapping */ /** "no-latin1" AltGr remapping */
static struct keymap_key no_latin1_altgr[] = { static struct keymap_key no_latin1_altgr[] = {
{ 0x22, 0x5b }, /* '"' => '[' */
{ 0x27, 0x7b }, /* '\'' => '{' */
{ 0x30, 0x7d }, /* '0' => '}' */ { 0x30, 0x7d }, /* '0' => '}' */
{ 0x32, 0x40 }, /* '2' => '@' */ { 0x32, 0x40 }, /* '2' => '@' */
{ 0x37, 0x7b }, /* '7' => '{' */
{ 0x38, 0x5b }, /* '8' => '[' */
{ 0x39, 0x5d }, /* '9' => ']' */ { 0x39, 0x5d }, /* '9' => ']' */
{ 0x5b, 0x7d }, /* '[' => '}' */ { 0x5b, 0x7d }, /* '[' => '}' */
{ 0x7b, 0x5d }, /* '{' => ']' */
{ 0, 0 } { 0, 0 }
}; };

View File

@ -41,6 +41,13 @@ static struct keymap_key no_basic[] = {
static struct keymap_key no_altgr[] = { static struct keymap_key no_altgr[] = {
{ 0x30, 0x7d }, /* '0' => '}' */ { 0x30, 0x7d }, /* '0' => '}' */
{ 0x32, 0x40 }, /* '2' => '@' */ { 0x32, 0x40 }, /* '2' => '@' */
{ 0x34, 0x24 }, /* '4' => '$' */
{ 0x37, 0x7b }, /* '7' => '{' */
{ 0x38, 0x5b }, /* '8' => '[' */
{ 0x39, 0x5d }, /* '9' => ']' */
{ 0x3a, 0x7e }, /* ':' => '~' */
{ 0x5c, 0x7e }, /* '\\' => '~' */
{ 0x5d, 0x7e }, /* ']' => '~' */
{ 0x71, 0x40 }, /* 'q' => '@' */ { 0x71, 0x40 }, /* 'q' => '@' */
{ 0, 0 } { 0, 0 }
}; };

View File

@ -44,6 +44,7 @@ static struct keymap_key pt_altgr[] = {
{ 0x32, 0x40 }, /* '2' => '@' */ { 0x32, 0x40 }, /* '2' => '@' */
{ 0x37, 0x7b }, /* '7' => '{' */ { 0x37, 0x7b }, /* '7' => '{' */
{ 0x38, 0x5b }, /* '8' => '[' */ { 0x38, 0x5b }, /* '8' => '[' */
{ 0x39, 0x5d }, /* '9' => ']' */
{ 0x71, 0x40 }, /* 'q' => '@' */ { 0x71, 0x40 }, /* 'q' => '@' */
{ 0, 0 } { 0, 0 }
}; };

View File

@ -40,6 +40,11 @@ static struct keymap_key se_altgr[] = {
{ 0x2d, 0x5c }, /* '-' => '\\' */ { 0x2d, 0x5c }, /* '-' => '\\' */
{ 0x30, 0x7d }, /* '0' => '}' */ { 0x30, 0x7d }, /* '0' => '}' */
{ 0x32, 0x40 }, /* '2' => '@' */ { 0x32, 0x40 }, /* '2' => '@' */
{ 0x34, 0x24 }, /* '4' => '$' */
{ 0x37, 0x7b }, /* '7' => '{' */
{ 0x38, 0x5b }, /* '8' => '[' */
{ 0x39, 0x5d }, /* '9' => ']' */
{ 0x5d, 0x7e }, /* ']' => '~' */
{ 0x71, 0x40 }, /* 'q' => '@' */ { 0x71, 0x40 }, /* 'q' => '@' */
{ 0xdc, 0x7c }, /* Pseudo-'\\' => '|' */ { 0xdc, 0x7c }, /* Pseudo-'\\' => '|' */
{ 0, 0 } { 0, 0 }

View File

@ -45,9 +45,11 @@ static struct keymap_key sg_basic[] = {
/** "sg" AltGr remapping */ /** "sg" AltGr remapping */
static struct keymap_key sg_altgr[] = { static struct keymap_key sg_altgr[] = {
{ 0x27, 0x7b }, /* '\'' => '{' */
{ 0x32, 0x40 }, /* '2' => '@' */ { 0x32, 0x40 }, /* '2' => '@' */
{ 0x33, 0x23 }, /* '3' => '#' */ { 0x33, 0x23 }, /* '3' => '#' */
{ 0x37, 0x7c }, /* '7' => '|' */ { 0x37, 0x7c }, /* '7' => '|' */
{ 0x3d, 0x7e }, /* '=' => '~' */
{ 0x5c, 0x7d }, /* '\\' => '}' */ { 0x5c, 0x7d }, /* '\\' => '}' */
{ 0, 0 } { 0, 0 }
}; };

View File

@ -33,6 +33,10 @@ import textwrap
from typing import ClassVar, Optional from typing import ClassVar, Optional
BACKSPACE = chr(0x7f)
"""Backspace character"""
class KeyType(IntEnum): class KeyType(IntEnum):
"""Key types""" """Key types"""
@ -174,7 +178,7 @@ class KeyLayout(UserDict[KeyModifiers, Sequence[Key]]):
KeyModifiers.NONE: [(KEY_NON_US, ord('\\'))], KeyModifiers.NONE: [(KEY_NON_US, ord('\\'))],
KeyModifiers.SHIFT: [(KEY_NON_US, ord('|'))], KeyModifiers.SHIFT: [(KEY_NON_US, ord('|'))],
# Treat Ctrl-Backspace as producing Backspace rather than Ctrl-H # Treat Ctrl-Backspace as producing Backspace rather than Ctrl-H
KeyModifiers.CTRL: [(KEY_BACKSPACE, 0x7f)], KeyModifiers.CTRL: [(KEY_BACKSPACE, ord(BACKSPACE))],
}, },
'il': { 'il': {
# Redefine some otherwise unreachable ASCII characters # Redefine some otherwise unreachable ASCII characters
@ -200,11 +204,6 @@ class KeyLayout(UserDict[KeyModifiers, Sequence[Key]]):
"""Basic shifted keyboard layout""" """Basic shifted keyboard layout"""
return self[KeyModifiers.SHIFT] return self[KeyModifiers.SHIFT]
@property
def altgr(self):
"""AltGr keyboard layout"""
return self.get(KeyModifiers.ALTGR, self.unshifted)
@classmethod @classmethod
def load(cls, name: str) -> KeyLayout: def load(cls, name: str) -> KeyLayout:
"""Load keymap using 'loadkeys -b'""" """Load keymap using 'loadkeys -b'"""
@ -281,7 +280,7 @@ class BiosKeyLayout(KeyLayout):
return inverse return inverse
class KeymapKeys(UserDict[str, str]): class KeymapKeys(UserDict[str, Optional[str]]):
"""An ASCII character remapping""" """An ASCII character remapping"""
@classmethod @classmethod
@ -312,7 +311,8 @@ class KeymapKeys(UserDict[str, str]):
self.ascii_name(source), self.ascii_name(target) self.ascii_name(source), self.ascii_name(target)
) )
for source, target in self.items() for source, target in self.items()
if ord(source) & ~BiosKeyLayout.KEY_PSEUDO != ord(target) if target
and ord(source) & ~BiosKeyLayout.KEY_PSEUDO != ord(target)
) + '\t{ 0, 0 }\n}' ) + '\t{ 0, 0 }\n}'
@ -335,13 +335,12 @@ class Keymap:
# Construct raw mapping from source ASCII to target ASCII # Construct raw mapping from source ASCII to target ASCII
raw = {source: self.target[key.modifiers][key.keycode].ascii raw = {source: self.target[key.modifiers][key.keycode].ascii
for source, key in self.source.inverse.items()} for source, key in self.source.inverse.items()}
# Eliminate any null mappings, mappings that attempt to remap # Eliminate any identity mappings, or mappings that attempt to
# the backspace key, or identity mappings # remap the backspace key
table = {source: target for source, target in raw.items() table = {source: target for source, target in raw.items()
if target if source != target
and ord(source) != 0x7f and source != BACKSPACE
and ord(target) != 0x7f and target != BACKSPACE}
and source != target}
# Recursively delete any mappings that would produce # Recursively delete any mappings that would produce
# unreachable alphanumerics (e.g. the "il" keymap, which maps # unreachable alphanumerics (e.g. the "il" keymap, which maps
# away the whole lower-case alphabet) # away the whole lower-case alphabet)
@ -354,8 +353,8 @@ class Keymap:
# Sanity check: ensure that all numerics are reachable using # Sanity check: ensure that all numerics are reachable using
# the same shift state # the same shift state
digits = '1234567890' digits = '1234567890'
unshifted = ''.join(table.get(x, x) for x in '1234567890') unshifted = ''.join(table.get(x) or x for x in '1234567890')
shifted = ''.join(table.get(x, x) for x in '!@#$%^&*()') shifted = ''.join(table.get(x) or x for x in '!@#$%^&*()')
if digits not in (shifted, unshifted): if digits not in (shifted, unshifted):
raise ValueError("Inconsistent numeric remapping %s / %s" % raise ValueError("Inconsistent numeric remapping %s / %s" %
(unshifted, shifted)) (unshifted, shifted))
@ -365,21 +364,22 @@ class Keymap:
def altgr(self) -> KeymapKeys: def altgr(self) -> KeymapKeys:
"""AltGr remapping table""" """AltGr remapping table"""
# Construct raw mapping from source ASCII to target ASCII # Construct raw mapping from source ASCII to target ASCII
raw = {source: self.target.altgr[key.keycode].ascii raw = {
for source, key in self.source.inverse.items() source:
if key.modifiers == KeyModifiers.NONE} self.target.get((key.modifiers | KeyModifiers.ALTGR),
self.target[key.modifiers])[key.keycode].ascii
for source, key in self.source.inverse.items()
}
# Identify printable keys that are unreachable via the basic map # Identify printable keys that are unreachable via the basic map
basic = self.basic basic = self.basic
unmapped = set(x for x in basic.keys() unmapped = set(x for x in basic.keys()
if x.isascii() and x.isprintable()) if x.isascii() and x.isprintable())
remapped = set(basic.values()) remapped = set(basic.values())
unreachable = unmapped - remapped unreachable = unmapped - remapped
# Eliminate any null mappings, mappings for unprintable # Eliminate any mappings for unprintable characters, or
# characters, or mappings for characters that are reachable # mappings for characters that are reachable via the basic map
# via the basic map
table = {source: target for source, target in raw.items() table = {source: target for source, target in raw.items()
if source.isprintable() if source.isprintable()
and target
and target in unreachable} and target in unreachable}
# Check that all characters are now reachable # Check that all characters are now reachable
unreachable -= set(table.values()) unreachable -= set(table.values())