From 36ef68c6984742b27317204ce12aebb368548790 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sun, 8 Oct 2017 21:48:48 +0200 Subject: [PATCH] Add :bind --default Closes #3059 --- doc/help/commands.asciidoc | 3 ++- qutebrowser/config/config.py | 12 ++++++++++++ qutebrowser/config/configcommands.py | 11 ++++++++++- tests/unit/config/test_config.py | 21 +++++++++++++++++++++ tests/unit/config/test_configcommands.py | 24 ++++++++++++++++++++++++ 5 files changed, 69 insertions(+), 2 deletions(-) diff --git a/doc/help/commands.asciidoc b/doc/help/commands.asciidoc index 349a67a5b..137bf3ef8 100644 --- a/doc/help/commands.asciidoc +++ b/doc/help/commands.asciidoc @@ -122,7 +122,7 @@ How many pages to go back. [[bind]] === bind -Syntax: +:bind [*--mode* 'mode'] 'key' ['command']+ +Syntax: +:bind [*--mode* 'mode'] [*--default*] 'key' ['command']+ Bind a key to a command. @@ -135,6 +135,7 @@ Bind a key to a command. * +*-m*+, +*--mode*+: A comma-separated list of modes to bind the key in (default: `normal`). See `:help bindings.commands` for the available modes. +* +*-d*+, +*--default*+: If given, restore a default binding. ==== note * This command does not split arguments after the last argument and handles quotes literally. diff --git a/qutebrowser/config/config.py b/qutebrowser/config/config.py index ffd0780d9..4bd7ddbc8 100644 --- a/qutebrowser/config/config.py +++ b/qutebrowser/config/config.py @@ -180,6 +180,18 @@ class KeyConfig: bindings[mode][key] = command self._config.update_mutables(save_yaml=save_yaml) + def bind_default(self, key, *, mode='normal', save_yaml=False): + """Restore a default keybinding""" + key = self._prepare(key, mode) + + bindings_commands = self._config.get_obj('bindings.commands') + try: + del bindings_commands[mode][key] + except KeyError: + raise configexc.KeybindingError( + "Can't find binding '{}' in {} mode".format(key, mode)) + self._config.update_mutables(save_yaml=save_yaml) + def unbind(self, key, *, mode='normal', save_yaml=False): """Unbind the given key in the given mode.""" key = self._prepare(key, mode) diff --git a/qutebrowser/config/configcommands.py b/qutebrowser/config/configcommands.py index 53aa425ee..5848c9680 100644 --- a/qutebrowser/config/configcommands.py +++ b/qutebrowser/config/configcommands.py @@ -92,7 +92,7 @@ class ConfigCommands: @cmdutils.register(instance='config-commands', maxsplit=1, no_cmd_split=True, no_replace_variables=True) @cmdutils.argument('command', completion=configmodel.bind) - def bind(self, key, command=None, *, mode='normal'): + def bind(self, key, command=None, *, mode='normal', default=False): """Bind a key to a command. Args: @@ -102,8 +102,17 @@ class ConfigCommands: mode: A comma-separated list of modes to bind the key in (default: `normal`). See `:help bindings.commands` for the available modes. + default: If given, restore a default binding. """ if command is None: + if default: + # :bind --default: Restore default + with self._handle_config_error(): + self._keyconfig.bind_default(key, mode=mode, + save_yaml=True) + return + + # No --default -> print binding if utils.is_special_key(key): # self._keyconfig.get_command does this, but we also need it # normalized for the output below diff --git a/tests/unit/config/test_config.py b/tests/unit/config/test_config.py index e42aca1a8..2d1de02ef 100644 --- a/tests/unit/config/test_config.py +++ b/tests/unit/config/test_config.py @@ -205,6 +205,27 @@ class TestKeyConfig: key_config_stub.bind('a', 'set-cmd-text :nop ;; rl-beginning-of-line', mode='normal') + def test_bind_default(self, key_config_stub, config_stub): + """Bind a key to its default.""" + default_cmd = 'message-info default' + bound_cmd = 'message-info bound' + config_stub.val.bindings.default = {'normal': {'a': default_cmd}} + config_stub.val.bindings.commands = {'normal': {'a': bound_cmd}} + assert key_config_stub.get_command('a', mode='normal') == bound_cmd + + key_config_stub.bind_default('a', mode='normal') + + assert key_config_stub.get_command('a', mode='normal') == default_cmd + + def test_bind_default_unbound(self, key_config_stub, config_stub, + no_bindings): + """Try binding a key to default which is not bound.""" + config_stub.val.bindings.default = no_bindings + config_stub.val.bindings.commands = no_bindings + with pytest.raises(configexc.KeybindingError, + match="Can't find binding 'foobar' in normal mode"): + key_config_stub.bind_default('foobar', mode='normal') + @pytest.mark.parametrize('key, normalized', [ ('a', 'a'), # default bindings ('b', 'b'), # custom bindings diff --git a/tests/unit/config/test_configcommands.py b/tests/unit/config/test_configcommands.py index 7b4588e03..fa6d98567 100644 --- a/tests/unit/config/test_configcommands.py +++ b/tests/unit/config/test_configcommands.py @@ -494,6 +494,30 @@ class TestBind: config_stub.val.bindings.commands = None commands.bind(',x', 'nop') + def test_bind_default(self, commands, key_config_stub, config_stub): + """Bind a key to its default.""" + default_cmd = 'message-info default' + bound_cmd = 'message-info bound' + config_stub.val.bindings.default = {'normal': {'a': default_cmd}} + config_stub.val.bindings.commands = {'normal': {'a': bound_cmd}} + assert key_config_stub.get_command('a', mode='normal') == bound_cmd + + commands.bind('a', mode='normal', default=True) + + assert key_config_stub.get_command('a', mode='normal') == default_cmd + + @pytest.mark.parametrize('key, mode, expected', [ + ('foobar', 'normal', "Can't find binding 'foobar' in normal mode"), + ('x', 'wrongmode', "Invalid mode wrongmode!"), + ]) + def test_bind_default_invalid(self, commands, key, mode, expected): + """Run ':bind --default foobar' / ':bind --default x wrongmode'. + + Should show an error. + """ + with pytest.raises(cmdexc.CommandError, match=expected): + commands.bind(key, mode=mode, default=True) + def test_unbind_none(self, commands, config_stub): config_stub.val.bindings.commands = None commands.unbind('H')