diff --git a/src/textual/app.py b/src/textual/app.py index 9139dd514..4c8762508 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -107,6 +107,7 @@ from textual.keys import ( REPLACED_KEYS, _character_to_key, _get_unicode_name_from_key, + _normalize_key_list, format_key, ) from textual.messages import CallbackType, Prune @@ -3709,7 +3710,10 @@ class App(Generic[ReturnType], DOMNode): Args: keymap: A mapping of binding IDs to key strings. """ - self._keymap = keymap + + self._keymap = { + binding_id: _normalize_key_list(keys) for binding_id, keys in keymap.items() + } self.refresh_bindings() def update_keymap(self, keymap: Keymap) -> None: @@ -3721,6 +3725,9 @@ class App(Generic[ReturnType], DOMNode): Args: keymap: A mapping of binding IDs to key strings. """ + keymap = { + binding_id: _normalize_key_list(keys) for binding_id, keys in keymap.items() + } self._keymap = {**self._keymap, **keymap} self.refresh_bindings() diff --git a/src/textual/keys.py b/src/textual/keys.py index b4eb6236d..c34e9edf7 100644 --- a/src/textual/keys.py +++ b/src/textual/keys.py @@ -354,3 +354,16 @@ def _character_to_key(character: str) -> str: key = character key = KEY_NAME_REPLACEMENTS.get(key, key) return key + + +def _normalize_key_list(keys: str) -> str: + """Normalizes a comma separated list of keys. + + Replaces single letter keys with full name. + Sorts alphabetically. + """ + + keys_list = [key.strip() for key in keys.split(",")] + return ",".join( + _character_to_key(key) if len(key) == 1 else key for key in sorted(keys_list) + ) diff --git a/tests/test_binding.py b/tests/test_binding.py index 2aaf500a1..d11158f9f 100644 --- a/tests/test_binding.py +++ b/tests/test_binding.py @@ -127,3 +127,13 @@ async def test_keymap_update() -> None: app.set_keymap({"quit": "f1"}) await pilot.pause() assert bindings_updated == [app.screen, app.screen] + + +async def test_keymap_key() -> None: + app: App[None] = App() + + async with app.run_test(): + app.set_keymap({"foo": "?,space"}) + assert app._keymap == {"foo": "question_mark,space"} + app.update_keymap({"bar": "$"}) + assert app._keymap == {"bar": "dollar_sign", "foo": "question_mark,space"}