Initial update for better bindings management

This commit is contained in:
Florian Bruhin 2017-06-30 16:26:26 +02:00
parent 127db2fe42
commit 0115285a84
4 changed files with 66 additions and 21 deletions

View File

@ -131,10 +131,20 @@ class KeyConfig:
def __init__(self, config): def __init__(self, config):
self._config = config self._config = config
def get_bindings_for(self, mode):
"""Get the combined bindings for the given mode."""
if val.bindings.default:
bindings = dict(val.bindings.default[mode])
else:
bindings = {}
if val.bindings.commands:
bindings.update(val.bindings.default[mode])
return bindings
def get_reverse_bindings_for(self, mode): def get_reverse_bindings_for(self, mode):
"""Get a dict of commands to a list of bindings for the mode.""" """Get a dict of commands to a list of bindings for the mode."""
cmd_to_keys = {} cmd_to_keys = {}
bindings = val.bindings.commands[mode] bindings = self.get_bindings_for(mode)
if bindings is None: if bindings is None:
return cmd_to_keys return cmd_to_keys
for key, full_cmd in bindings.items(): for key, full_cmd in bindings.items():
@ -150,7 +160,7 @@ class KeyConfig:
def _prepare(self, key, mode): def _prepare(self, key, mode):
"""Make sure the given mode exists and normalize the key.""" """Make sure the given mode exists and normalize the key."""
if mode not in val.bindings.commands: if mode not in configdata.DATA['bindings.default'].default:
raise configexc.KeybindingError("Invalid mode {}!".format(mode)) raise configexc.KeybindingError("Invalid mode {}!".format(mode))
if utils.is_special_key(key): if utils.is_special_key(key):
# <Ctrl-t>, <ctrl-T>, and <ctrl-t> should be considered equivalent # <Ctrl-t>, <ctrl-T>, and <ctrl-t> should be considered equivalent
@ -173,24 +183,29 @@ class KeyConfig:
except cmdexc.PrerequisitesError as e: except cmdexc.PrerequisitesError as e:
raise configexc.KeybindingError(str(e)) raise configexc.KeybindingError(str(e))
bindings = instance.get_obj('bindings.commands')[mode]
log.keyboard.vdebug("Adding binding {} -> {} in mode {}.".format( log.keyboard.vdebug("Adding binding {} -> {} in mode {}.".format(
key, command, mode)) key, command, mode))
if key in bindings and not force: if key in self.get_bindings_for(mode) and not force:
raise configexc.DuplicateKeyError(key) raise configexc.DuplicateKeyError(key)
bindings[key] = command
val.bindings.commands[mode][key] = command
self._config.update_mutables(save_yaml=save_yaml) self._config.update_mutables(save_yaml=save_yaml)
def unbind(self, key, *, mode='normal', save_yaml=False): def unbind(self, key, *, mode='normal', save_yaml=False):
"""Unbind the given key in the given mode.""" """Unbind the given key in the given mode."""
key = self._prepare(key, mode) key = self._prepare(key, mode)
bindings = instance.get_obj('bindings.commands')[mode]
try: if val.bindings.commands[mode] and key in val.bindings.commands[mode]:
del bindings[key] # In custom bindings -> remove it
except KeyError: del val.bindings.commands[mode][key]
elif val.bindings.default[mode] and key in val.bindings.default[mode]:
# In default bindings -> shadow it with <unbound>
# FIXME:conf what value to use here?
val.bindings.commands[mode][key] = '<unbound>'
else:
raise configexc.KeybindingError("Can't find binding '{}' in section '{}'!" raise configexc.KeybindingError("Can't find binding '{}' in section '{}'!"
.format(key, mode)) .format(key, mode))
self._config.update_mutables(save_yaml=save_yaml) self._config.update_mutables(save_yaml=save_yaml)
def get_command(self, key, mode): def get_command(self, key, mode):
@ -302,14 +317,11 @@ class ConfigCommands:
(default: `normal`). (default: `normal`).
force: Rebind the key if it is already bound. force: Rebind the key if it is already bound.
""" """
if utils.is_special_key(key):
# <Ctrl-t>, <ctrl-T>, and <ctrl-t> should be considered equivalent
key = utils.normalize_keystr(key)
if mode not in val.bindings.commands:
raise cmdexc.CommandError("Invalid mode {}!".format(mode))
if command is None: if command is None:
if utils.is_special_key(key):
# key_instance.get_command does this, but we also need it
# normalized for the output below
key = utils.normalize_keystr(key)
cmd = key_instance.get_command(key, mode) cmd = key_instance.get_command(key, mode)
if cmd is None: if cmd is None:
message.info("{} is unbound in {} mode".format(key, mode)) message.info("{} is unbound in {} mode".format(key, mode))

View File

@ -1822,7 +1822,7 @@ bindings.key_mappings:
This is useful for global remappings of keys, for example to map Ctrl-[ to This is useful for global remappings of keys, for example to map Ctrl-[ to
Escape. Escape.
bindings.commands: bindings.default:
default: default:
normal: normal:
<Escape>: clear-keychain ;; search ;; fullscreen --leave <Escape>: clear-keychain ;; search ;; fullscreen --leave
@ -2067,6 +2067,38 @@ bindings.commands:
<Escape>: leave-mode <Escape>: leave-mode
type: type:
name: Dict name: Dict
none_ok: true
keytype: String # section name
fixed_keys: ['normal', 'insert', 'hint', 'passthrough', 'command',
'prompt', 'caret', 'register']
valtype:
name: Dict
keytype: Key
valtype: Command
desc: >-
Default keybindings. If you want to add bindings, modify
`bindings.commands` instead.
The main purpose of this setting is that you can set it to an empty dictionary if you
want to load no default keybindings at all.
If you want to preserve default bindings (and get new bindings when there is
an update), add new bindings to `bindings.commands` (or use `:bind`) and
leave this setting alone.
bindings.commands:
default: {}
# normal: {}
# insert: {}
# hint: {}
# passthrough: {}
# command: {}
# prompt: {}
# caret: {}
# register: {}
type:
name: Dict
none_ok: true
keytype: String # section name keytype: String # section name
fixed_keys: ['normal', 'insert', 'hint', 'passthrough', 'command', fixed_keys: ['normal', 'insert', 'hint', 'passthrough', 'command',
'prompt', 'caret', 'register'] 'prompt', 'caret', 'register']

View File

@ -345,7 +345,7 @@ class BaseKeyParser(QObject):
self.bindings = {} self.bindings = {}
self.special_bindings = {} self.special_bindings = {}
for key, cmd in config.val.bindings.commands[modename].items(): for key, cmd in config.key_instance.get_bindings_for(modename).items():
assert cmd assert cmd
self._parse_key_command(modename, key, cmd) self._parse_key_command(modename, key, cmd)

View File

@ -96,11 +96,12 @@ class KeyHintView(QLabel):
return any(fnmatch.fnmatchcase(keychain, glob) return any(fnmatch.fnmatchcase(keychain, glob)
for glob in blacklist) for glob in blacklist)
if config.val.bindings.commands[modename] is None: bindings_dict = config.key_instance.get_bindings_for(modename)
if not bindings_dict:
bindings = [] bindings = []
else: else:
bindings = [(k, v) for (k, v) bindings = [(k, v) for (k, v)
in config.val.bindings.commands[modename].items() in bindings_dict.items()
if k.startswith(prefix) and if k.startswith(prefix) and
not utils.is_special_key(k) and not utils.is_special_key(k) and
not blacklisted(k)] not blacklisted(k)]