diff options
author | Florian Bruhin <me@the-compiler.org> | 2021-03-20 11:10:30 +0100 |
---|---|---|
committer | Florian Bruhin <me@the-compiler.org> | 2021-03-20 11:17:38 +0100 |
commit | 10c3eb0bef09139fba770b6a24374d629d6d9b04 (patch) | |
tree | 97a7e2632e8a45410d41a4dbbf23c1fa814bdb0a | |
parent | c6028d763ee2266e3fd7d88d821726d09d264d27 (diff) | |
download | qutebrowser-10c3eb0bef09139fba770b6a24374d629d6d9b04.tar.gz qutebrowser-10c3eb0bef09139fba770b6a24374d629d6d9b04.zip |
Fix bindings.key_mappings with multiple keys
Otherwise, when e.g. doing "<Meta+Up>": "gg" in bindings.key_mappings,
there's a crash like:
Traceback (most recent call last):
File "/usr/lib/python3.9/site-packages/qutebrowser/keyinput/eventfilter.py", line 105, in eventFilter
return handler(typing.cast(QKeyEvent, event))
File "/usr/lib/python3.9/site-packages/qutebrowser/keyinput/eventfilter.py", line 75, in _handle_key_event
return man.handle_event(event)
File "/usr/lib/python3.9/site-packages/qutebrowser/keyinput/modeman.py", line 462, in handle_event
return handler(cast(QKeyEvent, event))
File "/usr/lib/python3.9/site-packages/qutebrowser/keyinput/modeman.py", line 283, in _handle_keypress
match = parser.handle(event, dry_run=dry_run)
File "/usr/lib/python3.9/site-packages/qutebrowser/keyinput/modeparsers.py", line 105, in handle
match = super().handle(e, dry_run=dry_run)
File "/usr/lib/python3.9/site-packages/qutebrowser/keyinput/basekeyparser.py", line 309, in handle
result = self._match_key_mapping(result.sequence)
File "/usr/lib/python3.9/site-packages/qutebrowser/keyinput/basekeyparser.py", line 246, in _match_key_mapping
mapped = sequence.with_mappings(
File "/usr/lib/python3.9/site-packages/qutebrowser/keyinput/keyutils.py", line 675, in with_mappings
assert len(new_seq) == 1
AssertionError
While this isn't the intended way to use this setting, we shouldn't
crash - and let's just make it work instead of forbidding it.
(cherry picked from commit 5b6d2c60b46e233d4788a9b34d15fdb7d8d1c114)
-rw-r--r-- | qutebrowser/keyinput/keyutils.py | 7 | ||||
-rw-r--r-- | tests/unit/keyinput/test_keyutils.py | 19 |
2 files changed, 15 insertions, 11 deletions
diff --git a/qutebrowser/keyinput/keyutils.py b/qutebrowser/keyinput/keyutils.py index 01a07d6a0..ddf818708 100644 --- a/qutebrowser/keyinput/keyutils.py +++ b/qutebrowser/keyinput/keyutils.py @@ -648,10 +648,9 @@ class KeySequence: for key in self._iter_keys(): key_seq = KeySequence(key) if key_seq in mappings: - new_seq = mappings[key_seq] - assert len(new_seq) == 1 - key = new_seq[0].to_int() - keys.append(key) + keys += [info.to_int() for info in mappings[key_seq]] + else: + keys.append(key) return self.__class__(*keys) @classmethod diff --git a/tests/unit/keyinput/test_keyutils.py b/tests/unit/keyinput/test_keyutils.py index 8ab2ab147..195518127 100644 --- a/tests/unit/keyinput/test_keyutils.py +++ b/tests/unit/keyinput/test_keyutils.py @@ -482,13 +482,18 @@ class TestKeySequence: Qt.Key_A | Qt.ControlModifier) assert seq.strip_modifiers() == expected - def test_with_mappings(self): - seq = keyutils.KeySequence.parse('foobar') - mappings = { - keyutils.KeySequence.parse('b'): keyutils.KeySequence.parse('t') - } - seq2 = seq.with_mappings(mappings) - assert seq2 == keyutils.KeySequence.parse('footar') + @pytest.mark.parametrize('inp, mappings, expected', [ + ('foobar', {'b': 't'}, 'footar'), + ('foo<Ctrl+x>bar', {'<Ctrl+x>': '<Ctrl+y>'}, 'foo<Ctrl+y>bar'), + ('foobar', {'b': 'sa'}, 'foosaar'), + ]) + def test_with_mappings(self, inp, mappings, expected): + seq = keyutils.KeySequence.parse(inp) + seq2 = seq.with_mappings({ + keyutils.KeySequence.parse(k): keyutils.KeySequence.parse(v) + for k, v in mappings.items() + }) + assert seq2 == keyutils.KeySequence.parse(expected) @pytest.mark.parametrize('keystr, expected', [ ('<Ctrl-Alt-y>', |