From ee2520e03697fb4b634dccbb913fcf17c248b76e Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 23 Nov 2021 07:53:10 +0530 Subject: [PATCH] Also prevent infinite recursion in kitten_alias --- kitty/options/utils.py | 21 ++++++++++++++------- kitty_tests/options.py | 12 ++++++++++++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/kitty/options/utils.py b/kitty/options/utils.py index f52080504..aa2d72be1 100644 --- a/kitty/options/utils.py +++ b/kitty/options/utils.py @@ -849,14 +849,21 @@ def build_action_aliases(raw: Dict[str, List[str]], first_arg_replacement: str = def resolve_aliases_in_action(action: KeyAction, aliases: Dict[str, List[ActionAlias]]) -> KeyAction: for alias in aliases.get(action.func, ()): if alias.second_arg_test is None: - recursive = alias.func_name == action.func - action = action._replace(func=alias.func_name, args=alias.args + action.args) - if recursive: - aliases = aliases.copy() - aliases.pop(alias.func_name) - return resolve_aliases_in_action(action, aliases) + new_action = action._replace(func=alias.func_name, args=alias.args + action.args) + if new_action.func == action.func: + new_aliases = aliases.copy() + new_aliases.pop(alias.func_name) + else: + new_aliases = aliases + return resolve_aliases_in_action(new_action, new_aliases) if action.args and alias.second_arg_test(action.args[0]): - return resolve_aliases_in_action(action._replace(func=alias.func_name, args=alias.args + action.args[1:]), aliases) + new_action = action._replace(func=alias.func_name, args=alias.args + action.args[1:]) + if new_action.func == action.func and new_action.args and alias.second_arg_test(new_action.args[0]): + new_aliases = aliases.copy() + new_aliases[action.func] = [x for x in aliases[action.func] if x is not alias] + else: + new_aliases = aliases + return resolve_aliases_in_action(new_action, new_aliases) return action diff --git a/kitty_tests/options.py b/kitty_tests/options.py index 90d702503..f63203324 100644 --- a/kitty_tests/options.py +++ b/kitty_tests/options.py @@ -50,29 +50,41 @@ class TestConfParsing(BaseTest): self.assertFalse(bad_lines) opts = p('pointer_shape_when_grabbed XXX', bad_line_num=1) self.ae(opts.pointer_shape_when_grabbed, defaults.pointer_shape_when_grabbed) + opts = p('env A=1', 'env B=x$A', 'env C=', 'env D', 'clear_all_shortcuts y', 'kitten_alias a b --moo', 'map f1 kitten a arg') self.ae(opts.env, {'A': '1', 'B': 'x1', 'C': '', 'D': DELETE_ENV_VAR}) ka = tuple(opts.keymap.values())[0][0] self.ae(ka.func, 'kitten') self.ae(ka.args, ('b', '--moo', 'arg')) + + opts = p('clear_all_shortcuts y', 'kitten_alias hints hints --hi', 'map f1 kitten hints XXX') + ka = tuple(opts.keymap.values())[0][0] + self.ae(ka.func, 'kitten') + self.ae(ka.args, ('hints', '--hi', 'XXX')) + opts = p('clear_all_shortcuts y', 'action_alias la launch --moo', 'map f1 la XXX') ka = tuple(opts.keymap.values())[0][0] self.ae(ka.func, 'launch') self.ae(ka.args, ('--moo', 'XXX')) + opts = p('clear_all_shortcuts y', 'action_alias one launch --moo', 'action_alias two one recursive', 'map f1 two XXX') ka = tuple(opts.keymap.values())[0][0] self.ae(ka.func, 'launch') self.ae(ka.args, ('--moo', 'recursive', 'XXX')) + opts = p('clear_all_shortcuts y', 'action_alias launch launch --moo', 'map f1 launch XXX') ka = tuple(opts.keymap.values())[0][0] self.ae(ka.func, 'launch') self.ae(ka.args, ('--moo', 'XXX')) + opts = p('clear_all_shortcuts y', 'action_alias la launch --moo', 'map f1 combine : new_window : la ') ka = tuple(opts.keymap.values())[0] self.ae((ka[0].func, ka[1].func), ('new_window', 'launch')) + opts = p('kitty_mod alt') self.ae(opts.kitty_mod, to_modifiers('alt')) self.ae(next(keys_for_func(opts, 'next_layout')).mods, opts.kitty_mod) + # deprecation handling opts = p('clear_all_shortcuts y', 'send_text all f1 hello') self.ae(len(opts.keymap), 1)