Add :bind --default

Closes #3059
This commit is contained in:
Florian Bruhin 2017-10-08 21:48:48 +02:00
parent 83fdb68fc2
commit 36ef68c698
5 changed files with 69 additions and 2 deletions

View File

@ -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.

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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')