From 63fa0c4e947100219e9d0cfa6283f39a832b2fed Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 12 Aug 2022 12:37:15 +0530 Subject: [PATCH] Nicer fix for human_repr of keys defined with kitty_mod --- kitty/debug_config.py | 31 +++++++++---------------------- kitty/fast_data_types.pyi | 2 ++ kitty/keys.c | 10 ++++++++++ kitty/types.py | 23 +++++++++++++++-------- 4 files changed, 36 insertions(+), 30 deletions(-) diff --git a/kitty/debug_config.py b/kitty/debug_config.py index 2fb8466db..10d5aeeeb 100644 --- a/kitty/debug_config.py +++ b/kitty/debug_config.py @@ -52,29 +52,16 @@ def print_mapping_changes(defns: Dict[str, str], changes: Set[str], text: str, p print_event(k, defns[k], print) -def compare_shortcut_maps(final: Dict[Shortcut, str], final_kitty_mod: int, initial: Dict[Shortcut, str], initial_kitty_mod: int, print: Print) -> None: - # previous_tab uses a definition of ctrl+shift+tab not kitty_mod+tab, but - # we cant distinguish these as the information about the original - # definition is discarded. - ei = {k._replace(kitty_mod=0 if v == 'previous_tab' and k.human_repr.endswith('+tab') else initial_kitty_mod).human_repr: v for k, v in initial.items()} - ef = {k._replace(kitty_mod=final_kitty_mod).human_repr: v for k, v in final.items()} +def compare_maps(final: Dict[AnyEvent, str], final_kitty_mod: int, initial: Dict[AnyEvent, str], initial_kitty_mod: int, print: Print) -> None: + ei = {k.human_repr(initial_kitty_mod): v for k, v in initial.items()} + ef = {k.human_repr(final_kitty_mod): v for k, v in final.items()} added = set(ef) - set(ei) removed = set(ei) - set(ef) changed = {k for k in set(ef) & set(ei) if ef[k] != ei[k]} - print_mapping_changes(ef, added, 'Added shortcuts:', print) - print_mapping_changes(ei, removed, 'Removed shortcuts:', print) - print_mapping_changes(ef, changed, 'Changed shortcuts:', print) - - -def compare_mouse_maps(final: Dict[MouseEvent, str], final_kitty_mod: int, initial: Dict[MouseEvent, str], initial_kitty_mod: int, print: Print) -> None: - ei = {k.human_repr: v for k, v in initial.items()} - ef = {k.human_repr: v for k, v in final.items()} - added = set(ef) - set(ei) - removed = set(ei) - set(ef) - changed = {k for k in set(ef) & set(ei) if ef[k] != ei[k]} - print_mapping_changes(ef, added, 'Added mouse actions:', print) - print_mapping_changes(ei, removed, 'Removed mouse actions:', print) - print_mapping_changes(ef, changed, 'Changed mouse actions:', print) + which = 'shortcuts' if isinstance(next(iter(initial)), Shortcut) else 'mouse actions' + print_mapping_changes(ef, added, f'Added {which}:', print) + print_mapping_changes(ei, removed, f'Removed {which}:', print) + print_mapping_changes(ef, changed, f'Changed {which}:', print) def flatten_sequence_map(m: SequenceMap) -> ShortcutMap: @@ -120,14 +107,14 @@ def compare_opts(opts: KittyOpts, print: Print) -> None: else: print(fmt.format(f), str(getattr(opts, f))) - compare_mouse_maps(opts.mousemap, opts.kitty_mod, default_opts.mousemap, default_opts.kitty_mod, print) + compare_maps(opts.mousemap, opts.kitty_mod, default_opts.mousemap, default_opts.kitty_mod, print) final_, initial_ = opts.keymap, default_opts.keymap final: ShortcutMap = {Shortcut((k,)): v for k, v in final_.items()} initial: ShortcutMap = {Shortcut((k,)): v for k, v in initial_.items()} final_s, initial_s = map(flatten_sequence_map, (opts.sequence_map, default_opts.sequence_map)) final.update(final_s) initial.update(initial_s) - compare_shortcut_maps(final, opts.kitty_mod, initial, default_opts.kitty_mod, print) + compare_maps(final, opts.kitty_mod, initial, default_opts.kitty_mod, print) if colors: print(f'{title("Colors")}:', end='\n\t') print('\n\t'.join(sorted(colors))) diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index 44491dceb..c6d55e41c 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -1478,6 +1478,8 @@ class SingleKey: def is_native(self) -> bool: ... @property def key(self) -> int: ... + @property + def defined_with_kitty_mod(self) -> bool: ... def __iter__(self) -> Iterator[int]: ... def _replace(self, mods: int = 0, is_native: object = False, key: int = -1) -> 'SingleKey': ... def resolve_kitty_mod(self, mod: int) -> 'SingleKey': ... diff --git a/kitty/keys.c b/kitty/keys.c index fec331d32..c33cee633 100644 --- a/kitty/keys.c +++ b/kitty/keys.c @@ -305,6 +305,7 @@ typedef struct { PyObject_HEAD Key key; + bool defined_with_kitty_mod; } SingleKey; static inline void @@ -366,10 +367,18 @@ SingleKey_get_is_native(SingleKey *self, void UNUSED *closure) { Py_RETURN_FALSE; } +static PyObject* +SingleKey_defined_with_kitty_mod(SingleKey *self, void UNUSED *closure) { + if (self->defined_with_kitty_mod || (self->key.mods & GLFW_MOD_KITTY)) Py_RETURN_TRUE; + Py_RETURN_FALSE; +} + + static PyGetSetDef SingleKey_getsetters[] = { {"key", (getter)SingleKey_get_key, NULL, "The key as an integer", NULL}, {"mods", (getter)SingleKey_get_mods, NULL, "The modifiers as an integer", NULL}, {"is_native", (getter)SingleKey_get_is_native, NULL, "A bool", NULL}, + {"defined_with_kitty_mod", (getter)SingleKey_defined_with_kitty_mod, NULL, "A bool", NULL}, {NULL} /* Sentinel */ }; @@ -421,6 +430,7 @@ SingleKey_resolve_kitty_mod(SingleKey *self, PyObject *km) { if (!ans) return NULL; ans->key.val = self->key.val; ans->key.mods = (ans->key.mods & ~GLFW_MOD_KITTY) | kitty_mod; + ans->defined_with_kitty_mod = true; return (PyObject*)ans; } diff --git a/kitty/types.py b/kitty/types.py index 45803cdf9..02baf77fe 100644 --- a/kitty/types.py +++ b/kitty/types.py @@ -51,8 +51,7 @@ class SignalInfo(NamedTuple): sival_ptr: int -def mod_to_names(mods: int, kitty_mod: int = 0) -> Iterator[str]: - has_kitty_mod = kitty_mod and (mods & kitty_mod) == kitty_mod +def mod_to_names(mods: int, has_kitty_mod: bool = False, kitty_mod: int = 0) -> Iterator[str]: if has_kitty_mod: mods &= ~kitty_mod yield 'kitty_mod' @@ -61,13 +60,22 @@ def mod_to_names(mods: int, kitty_mod: int = 0) -> Iterator[str]: yield name +def human_repr_of_single_key(self: 'SingleKey', kitty_mod: int) -> str: + from .fast_data_types import glfw_get_key_name + names = [] + names = list(mod_to_names(self.mods, self.defined_with_kitty_mod, kitty_mod)) + if self.key > 0: + kname = (glfw_get_key_name(0, self.key) if self.is_native else glfw_get_key_name(self.key, 0)) or f'{self.key}' + kname = {' ': 'space'}.get(kname, kname) + names.append(kname) + return '+'.join(names) + + class Shortcut(NamedTuple): keys: Tuple['SingleKey', ...] - kitty_mod: int = 0 - @property - def human_repr(self) -> str: - return ' > '.join(k.human_repr_with_kitty_mod(self.kitty_mod) for k in self.keys) + def human_repr(self, kitty_mod: int = 0) -> str: + return ' > '.join(human_repr_of_single_key(k, kitty_mod) for k in self.keys) class MouseEvent(NamedTuple): @@ -76,8 +84,7 @@ class MouseEvent(NamedTuple): repeat_count: int = 1 grabbed: bool = False - @property - def human_repr(self) -> str: + def human_repr(self, kitty_mod: int = 0) -> str: from .options.utils import mouse_button_map, mouse_trigger_count_map def mouse_button_num_to_name(num: int) -> str: