From 1dc20f4d02074a9f34bac67219ff3bbc55b7c857 Mon Sep 17 00:00:00 2001 From: Ryan Roden-Corrent Date: Fri, 3 Jun 2016 23:04:44 -0400 Subject: [PATCH 1/2] Handle special keystrings case-insensitively. Load all special keystrings (e.g. ) into memory as lowercase, and automatically lowercase any special keystring given to bind/unbind. This prevents and from being treated differently. Resolves #816. Also resolves #1544 (dupe). --- qutebrowser/config/parsers/keyconf.py | 11 +++++++++++ tests/end2end/features/keyinput.feature | 22 ++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/qutebrowser/config/parsers/keyconf.py b/qutebrowser/config/parsers/keyconf.py index 71ca14ceb..8841bea73 100644 --- a/qutebrowser/config/parsers/keyconf.py +++ b/qutebrowser/config/parsers/keyconf.py @@ -165,6 +165,10 @@ class KeyConfigParser(QObject): (default: `normal`). force: Rebind the key if it is already bound. """ + if utils.is_special_key(key): + # , , and should be considered equivalent + key = key.lower() + if mode is None: mode = 'normal' @@ -206,6 +210,10 @@ class KeyConfigParser(QObject): mode: A comma-separated list of modes to unbind the key in (default: `normal`). """ + if utils.is_special_key(key): + # , , and should be considered equivalent + key = key.lower() + if mode is None: mode = 'normal' mode = self._normalize_sectname(mode) @@ -377,6 +385,9 @@ class KeyConfigParser(QObject): def _add_binding(self, sectname, keychain, command, *, force=False): """Add a new binding from keychain to command in section sectname.""" + if utils.is_special_key(keychain): + # , , and should be considered equivalent + keychain = keychain.lower() log.keyboard.vdebug("Adding binding {} -> {} in mode {}.".format( keychain, command, sectname)) if sectname not in self.keybindings: diff --git a/tests/end2end/features/keyinput.feature b/tests/end2end/features/keyinput.feature index 4385c2357..b2fa4729c 100644 --- a/tests/end2end/features/keyinput.feature +++ b/tests/end2end/features/keyinput.feature @@ -45,6 +45,22 @@ Feature: Keyboard input And I run :bind --mode=caret test08 Then the message "test08 is bound to 'message-info bar' in caret mode" should be shown + Scenario: Binding special keys with differing case (issue 1544) + When I run :bind message-info test01 + And I run :bind message-info test01 + Then the error "Duplicate keychain - use --force to override!" should be shown + + Scenario: Print a special binding with differing case (issue 1544) + When I run :bind message-info foo + And I run :bind + Then the message " is bound to 'message-info foo' in normal mode" should be shown + + Scenario: Overriding a special binding with differing case (issue 816) + When I run :bind message-info foo + And I run :bind --force message-info bar + And I run :bind + Then the message " is bound to 'message-info bar' in normal mode" should be shown + # :unbind Scenario: Binding and unbinding a keychain @@ -67,6 +83,12 @@ Feature: Keyboard input Then "No binding found for o." should be logged # maybe check it's unbound in the config? + Scenario: Binding and unbinding a special keychain with differing case (issue 1544) + When I run :bind message-error test09 + And I run :unbind + When I run :bind + Then the message " is unbound in normal mode" should be shown + # :clear-keychain Scenario: Clearing the keychain From 9f660a98f265d1bc24839eb9c146ae7e10cb3c84 Mon Sep 17 00:00:00 2001 From: Ryan Roden-Corrent Date: Sat, 4 Jun 2016 07:29:56 -0400 Subject: [PATCH 2/2] Default mode='normal' for bind/unbind. Both set mode=None, then later checked if mode == 'None' and set it to 'normal'. This reduces the function complexity just enough that pylint will stop complaining. --- qutebrowser/config/parsers/keyconf.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/qutebrowser/config/parsers/keyconf.py b/qutebrowser/config/parsers/keyconf.py index 8841bea73..7c00b9584 100644 --- a/qutebrowser/config/parsers/keyconf.py +++ b/qutebrowser/config/parsers/keyconf.py @@ -154,7 +154,7 @@ class KeyConfigParser(QObject): @cmdutils.argument('win_id', win_id=True) @cmdutils.argument('key', completion=usertypes.Completion.empty) @cmdutils.argument('command', completion=usertypes.Completion.command) - def bind(self, key, win_id, command=None, *, mode=None, force=False): + def bind(self, key, win_id, command=None, *, mode='normal', force=False): """Bind a key to a command. Args: @@ -169,9 +169,6 @@ class KeyConfigParser(QObject): # , , and should be considered equivalent key = key.lower() - if mode is None: - mode = 'normal' - if command is None: cmd = self.get_bindings_for(mode).get(key, None) if cmd is None: @@ -202,7 +199,7 @@ class KeyConfigParser(QObject): self._mark_config_dirty() @cmdutils.register(instance='key-config') - def unbind(self, key, mode=None): + def unbind(self, key, mode='normal'): """Unbind a keychain. Args: @@ -214,8 +211,6 @@ class KeyConfigParser(QObject): # , , and should be considered equivalent key = key.lower() - if mode is None: - mode = 'normal' mode = self._normalize_sectname(mode) for m in mode.split(','): if m not in configdata.KEY_DATA: