Refactor key mode/parser handling in modeman.
This commit is contained in:
parent
728f06e797
commit
b55e22b5c3
@ -49,6 +49,8 @@ class BaseKeyParser(QObject):
|
||||
special: execute() was called via a special key binding
|
||||
|
||||
do_log: Whether to log keypresses or not.
|
||||
passthrough: Whether unbound keys should be passed through with this
|
||||
handler.
|
||||
|
||||
Attributes:
|
||||
bindings: Bound key bindings
|
||||
@ -69,6 +71,7 @@ class BaseKeyParser(QObject):
|
||||
|
||||
keystring_updated = pyqtSignal(str)
|
||||
do_log = True
|
||||
passthrough = False
|
||||
|
||||
Match = usertypes.enum('Match', ['partial', 'definitive', 'ambiguous',
|
||||
'other', 'none'])
|
||||
|
@ -55,6 +55,7 @@ class PassthroughKeyParser(CommandKeyParser):
|
||||
"""
|
||||
|
||||
do_log = False
|
||||
passthrough = True
|
||||
|
||||
def __init__(self, win_id, mode, parent=None, warn=True):
|
||||
"""Constructor.
|
||||
|
@ -84,16 +84,8 @@ def init(win_id, parent):
|
||||
modeman.destroyed.connect(
|
||||
functools.partial(objreg.delete, 'keyparsers', scope='window',
|
||||
window=win_id))
|
||||
modeman.register(KM.normal, keyparsers[KM.normal].handle)
|
||||
modeman.register(KM.hint, keyparsers[KM.hint].handle)
|
||||
modeman.register(KM.insert, keyparsers[KM.insert].handle, passthrough=True)
|
||||
modeman.register(KM.passthrough, keyparsers[KM.passthrough].handle,
|
||||
passthrough=True)
|
||||
modeman.register(KM.command, keyparsers[KM.command].handle,
|
||||
passthrough=True)
|
||||
modeman.register(KM.prompt, keyparsers[KM.prompt].handle, passthrough=True)
|
||||
modeman.register(KM.yesno, keyparsers[KM.yesno].handle)
|
||||
modeman.register(KM.caret, keyparsers[KM.caret].handle, passthrough=True)
|
||||
for mode, parser in keyparsers.items():
|
||||
modeman.register(mode, parser)
|
||||
return modeman
|
||||
|
||||
|
||||
@ -126,10 +118,9 @@ class ModeManager(QObject):
|
||||
"""Manager for keyboard modes.
|
||||
|
||||
Attributes:
|
||||
passthrough: A list of modes in which to pass through events.
|
||||
mode: The mode we're currently in.
|
||||
_win_id: The window ID of this ModeManager
|
||||
_handlers: A dictionary of modes and their handlers.
|
||||
_parsers: A dictionary of modes and their keyparsers.
|
||||
_forward_unbound_keys: If we should forward unbound keys.
|
||||
_releaseevents_to_pass: A set of KeyEvents where the keyPressEvent was
|
||||
passed through, so the release event should as
|
||||
@ -151,8 +142,7 @@ class ModeManager(QObject):
|
||||
def __init__(self, win_id, parent=None):
|
||||
super().__init__(parent)
|
||||
self._win_id = win_id
|
||||
self._handlers = {}
|
||||
self.passthrough = []
|
||||
self._parsers = {}
|
||||
self.mode = usertypes.KeyMode.normal
|
||||
self._releaseevents_to_pass = set()
|
||||
self._forward_unbound_keys = config.get(
|
||||
@ -160,8 +150,7 @@ class ModeManager(QObject):
|
||||
objreg.get('config').changed.connect(self.set_forward_unbound_keys)
|
||||
|
||||
def __repr__(self):
|
||||
return utils.get_repr(self, mode=self.mode,
|
||||
passthrough=self.passthrough)
|
||||
return utils.get_repr(self, mode=self.mode)
|
||||
|
||||
def _eventFilter_keypress(self, event):
|
||||
"""Handle filtering of KeyPress events.
|
||||
@ -173,11 +162,11 @@ class ModeManager(QObject):
|
||||
True if event should be filtered, False otherwise.
|
||||
"""
|
||||
curmode = self.mode
|
||||
handler = self._handlers[curmode]
|
||||
parser = self._parsers[curmode]
|
||||
if curmode != usertypes.KeyMode.insert:
|
||||
log.modes.debug("got keypress in mode {} - calling handler "
|
||||
"{}".format(curmode, utils.qualname(handler)))
|
||||
handled = handler(event) if handler is not None else False
|
||||
log.modes.debug("got keypress in mode {} - delegating to "
|
||||
"{}".format(curmode, utils.qualname(parser)))
|
||||
handled = parser.handle(event)
|
||||
|
||||
is_non_alnum = bool(event.modifiers()) or not event.text().strip()
|
||||
focus_widget = QApplication.instance().focusWidget()
|
||||
@ -187,7 +176,7 @@ class ModeManager(QObject):
|
||||
filter_this = True
|
||||
elif is_tab and not isinstance(focus_widget, QWebView):
|
||||
filter_this = True
|
||||
elif (curmode in self.passthrough or
|
||||
elif (parser.passthrough or
|
||||
self._forward_unbound_keys == 'all' or
|
||||
(self._forward_unbound_keys == 'auto' and is_non_alnum)):
|
||||
filter_this = False
|
||||
@ -202,8 +191,8 @@ class ModeManager(QObject):
|
||||
"passthrough: {}, is_non_alnum: {}, is_tab {} --> "
|
||||
"filter: {} (focused: {!r})".format(
|
||||
handled, self._forward_unbound_keys,
|
||||
curmode in self.passthrough, is_non_alnum,
|
||||
is_tab, filter_this, focus_widget))
|
||||
parser.passthrough, is_non_alnum, is_tab,
|
||||
filter_this, focus_widget))
|
||||
return filter_this
|
||||
|
||||
def _eventFilter_keyrelease(self, event):
|
||||
@ -226,20 +215,16 @@ class ModeManager(QObject):
|
||||
log.modes.debug("filter: {}".format(filter_this))
|
||||
return filter_this
|
||||
|
||||
def register(self, mode, handler, passthrough=False):
|
||||
def register(self, mode, parser):
|
||||
"""Register a new mode.
|
||||
|
||||
Args:
|
||||
mode: The name of the mode.
|
||||
handler: Handler for keyPressEvents.
|
||||
passthrough: Whether to pass key bindings in this mode through to
|
||||
the widgets.
|
||||
parser: The KeyParser which should be used.
|
||||
"""
|
||||
if not isinstance(mode, usertypes.KeyMode):
|
||||
raise TypeError("Mode {} is no KeyMode member!".format(mode))
|
||||
self._handlers[mode] = handler
|
||||
if passthrough:
|
||||
self.passthrough.append(mode)
|
||||
assert isinstance(mode, usertypes.KeyMode)
|
||||
assert parser is not None
|
||||
self._parsers[mode] = parser
|
||||
|
||||
def enter(self, mode, reason=None, only_if_normal=False):
|
||||
"""Enter a new mode.
|
||||
@ -253,8 +238,8 @@ class ModeManager(QObject):
|
||||
raise TypeError("Mode {} is no KeyMode member!".format(mode))
|
||||
log.modes.debug("Entering mode {}{}".format(
|
||||
mode, '' if reason is None else ' (reason: {})'.format(reason)))
|
||||
if mode not in self._handlers:
|
||||
raise ValueError("No handler for mode {}".format(mode))
|
||||
if mode not in self._parsers:
|
||||
raise ValueError("No keyparser for mode {}".format(mode))
|
||||
prompt_modes = (usertypes.KeyMode.prompt, usertypes.KeyMode.yesno)
|
||||
if self.mode == mode or (self.mode in prompt_modes and
|
||||
mode in prompt_modes):
|
||||
|
@ -224,6 +224,8 @@ class CaretKeyParser(keyparser.CommandKeyParser):
|
||||
|
||||
"""KeyParser for caret mode."""
|
||||
|
||||
passthrough = True
|
||||
|
||||
def __init__(self, win_id, parent=None):
|
||||
super().__init__(win_id, parent, supports_count=True,
|
||||
supports_chains=True)
|
||||
|
@ -469,9 +469,9 @@ class StatusBar(QWidget):
|
||||
@pyqtSlot(usertypes.KeyMode)
|
||||
def on_mode_entered(self, mode):
|
||||
"""Mark certain modes in the commandline."""
|
||||
mode_manager = objreg.get('mode-manager', scope='window',
|
||||
window=self._win_id)
|
||||
if mode in mode_manager.passthrough:
|
||||
keyparsers = objreg.get('keyparsers', scope='window',
|
||||
window=self._win_id)
|
||||
if keyparsers[mode].passthrough:
|
||||
self._set_mode_text(mode.name)
|
||||
if mode in (usertypes.KeyMode.insert, usertypes.KeyMode.caret):
|
||||
self.set_mode_active(mode, True)
|
||||
@ -479,10 +479,10 @@ class StatusBar(QWidget):
|
||||
@pyqtSlot(usertypes.KeyMode, usertypes.KeyMode)
|
||||
def on_mode_left(self, old_mode, new_mode):
|
||||
"""Clear marked mode."""
|
||||
mode_manager = objreg.get('mode-manager', scope='window',
|
||||
window=self._win_id)
|
||||
if old_mode in mode_manager.passthrough:
|
||||
if new_mode in mode_manager.passthrough:
|
||||
keyparsers = objreg.get('keyparsers', scope='window',
|
||||
window=self._win_id)
|
||||
if keyparsers[old_mode].passthrough:
|
||||
if keyparsers[new_mode].passthrough:
|
||||
self._set_mode_text(new_mode.name)
|
||||
else:
|
||||
self.txt.set_text(self.txt.Text.normal, '')
|
||||
|
Loading…
Reference in New Issue
Block a user