diff --git a/doc/help/settings.asciidoc b/doc/help/settings.asciidoc index 3a873028a..418783a31 100644 --- a/doc/help/settings.asciidoc +++ b/doc/help/settings.asciidoc @@ -191,7 +191,6 @@ |<>|Make chars in hint strings uppercase. |<>|The maximum time in minutes between two history items for them to be considered being from the same browsing session. |<>|Find text on a page case-insensitively. -|<>|Timeout (in milliseconds) for ambiguous key bindings. |<>|Forward unbound keys to the webview in normal mode. |<>|Leave insert mode if a non-editable element is clicked. |<>|Automatically enter insert mode if an editable element is focused after loading the page. @@ -2050,13 +2049,6 @@ Valid values: Default: +pass:[smart]+ -[[input.ambiguous_timeout]] -== input.ambiguous_timeout -Timeout (in milliseconds) for ambiguous key bindings. -If the current input forms both a complete match and a partial match, the complete match will be executed after this time. - -Default: +pass:[500]+ - [[input.forward_unbound_keys]] == input.forward_unbound_keys Forward unbound keys to the webview in normal mode. diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml index a94aa535f..912774876 100644 --- a/qutebrowser/config/configdata.yml +++ b/qutebrowser/config/configdata.yml @@ -794,19 +794,6 @@ hints.uppercase: ## input -# FIXME:conf get rid of this? -input.ambiguous_timeout: - default: 500 - type: - name: Int - minval: 0 - maxval: maxint - desc: >- - Timeout (in milliseconds) for ambiguous key bindings. - - If the current input forms both a complete match and a partial match, the complete - match will be executed after this time. - input.forward_unbound_keys: default: auto type: diff --git a/qutebrowser/keyinput/basekeyparser.py b/qutebrowser/keyinput/basekeyparser.py index bc27c7ffe..9eec4b28f 100644 --- a/qutebrowser/keyinput/basekeyparser.py +++ b/qutebrowser/keyinput/basekeyparser.py @@ -20,7 +20,6 @@ """Base class for vim-like key sequence parser.""" import re -import functools import unicodedata from PyQt5.QtCore import pyqtSignal, QObject @@ -41,7 +40,6 @@ class BaseKeyParser(QObject): partial: No keychain matched yet, but it's still possible in the future. definitive: Keychain matches exactly. - ambiguous: There are both a partial and a definitive match. none: No more matches possible. Types: type of a key binding. @@ -59,7 +57,6 @@ class BaseKeyParser(QObject): _warn_on_keychains: Whether a warning should be logged when binding keychains in a section which does not support them. _keystring: The currently entered key sequence - _ambiguous_timer: Timer for delayed execution with ambiguous bindings. _modename: The name of the input mode associated with this keyparser. _supports_count: Whether count is supported _supports_chains: Whether keychains are supported @@ -78,16 +75,13 @@ class BaseKeyParser(QObject): do_log = True passthrough = False - Match = usertypes.enum('Match', ['partial', 'definitive', 'ambiguous', - 'other', 'none']) + Match = usertypes.enum('Match', ['partial', 'definitive', 'other', 'none']) Type = usertypes.enum('Type', ['chain', 'special']) def __init__(self, win_id, parent=None, supports_count=None, supports_chains=False): super().__init__(parent) self._win_id = win_id - self._ambiguous_timer = usertypes.Timer(self, 'ambiguous-match') - self._ambiguous_timer.setSingleShot(True) self._modename = None self._keystring = '' if supports_count is None: @@ -189,7 +183,6 @@ class BaseKeyParser(QObject): self._debug_log("Ignoring, no text char") return self.Match.none - self._stop_timers() key_mappings = config.val.bindings.key_mappings txt = key_mappings.get(txt, txt) self._keystring += txt @@ -207,10 +200,6 @@ class BaseKeyParser(QObject): self._keystring)) self.clear_keystring() self.execute(binding, self.Type.chain, count) - elif match == self.Match.ambiguous: - self._debug_log("Ambiguous match for '{}'.".format( - self._keystring)) - self._handle_ambiguous_match(binding, count) elif match == self.Match.partial: self._debug_log("No match for '{}' (added {})".format( self._keystring, txt)) @@ -230,11 +219,9 @@ class BaseKeyParser(QObject): Return: A tuple (matchtype, binding). - matchtype: Match.definitive, Match.ambiguous, Match.partial or - Match.none - binding: - None with Match.partial/Match.none - - The found binding with Match.definitive/ - Match.ambiguous + matchtype: Match.definitive, Match.partial or Match.none. + binding: - None with Match.partial/Match.none. + - The found binding with Match.definitive. """ # A (cmd_input, binding) tuple (k, v of bindings) or None. definitive_match = None @@ -252,58 +239,13 @@ class BaseKeyParser(QObject): elif binding.startswith(cmd_input): partial_match = True break - if definitive_match is not None and partial_match: - return (self.Match.ambiguous, definitive_match[1]) - elif definitive_match is not None: + if definitive_match is not None: return (self.Match.definitive, definitive_match[1]) elif partial_match: return (self.Match.partial, None) else: return (self.Match.none, None) - def _stop_timers(self): - """Stop a delayed execution if any is running.""" - if self._ambiguous_timer.isActive() and self.do_log: - log.keyboard.debug("Stopping delayed execution.") - self._ambiguous_timer.stop() - try: - self._ambiguous_timer.timeout.disconnect() - except TypeError: - # no connections - pass - - def _handle_ambiguous_match(self, binding, count): - """Handle an ambiguous match. - - Args: - binding: The command-string to execute. - count: The count to pass. - """ - self._debug_log("Ambiguous match for '{}'".format(self._keystring)) - time = config.val.input.ambiguous_timeout - if time == 0: - # execute immediately - self.clear_keystring() - self.execute(binding, self.Type.chain, count) - else: - # execute in `time' ms - self._debug_log("Scheduling execution of {} in {}ms".format( - binding, time)) - self._ambiguous_timer.setInterval(time) - self._ambiguous_timer.timeout.connect( - functools.partial(self.delayed_exec, binding, count)) - self._ambiguous_timer.start() - - def delayed_exec(self, command, count): - """Execute a delayed command. - - Args: - command/count: As if passed to self.execute() - """ - self._debug_log("Executing delayed command now!") - self.clear_keystring() - self.execute(command, self.Type.chain, count) - def handle(self, e): """Handle a new keypress and call the respective handlers. diff --git a/tests/end2end/features/keyinput.feature b/tests/end2end/features/keyinput.feature index 1e16c5fd5..21642d165 100644 --- a/tests/end2end/features/keyinput.feature +++ b/tests/end2end/features/keyinput.feature @@ -7,11 +7,13 @@ Feature: Keyboard input # :clear-keychain Scenario: Clearing the keychain - When I run :bind foo message-error test12 - And I run :bind bar message-info test12-2 - And I press the keys "fo" + When I run :bind ,foo message-error test12 + And I run :bind ,bar message-info test12-2 + And I press the keys ",fo" And I run :clear-keychain - And I press the keys "bar" + And I press the keys ",bar" + And I run :unbind ,foo + And I run :unbind ,bar Then the message "test12-2" should be shown # input.forward_unbound_keys diff --git a/tests/unit/keyinput/test_basekeyparser.py b/tests/unit/keyinput/test_basekeyparser.py index 1df5e73c6..18f04266d 100644 --- a/tests/unit/keyinput/test_basekeyparser.py +++ b/tests/unit/keyinput/test_basekeyparser.py @@ -37,7 +37,6 @@ def keyparser(key_config_stub): 0, supports_count=True, supports_chains=True) kp.execute = mock.Mock() yield kp - assert not kp._ambiguous_timer.isActive() @pytest.fixture @@ -242,51 +241,15 @@ class TestKeyChain: 'message-info 0', keyparser.Type.chain, None) assert keyparser._keystring == '' - def test_ambiguous_keychain(self, qapp, handle_text, config_stub, - keyparser): - config_stub.val.input.ambiguous_timeout = 100 - timer = keyparser._ambiguous_timer - assert not timer.isActive() - # We start with 'a' where the keychain gives us an ambiguous result. - # Then we check if the timer has been set up correctly - handle_text((Qt.Key_A, 'a')) - assert not keyparser.execute.called - assert timer.isSingleShot() - assert timer.interval() == 100 - assert timer.isActive() - # Now we type an 'x' and check 'ax' has been executed and the timer - # stopped. - handle_text((Qt.Key_X, 'x')) - keyparser.execute.assert_called_once_with( - 'message-info ax', keyparser.Type.chain, None) - assert not timer.isActive() - assert keyparser._keystring == '' - - def test_ambiguous_keychain_no_timeout(self, handle_text, config_stub, - keyparser): - config_stub.val.input.ambiguous_timeout = 0 + def test_ambiguous_keychain(self, handle_text, keyparser): handle_text((Qt.Key_A, 'a')) assert keyparser.execute.called - assert not keyparser._ambiguous_timer.isActive() def test_invalid_keychain(self, handle_text, keyparser): handle_text((Qt.Key_B, 'b')) handle_text((Qt.Key_C, 'c')) assert keyparser._keystring == '' - def test_ambiguous_delayed_exec(self, handle_text, config_stub, qtbot, - keyparser): - config_stub.val.input.ambiguous_timeout = 100 - - # 'a' is an ambiguous result. - handle_text((Qt.Key_A, 'a')) - assert not keyparser.execute.called - assert keyparser._ambiguous_timer.isActive() - # We wait for the timeout to occur. - with qtbot.waitSignal(keyparser.keystring_updated): - pass - assert keyparser.execute.called - class TestCount: