Merge branch 'rcorre-keyhint_fix'

This commit is contained in:
Florian Bruhin 2016-05-20 13:07:47 +02:00
commit d67bfc8c45
6 changed files with 56 additions and 23 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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