Merge branch 'better_keyhints' of https://github.com/rcorre/qutebrowser into rcorre-better_keyhints
This commit is contained in:
commit
c96722f169
@ -341,6 +341,7 @@ class ConfigManager(QObject):
|
||||
('colors', 'tab.indicator.system'): 'tabs.indicator.system',
|
||||
('completion', 'history-length'): 'cmd-history-max-items',
|
||||
('colors', 'downloads.fg'): 'downloads.fg.start',
|
||||
('ui', 'show-keyhints'): 'keyhint-blacklist',
|
||||
}
|
||||
DELETED_OPTIONS = [
|
||||
('colors', 'tab.separator'),
|
||||
@ -360,6 +361,8 @@ class ConfigManager(QObject):
|
||||
_get_value_transformer({'false': '-1', 'true': '1000'}),
|
||||
('general', 'log-javascript-console'):
|
||||
_get_value_transformer({'false': 'none', 'true': 'debug'}),
|
||||
('ui', 'keyhint-blacklist'):
|
||||
_get_value_transformer({'false': '*', 'true': ''}),
|
||||
}
|
||||
|
||||
changed = pyqtSignal(str, str)
|
||||
|
@ -355,9 +355,11 @@ def data(readonly=False):
|
||||
"Hide the window decoration when using wayland "
|
||||
"(requires restart)"),
|
||||
|
||||
('show-keyhints',
|
||||
SettingValue(typ.Bool(), 'true'),
|
||||
"Show possible keychains based on the current keystring"),
|
||||
('keyhint-blacklist',
|
||||
SettingValue(typ.List(none_ok=True), ''),
|
||||
"Keychains that shouldn't be shown in the keyhint dialog\n\n"
|
||||
"Globs are supported, so ';*' will blacklist all keychains"
|
||||
"starting with ';'. Use '*' to disable keyhints"),
|
||||
|
||||
readonly=readonly
|
||||
)),
|
||||
|
@ -25,12 +25,13 @@ It is intended to help discoverability of keybindings.
|
||||
"""
|
||||
|
||||
import html
|
||||
import fnmatch
|
||||
|
||||
from PyQt5.QtWidgets import QLabel, QSizePolicy
|
||||
from PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt
|
||||
|
||||
from qutebrowser.config import config, style
|
||||
from qutebrowser.utils import objreg, utils
|
||||
from qutebrowser.utils import objreg, utils, usertypes
|
||||
|
||||
|
||||
class KeyHintView(QLabel):
|
||||
@ -39,7 +40,6 @@ class KeyHintView(QLabel):
|
||||
|
||||
Attributes:
|
||||
_win_id: Window ID of parent.
|
||||
_enabled: If False, do not show the window at all
|
||||
|
||||
Signals:
|
||||
reposition_keyhint: Emitted when this widget should be resized.
|
||||
@ -61,23 +61,16 @@ class KeyHintView(QLabel):
|
||||
super().__init__(parent)
|
||||
self.setTextFormat(Qt.RichText)
|
||||
self._win_id = win_id
|
||||
self.set_enabled()
|
||||
cfg = objreg.get('config')
|
||||
cfg.changed.connect(self.set_enabled)
|
||||
style.set_register_stylesheet(self)
|
||||
self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum)
|
||||
self.hide()
|
||||
self._show_timer = usertypes.Timer(self, 'keyhint_show')
|
||||
self._show_timer.setInterval(500)
|
||||
self._show_timer.timeout.connect(self.show)
|
||||
|
||||
def __repr__(self):
|
||||
return utils.get_repr(self, win_id=self._win_id)
|
||||
|
||||
@config.change_filter('ui', 'show-keyhints')
|
||||
def set_enabled(self):
|
||||
"""Update self._enabled when the config changed."""
|
||||
self._enabled = config.get('ui', 'show-keyhints')
|
||||
if not self._enabled:
|
||||
self.hide()
|
||||
|
||||
def showEvent(self, e):
|
||||
"""Adjust the keyhint size when it's freshly shown."""
|
||||
self.reposition_keyhint.emit()
|
||||
@ -90,19 +83,29 @@ class KeyHintView(QLabel):
|
||||
Args:
|
||||
prefix: The current partial keystring.
|
||||
"""
|
||||
if not prefix or not self._enabled:
|
||||
if not prefix:
|
||||
self._show_timer.stop()
|
||||
self.hide()
|
||||
return
|
||||
|
||||
blacklist = config.get('ui', 'keyhint-blacklist') or []
|
||||
keyconf = objreg.get('key-config')
|
||||
|
||||
def blacklisted(keychain):
|
||||
return any(fnmatch.fnmatchcase(keychain, glob)
|
||||
for glob in blacklist)
|
||||
|
||||
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 k.startswith(prefix) and not utils.is_special_key(k) and
|
||||
not blacklisted(k)]
|
||||
|
||||
if not bindings:
|
||||
self._show_timer.stop()
|
||||
return
|
||||
|
||||
self.show()
|
||||
# delay so a quickly typed keychain doesn't display hints
|
||||
self._show_timer.start()
|
||||
suffix_color = html.escape(config.get('colors', 'keyhint.fg.suffix'))
|
||||
|
||||
text = ''
|
||||
|
@ -34,7 +34,6 @@ def expected_text(*args):
|
||||
"""
|
||||
text = '<table>'
|
||||
for group in args:
|
||||
print("group = {}".format(group))
|
||||
text += ("<tr>"
|
||||
"<td>{}</td>"
|
||||
"<td style='color: {}'>{}</td>"
|
||||
@ -54,7 +53,7 @@ def keyhint(qtbot, config_stub, key_config_stub):
|
||||
'keyhint.bg': 'black'
|
||||
},
|
||||
'fonts': {'keyhint': 'Comic Sans'},
|
||||
'ui': {'show-keyhints': True},
|
||||
'ui': {'keyhint-blacklist': ''},
|
||||
}
|
||||
keyhint = KeyHintView(0, None)
|
||||
qtbot.add_widget(keyhint)
|
||||
@ -63,7 +62,7 @@ def keyhint(qtbot, config_stub, key_config_stub):
|
||||
|
||||
|
||||
def test_suggestions(keyhint, key_config_stub):
|
||||
"""Test cursor position based on the prompt."""
|
||||
"""Test that keyhints are shown based on a prefix."""
|
||||
# we want the dict to return sorted items() for reliable testing
|
||||
key_config_stub.set_bindings_for('normal', OrderedDict([
|
||||
('aa', 'cmd-aa'),
|
||||
@ -95,14 +94,6 @@ def test_special_bindings(keyhint, key_config_stub):
|
||||
('<', 'yellow', 'b', 'cmd-<b'))
|
||||
|
||||
|
||||
def test_disable(keyhint, config_stub):
|
||||
"""Ensure the widget isn't visible if disabled."""
|
||||
config_stub.set('ui', 'show-keyhints', False)
|
||||
keyhint.update_keyhint('normal', 'a')
|
||||
assert not keyhint.text()
|
||||
assert not keyhint.isVisible()
|
||||
|
||||
|
||||
def test_color_switch(keyhint, config_stub, key_config_stub):
|
||||
"""Ensure the the keyhint suffix color can be updated at runtime."""
|
||||
config_stub.set('colors', 'keyhint.fg.suffix', '#ABCDEF')
|
||||
@ -118,4 +109,37 @@ def test_no_matches(keyhint, key_config_stub):
|
||||
('aa', 'cmd-aa'),
|
||||
('ab', 'cmd-ab')]))
|
||||
keyhint.update_keyhint('normal', 'z')
|
||||
assert not keyhint.text()
|
||||
assert not keyhint.isVisible()
|
||||
|
||||
|
||||
def test_blacklist(keyhint, config_stub, key_config_stub):
|
||||
"""Test that blacklisted keychaints aren't hinted."""
|
||||
config_stub.set('ui', 'keyhint-blacklist', ['ab*'])
|
||||
# we want the dict to return sorted items() for reliable testing
|
||||
key_config_stub.set_bindings_for('normal', OrderedDict([
|
||||
('aa', 'cmd-aa'),
|
||||
('ab', 'cmd-ab'),
|
||||
('aba', 'cmd-aba'),
|
||||
('abb', 'cmd-abb'),
|
||||
('xd', 'cmd-xd'),
|
||||
('xe', 'cmd-xe')]))
|
||||
|
||||
keyhint.update_keyhint('normal', 'a')
|
||||
assert keyhint.text() == expected_text(('a', 'yellow', 'a', 'cmd-aa'))
|
||||
|
||||
|
||||
def test_blacklist_all(keyhint, config_stub, key_config_stub):
|
||||
"""Test that setting the blacklist to * disables keyhints."""
|
||||
config_stub.set('ui', 'keyhint-blacklist', ['*'])
|
||||
# we want the dict to return sorted items() for reliable testing
|
||||
key_config_stub.set_bindings_for('normal', OrderedDict([
|
||||
('aa', 'cmd-aa'),
|
||||
('ab', 'cmd-ab'),
|
||||
('aba', 'cmd-aba'),
|
||||
('abb', 'cmd-abb'),
|
||||
('xd', 'cmd-xd'),
|
||||
('xe', 'cmd-xe')]))
|
||||
|
||||
keyhint.update_keyhint('normal', 'a')
|
||||
assert not keyhint.text()
|
||||
|
Loading…
Reference in New Issue
Block a user