diff options
author | Florian Bruhin <me@the-compiler.org> | 2020-06-17 13:16:14 +0200 |
---|---|---|
committer | Florian Bruhin <me@the-compiler.org> | 2020-06-17 14:12:24 +0200 |
commit | ccc9d1779c3d753a9c2bc1d488ec32d85e7fc135 (patch) | |
tree | ec080b64afec16390fd3d98338f24577733258c7 /qutebrowser | |
parent | 03a5291d0596989bba8e056c9be06489330bb9d0 (diff) | |
download | qutebrowser-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')
-rw-r--r-- | qutebrowser/keyinput/basekeyparser.py | 63 | ||||
-rw-r--r-- | qutebrowser/keyinput/modeman.py | 56 | ||||
-rw-r--r-- | qutebrowser/keyinput/modeparsers.py | 119 | ||||
-rw-r--r-- | qutebrowser/utils/usertypes.py | 4 |
4 files changed, 99 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 diff --git a/qutebrowser/utils/usertypes.py b/qutebrowser/utils/usertypes.py index 247946497..0b6f9c219 100644 --- a/qutebrowser/utils/usertypes.py +++ b/qutebrowser/utils/usertypes.py @@ -256,6 +256,10 @@ class KeyMode(enum.Enum): jump_mark = 10 record_macro = 11 run_macro = 12 + # 'register' is a bit of an oddball here: It's not really a "real" mode, + # but it's used in the config for common bindings for + # set_mark/jump_mark/record_macro/run_macro. + register = 13 class Exit(enum.IntEnum): |