Merge branch 'rcorre-keyhint_fix'
This commit is contained in:
commit
d67bfc8c45
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -94,28 +94,31 @@ class KeyHintView(QLabel):
|
||||
self.hide()
|
||||
return
|
||||
|
||||
keyconf = objreg.get('key-config')
|
||||
bindings = [(k, v) for (k, v)
|
||||
in keyconf.get_bindings_for(modename).items()
|
||||
if k.startswith(prefix) and not utils.is_special_key(k)]
|
||||
|
||||
if not bindings:
|
||||
return
|
||||
|
||||
self.show()
|
||||
suffix_color = html.escape(config.get('colors', 'keyhint.fg.suffix'))
|
||||
|
||||
text = ''
|
||||
keyconf = objreg.get('key-config')
|
||||
# this is only fired in normal mode
|
||||
for key, cmd in keyconf.get_bindings_for(modename).items():
|
||||
# for now, special keys can't be part of keychains, so ignore them
|
||||
is_special_binding = key.startswith('<') and key.endswith('>')
|
||||
if key.startswith(prefix) and not is_special_binding:
|
||||
text += (
|
||||
"<tr>"
|
||||
"<td>{}</td>"
|
||||
"<td style='color: {}'>{}</td>"
|
||||
"<td style='padding-left: 2ex'>{}</td>"
|
||||
"</tr>"
|
||||
).format(
|
||||
html.escape(prefix),
|
||||
suffix_color,
|
||||
html.escape(key[len(prefix):]),
|
||||
html.escape(cmd)
|
||||
)
|
||||
for key, cmd in bindings:
|
||||
text += (
|
||||
"<tr>"
|
||||
"<td>{}</td>"
|
||||
"<td style='color: {}'>{}</td>"
|
||||
"<td style='padding-left: 2ex'>{}</td>"
|
||||
"</tr>"
|
||||
).format(
|
||||
html.escape(prefix),
|
||||
suffix_color,
|
||||
html.escape(key[len(prefix):]),
|
||||
html.escape(cmd)
|
||||
)
|
||||
text = '<table>{}</table>'.format(text)
|
||||
|
||||
self.setText(text)
|
||||
|
@ -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. <ctrl-x> or <space>)."""
|
||||
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 <Ctrl-x> 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]
|
||||
|
@ -110,3 +110,12 @@ def test_color_switch(keyhint, config_stub, key_config_stub):
|
||||
('aa', 'cmd-aa')]))
|
||||
keyhint.update_keyhint('normal', 'a')
|
||||
assert keyhint.text() == expected_text(('a', '#ABCDEF', 'a', 'cmd-aa'))
|
||||
|
||||
|
||||
def test_no_matches(keyhint, key_config_stub):
|
||||
"""Ensure the widget isn't visible if there are no keystrings to show."""
|
||||
key_config_stub.set_bindings_for('normal', OrderedDict([
|
||||
('aa', 'cmd-aa'),
|
||||
('ab', 'cmd-ab')]))
|
||||
keyhint.update_keyhint('normal', 'z')
|
||||
assert not keyhint.isVisible()
|
||||
|
@ -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', [
|
||||
('<Control-x>', True),
|
||||
('<Meta-x>', True),
|
||||
('<Ctrl-Alt-y>', True),
|
||||
('x', False),
|
||||
('X', False),
|
||||
('<Escape>', True),
|
||||
('foobar', False),
|
||||
('foo>', False),
|
||||
('<foo', False),
|
||||
('<<', False),
|
||||
])
|
||||
def test_is_special_key(keystr, expected):
|
||||
assert utils.is_special_key(keystr) == expected
|
||||
|
Loading…
Reference in New Issue
Block a user