summaryrefslogtreecommitdiff
path: root/qutebrowser/keyinput
diff options
context:
space:
mode:
authorFlorian Bruhin <me@the-compiler.org>2020-06-17 13:16:14 +0200
committerFlorian Bruhin <me@the-compiler.org>2020-06-17 14:12:24 +0200
commitccc9d1779c3d753a9c2bc1d488ec32d85e7fc135 (patch)
treeec080b64afec16390fd3d98338f24577733258c7 /qutebrowser/keyinput
parent03a5291d0596989bba8e056c9be06489330bb9d0 (diff)
downloadqutebrowser-ccc9d1779c3d753a9c2bc1d488ec32d85e7fc135.tar.gz
qutebrowser-ccc9d1779c3d753a9c2bc1d488ec32d85e7fc135.zip
modeparsers: Refactor to avoid subclassing
Before the changes in this commit, we've had to have a subclassed parser for every mode, even if there was no special key handling going on in that mode. With a couple of changes, we can avoid many of those subclasses and only have subclasses for bigger changes (like hint or register modes). - The awkward handling of self._modename in _read_config() is now removed. _read_config() doesn't take an argument, always uses the mode in self._mode and gets called from __init__. - BaseKeyParser takes the mode as an argument to __init__. - The class attributes (do_log/passthrough/supports_count) now also get passed via the constructor.
Diffstat (limited to 'qutebrowser/keyinput')
-rw-r--r--qutebrowser/keyinput/basekeyparser.py63
-rw-r--r--qutebrowser/keyinput/modeman.py56
-rw-r--r--qutebrowser/keyinput/modeparsers.py119
3 files changed, 95 insertions, 143 deletions
diff --git a/qutebrowser/keyinput/basekeyparser.py b/qutebrowser/keyinput/basekeyparser.py
index 9eb20c166..cc7fdc5be 100644
--- a/qutebrowser/keyinput/basekeyparser.py
+++ b/qutebrowser/keyinput/basekeyparser.py
@@ -140,23 +140,16 @@ class BaseKeyParser(QObject):
Not intended to be instantiated directly. Subclasses have to override
execute() to do whatever they want to.
- Class Attributes:
- Match: types of a match between a binding and the keystring.
- partial: No keychain matched yet, but it's still possible in the
- future.
- definitive: Keychain matches exactly.
- none: No more matches possible.
-
- do_log: Whether to log keypresses or not.
- passthrough: Whether unbound keys should be passed through with this
- handler.
- supports_count: Whether count is supported.
-
Attributes:
+ mode_name: The name of the mode in the config.
bindings: Bound key bindings
+ _mode: The usertypes.KeyMode associated with this keyparser.
_win_id: The window ID this keyparser is associated with.
_sequence: The currently entered key sequence
- _modename: The name of the input mode associated with this keyparser.
+ _do_log: Whether to log keypresses or not.
+ passthrough: Whether unbound keys should be passed through with this
+ handler.
+ _supports_count: Whether count is supported.
Signals:
keystring_updated: Emitted when the keystring is updated.
@@ -169,21 +162,31 @@ class BaseKeyParser(QObject):
keystring_updated = pyqtSignal(str)
request_leave = pyqtSignal(usertypes.KeyMode, str, bool)
- do_log = True
- passthrough = False
- supports_count = True
- def __init__(self, win_id: int, parent: QObject = None) -> None:
+ def __init__(self, *, mode: usertypes.KeyMode,
+ win_id: int,
+ parent: QObject = None,
+ do_log: bool = True,
+ passthrough: bool = False,
+ supports_count: bool = True) -> None:
super().__init__(parent)
self._win_id = win_id
- self._modename = None
self._sequence = keyutils.KeySequence()
self._count = ''
+ self._mode = mode
+ self._do_log = do_log
+ self.passthrough = passthrough
+ self._supports_count = supports_count
self.bindings = BindingTrie()
+ self._read_config()
config.instance.changed.connect(self._on_config_changed)
def __repr__(self) -> str:
- return utils.get_repr(self)
+ return utils.get_repr(self, mode=self._mode,
+ win_id=self._win_id,
+ do_log=self._do_log,
+ passthrough=self.passthrough,
+ supports_count=self._supports_count)
def _debug_log(self, message: str) -> None:
"""Log a message to the debug log if logging is active.
@@ -191,7 +194,7 @@ class BaseKeyParser(QObject):
Args:
message: The message to log.
"""
- if self.do_log:
+ if self._do_log:
log.keyboard.debug(message)
def _match_key(self, sequence: keyutils.KeySequence) -> MatchResult:
@@ -234,7 +237,7 @@ class BaseKeyParser(QObject):
dry_run: bool) -> bool:
"""Try to match a key as count."""
txt = str(sequence[-1]) # To account for sequences changed above.
- if (txt in string.digits and self.supports_count and
+ if (txt in string.digits and self._supports_count and
not (not self._count and txt == '0')):
self._debug_log("Trying match as count")
assert len(txt) == 1, txt
@@ -319,22 +322,12 @@ class BaseKeyParser(QObject):
def _on_config_changed(self) -> None:
self._read_config()
- def _read_config(self, modename: str = None) -> None:
- """Read the configuration.
-
- Args:
- modename: Name of the mode to use.
- """
- if modename is None:
- if self._modename is None:
- raise ValueError("read_config called with no mode given, but "
- "None defined so far!")
- modename = self._modename
- else:
- self._modename = modename
+ def _read_config(self) -> None:
+ """Read the configuration."""
self.bindings = BindingTrie()
+ config_bindings = config.key_instance.get_bindings_for(self._mode.name)
- for key, cmd in config.key_instance.get_bindings_for(modename).items():
+ for key, cmd in config_bindings.items():
assert cmd
self.bindings[key] = cmd
diff --git a/qutebrowser/keyinput/modeman.py b/qutebrowser/keyinput/modeman.py
index eb96020f3..2ec956422 100644
--- a/qutebrowser/keyinput/modeman.py
+++ b/qutebrowser/keyinput/modeman.py
@@ -102,70 +102,86 @@ def init(win_id: int, parent: QObject) -> 'ModeManager':
parent=modeman),
usertypes.KeyMode.insert:
- modeparsers.PassthroughKeyParser(
- win_id=win_id,
+ modeparsers.CommandKeyParser(
mode=usertypes.KeyMode.insert,
+ win_id=win_id,
commandrunner=commandrunner,
- parent=modeman),
+ parent=modeman,
+ passthrough=True,
+ do_log=False,
+ supports_count=False),
usertypes.KeyMode.passthrough:
- modeparsers.PassthroughKeyParser(
- win_id=win_id,
+ modeparsers.CommandKeyParser(
mode=usertypes.KeyMode.passthrough,
+ win_id=win_id,
commandrunner=commandrunner,
- parent=modeman),
+ parent=modeman,
+ passthrough=True,
+ do_log=False,
+ supports_count=False),
usertypes.KeyMode.command:
- modeparsers.PassthroughKeyParser(
- win_id=win_id,
+ modeparsers.CommandKeyParser(
mode=usertypes.KeyMode.command,
+ win_id=win_id,
commandrunner=commandrunner,
- parent=modeman),
+ parent=modeman,
+ passthrough=True,
+ do_log=False,
+ supports_count=False),
usertypes.KeyMode.prompt:
- modeparsers.PassthroughKeyParser(
- win_id=win_id,
+ modeparsers.CommandKeyParser(
mode=usertypes.KeyMode.prompt,
+ win_id=win_id,
commandrunner=commandrunner,
- parent=modeman),
+ parent=modeman,
+ passthrough=True,
+ do_log=False,
+ supports_count=False),
usertypes.KeyMode.yesno:
- modeparsers.PromptKeyParser(
+ modeparsers.CommandKeyParser(
+ mode=usertypes.KeyMode.yesno,
win_id=win_id,
commandrunner=commandrunner,
- parent=modeman),
+ parent=modeman,
+ supports_count=False),
usertypes.KeyMode.caret:
- modeparsers.CaretKeyParser(
+ modeparsers.CommandKeyParser(
+ mode=usertypes.KeyMode.caret,
win_id=win_id,
commandrunner=commandrunner,
- parent=modeman),
+ parent=modeman,
+ passthrough=True),
usertypes.KeyMode.set_mark:
modeparsers.RegisterKeyParser(
- win_id=win_id,
mode=usertypes.KeyMode.set_mark,
+ win_id=win_id,
commandrunner=commandrunner,
parent=modeman),
usertypes.KeyMode.jump_mark:
modeparsers.RegisterKeyParser(
- win_id=win_id,
mode=usertypes.KeyMode.jump_mark,
+ win_id=win_id,
commandrunner=commandrunner,
parent=modeman),
usertypes.KeyMode.record_macro:
modeparsers.RegisterKeyParser(
- win_id=win_id,
mode=usertypes.KeyMode.record_macro,
+ win_id=win_id,
commandrunner=commandrunner,
parent=modeman),
usertypes.KeyMode.run_macro:
modeparsers.RegisterKeyParser(
- win_id=win_id,
mode=usertypes.KeyMode.run_macro,
+ win_id=win_id,
commandrunner=commandrunner,
parent=modeman),
} # type: ParserDictType
diff --git a/qutebrowser/keyinput/modeparsers.py b/qutebrowser/keyinput/modeparsers.py
index acac59ad5..e848250c0 100644
--- a/qutebrowser/keyinput/modeparsers.py
+++ b/qutebrowser/keyinput/modeparsers.py
@@ -51,10 +51,16 @@ class CommandKeyParser(basekeyparser.BaseKeyParser):
_commandrunner: CommandRunner instance.
"""
- def __init__(self, win_id: int,
+ def __init__(self, *, mode: usertypes.KeyMode,
+ win_id: int,
commandrunner: 'runners.CommandRunner',
- parent: QObject = None) -> None:
- super().__init__(win_id, parent)
+ parent: QObject = None,
+ do_log: bool = True,
+ passthrough: bool = False,
+ supports_count: bool = True) -> None:
+ super().__init__(mode=mode, win_id=win_id, parent=parent,
+ do_log=do_log, passthrough=passthrough,
+ supports_count=supports_count)
self._commandrunner = commandrunner
def execute(self, cmdstr: str, count: int = None) -> None:
@@ -72,11 +78,11 @@ class NormalKeyParser(CommandKeyParser):
_partial_timer: Timer to clear partial keypresses.
"""
- def __init__(self, win_id: int,
+ def __init__(self, *, win_id: int,
commandrunner: 'runners.CommandRunner',
parent: QObject = None) -> None:
- super().__init__(win_id, commandrunner, parent)
- self._read_config('normal')
+ super().__init__(mode=usertypes.KeyMode.normal, win_id=win_id,
+ commandrunner=commandrunner, parent=parent)
self._partial_timer = usertypes.Timer(self, 'partial-match')
self._partial_timer.setSingleShot(True)
self._partial_timer.timeout.connect(self._clear_partial_match)
@@ -130,55 +136,6 @@ class NormalKeyParser(CommandKeyParser):
self._inhibited = False
-class PassthroughKeyParser(CommandKeyParser):
-
- """KeyChainParser which passes through normal keys.
-
- Used for insert/passthrough modes.
-
- Attributes:
- _mode: The mode this keyparser is for.
- """
-
- do_log = False
- passthrough = True
- supports_count = False
-
- def __init__(self, win_id: int,
- mode: usertypes.KeyMode,
- commandrunner: 'runners.CommandRunner',
- parent: QObject = None) -> None:
- """Constructor.
-
- Args:
- mode: The mode this keyparser is for.
- parent: Qt parent.
- warn: Whether to warn if an ignored key was bound.
- """
- super().__init__(win_id, commandrunner, parent)
- self._read_config(mode.name)
- self._mode = mode
-
- def __repr__(self) -> str:
- return utils.get_repr(self, mode=self._mode)
-
-
-class PromptKeyParser(CommandKeyParser):
-
- """KeyParser for yes/no prompts."""
-
- supports_count = False
-
- def __init__(self, win_id: int,
- commandrunner: 'runners.CommandRunner',
- parent: QObject = None) -> None:
- super().__init__(win_id, commandrunner, parent)
- self._read_config('yesno')
-
- def __repr__(self) -> str:
- return utils.get_repr(self)
-
-
class HintKeyParser(CommandKeyParser):
"""KeyChainParser for hints.
@@ -189,17 +146,16 @@ class HintKeyParser(CommandKeyParser):
_last_press: The nature of the last keypress, a LastPress member.
"""
- supports_count = False
-
- def __init__(self, win_id: int,
+ def __init__(self, *, win_id: int,
commandrunner: 'runners.CommandRunner',
hintmanager: hints.HintManager,
parent: QObject = None) -> None:
- super().__init__(win_id, commandrunner, parent)
+ super().__init__(mode=usertypes.KeyMode.hint, win_id=win_id,
+ commandrunner=commandrunner, parent=parent,
+ supports_count=False)
self._hintmanager = hintmanager
self._filtertext = ''
self._last_press = LastPress.none
- self._read_config('hint')
self.keystring_updated.connect(self._hintmanager.handle_partial_key)
def _handle_filter_key(self, e: QKeyEvent) -> QKeySequence.SequenceMatch:
@@ -277,37 +233,23 @@ class HintKeyParser(CommandKeyParser):
self._filtertext = ''
-class CaretKeyParser(CommandKeyParser):
-
- """KeyParser for caret mode."""
-
- passthrough = True
-
- def __init__(self, win_id: int,
- commandrunner: 'runners.CommandRunner',
- parent: QObject = None) -> None:
- super().__init__(win_id, commandrunner, parent)
- self._read_config('caret')
-
-
class RegisterKeyParser(CommandKeyParser):
"""KeyParser for modes that record a register key.
Attributes:
- _mode: One of KeyMode.set_mark, KeyMode.jump_mark, KeyMode.record_macro
- and KeyMode.run_macro.
+ _register_mode: One of KeyMode.set_mark, KeyMode.jump_mark,
+ KeyMode.record_macro and KeyMode.run_macro.
"""
- supports_count = False
-
- def __init__(self, win_id: int,
+ def __init__(self, *, win_id: int,
mode: usertypes.KeyMode,
commandrunner: 'runners.CommandRunner',
parent: QObject = None) -> None:
- super().__init__(win_id, commandrunner, parent)
- self._mode = mode
- self._read_config('register')
+ super().__init__(mode=usertypes.KeyMode.register, win_id=win_id,
+ commandrunner=commandrunner, parent=parent,
+ supports_count=False)
+ self._register_mode = mode
def handle(self, e: QKeyEvent, *,
dry_run: bool = False) -> QKeySequence.SequenceMatch:
@@ -326,19 +268,20 @@ class RegisterKeyParser(CommandKeyParser):
window=self._win_id)
try:
- if self._mode == usertypes.KeyMode.set_mark:
+ if self._register_mode == usertypes.KeyMode.set_mark:
tabbed_browser.set_mark(key)
- elif self._mode == usertypes.KeyMode.jump_mark:
+ elif self._register_mode == usertypes.KeyMode.jump_mark:
tabbed_browser.jump_mark(key)
- elif self._mode == usertypes.KeyMode.record_macro:
+ elif self._register_mode == usertypes.KeyMode.record_macro:
macros.macro_recorder.record_macro(key)
- elif self._mode == usertypes.KeyMode.run_macro:
+ elif self._register_mode == usertypes.KeyMode.run_macro:
macros.macro_recorder.run_macro(self._win_id, key)
else:
- raise ValueError(
- "{} is not a valid register mode".format(self._mode))
+ raise ValueError("{} is not a valid register mode".format(
+ self._register_mode))
except cmdexc.Error as err:
message.error(str(err), stack=traceback.format_exc())
- self.request_leave.emit(self._mode, "valid register key", True)
+ self.request_leave.emit(
+ self._register_mode, "valid register key", True)
return QKeySequence.ExactMatch