diff --git a/qutebrowser/completion/models/miscmodels.py b/qutebrowser/completion/models/miscmodels.py index 831243312..4b48290d9 100644 --- a/qutebrowser/completion/models/miscmodels.py +++ b/qutebrowser/completion/models/miscmodels.py @@ -24,7 +24,7 @@ from PyQt5.QtCore import Qt, QTimer, pyqtSlot from qutebrowser.browser import webview from qutebrowser.config import config, configdata -from qutebrowser.utils import objreg, log, qtutils +from qutebrowser.utils import objreg, log, qtutils, utils from qutebrowser.commands import cmdutils from qutebrowser.completion.models import base @@ -57,7 +57,7 @@ class CommandCompletionModel(base.BaseCompletionModel): cmd_to_keys = defaultdict(list) for key, cmd in keyconf.get_bindings_for('normal').items(): # put special bindings last - if key.startswith('<') and key.endswith('>'): + if utils.is_special_key(key): cmd_to_keys[cmd].append(key) else: cmd_to_keys[cmd].insert(0, key) diff --git a/qutebrowser/keyinput/basekeyparser.py b/qutebrowser/keyinput/basekeyparser.py index 4accafcb6..dd8535234 100644 --- a/qutebrowser/keyinput/basekeyparser.py +++ b/qutebrowser/keyinput/basekeyparser.py @@ -335,7 +335,7 @@ class BaseKeyParser(QObject): def _parse_key_command(self, modename, key, cmd): """Parse the keys and their command and store them in the object.""" - if key.startswith('<') and key.endswith('>'): + if utils.is_special_key(key): keystr = utils.normalize_keystr(key[1:-1]) self.special_bindings[keystr] = cmd elif self._supports_chains: diff --git a/qutebrowser/misc/keyhintwidget.py b/qutebrowser/misc/keyhintwidget.py index 270983b74..c3864c691 100644 --- a/qutebrowser/misc/keyhintwidget.py +++ b/qutebrowser/misc/keyhintwidget.py @@ -95,10 +95,9 @@ class KeyHintView(QLabel): return keyconf = objreg.get('key-config') - is_special = lambda k: k.startswith('<') and k.endswith('>') - bindings = [(key, cmd) for (key, cmd) + bindings = [(k, v) for (k, v) in keyconf.get_bindings_for(modename).items() - if key.startswith(prefix) and not is_special(key)] + if k.startswith(prefix) and not utils.is_special_key(k)] if not bindings: return diff --git a/qutebrowser/utils/utils.py b/qutebrowser/utils/utils.py index c04516d36..febceca76 100644 --- a/qutebrowser/utils/utils.py +++ b/qutebrowser/utils/utils.py @@ -440,9 +440,14 @@ class KeyParseError(Exception): super().__init__("Could not parse {!r}: {}".format(keystr, error)) +def is_special_key(keystr): + """True if keystr is a 'special' keystring (e.g. or ).""" + return keystr.startswith('<') and keystr.endswith('>') + + def _parse_single_key(keystr): """Convert a single key string to a (Qt.Key, Qt.Modifiers, text) tuple.""" - if keystr.startswith('<') and keystr.endswith('>'): + if is_special_key(keystr): # Special key keystr = keystr[1:-1] elif len(keystr) == 1: @@ -489,7 +494,7 @@ def _parse_single_key(keystr): def parse_keystring(keystr): """Parse a keystring like or xyz and return a KeyInfo list.""" - if keystr.startswith('<') and keystr.endswith('>'): + if is_special_key(keystr): return [_parse_single_key(keystr)] else: return [_parse_single_key(char) for char in keystr] diff --git a/tests/unit/utils/test_utils.py b/tests/unit/utils/test_utils.py index b6950e969..52c36eee3 100644 --- a/tests/unit/utils/test_utils.py +++ b/tests/unit/utils/test_utils.py @@ -984,3 +984,19 @@ class TestGetSetClipboard: def test_supports_selection(self, clipboard_mock, selection): clipboard_mock.supportsSelection.return_value = selection assert utils.supports_selection() == selection + + +@pytest.mark.parametrize('keystr, expected', [ + ('', True), + ('', True), + ('', True), + ('x', False), + ('X', False), + ('', True), + ('foobar', False), + ('foo>', False), + ('