parent
a7b6d179d4
commit
b88ac51d25
@ -147,10 +147,18 @@ class BaseKeyParser(QObject):
|
||||
return QKeySequence.NoMatch
|
||||
|
||||
# First, try a straightforward match
|
||||
self._debug_log("Trying simple match")
|
||||
match, binding = self._match_key(sequence)
|
||||
|
||||
# Then try without optional modifiers
|
||||
if match == QKeySequence.NoMatch:
|
||||
self._debug_log("Trying match without modifiers")
|
||||
sequence = sequence.strip_modifiers()
|
||||
match, binding = self._match_key(sequence)
|
||||
|
||||
# If that doesn't match, try a key_mapping
|
||||
if match == QKeySequence.NoMatch:
|
||||
self._debug_log("Trying match with key_mappings")
|
||||
mapped = sequence.with_mappings(config.val.bindings.key_mappings)
|
||||
if sequence != mapped:
|
||||
self._debug_log("Mapped {} -> {}".format(
|
||||
@ -159,10 +167,12 @@ class BaseKeyParser(QObject):
|
||||
sequence = mapped
|
||||
|
||||
# If that doesn't match either, try treating it as count.
|
||||
txt = str(sequence[-1]) # To account for sequences changed above.
|
||||
if (match == QKeySequence.NoMatch and
|
||||
txt.isdigit() and
|
||||
self._supports_count and
|
||||
not (not self._count and txt == '0')):
|
||||
self._debug_log("Trying match as count")
|
||||
assert len(txt) == 1, txt
|
||||
if not dry_run:
|
||||
self._count += txt
|
||||
|
@ -510,6 +510,12 @@ class KeySequence:
|
||||
|
||||
return self.__class__(*keys)
|
||||
|
||||
def strip_modifiers(self):
|
||||
"""Strip optional modifiers from keys."""
|
||||
modifiers = Qt.KeypadModifier
|
||||
keys = [key & ~modifiers for key in self._iter_keys()]
|
||||
return self.__class__(*keys)
|
||||
|
||||
def with_mappings(self, mappings):
|
||||
"""Get a new KeySequence with the given mappings applied."""
|
||||
keys = []
|
||||
|
@ -198,13 +198,34 @@ class TestHandle:
|
||||
keyparser.execute.assert_called_with('message-info ba', None)
|
||||
assert not keyparser._sequence
|
||||
|
||||
@pytest.mark.parametrize('key, number', [(Qt.Key_0, 0), (Qt.Key_1, 1)])
|
||||
def test_number_press(self, handle_text, keyparser, key, number):
|
||||
handle_text(key)
|
||||
@pytest.mark.parametrize('key, modifiers, number', [
|
||||
(Qt.Key_0, Qt.NoModifier, 0),
|
||||
(Qt.Key_1, Qt.NoModifier, 1),
|
||||
(Qt.Key_1, Qt.KeypadModifier, 1),
|
||||
])
|
||||
def test_number_press(self, fake_keyevent, keyparser,
|
||||
key, modifiers, number):
|
||||
keyparser.handle(fake_keyevent(key, modifiers))
|
||||
command = 'message-info {}'.format(number)
|
||||
keyparser.execute.assert_called_once_with(command, None)
|
||||
assert not keyparser._sequence
|
||||
|
||||
@pytest.mark.parametrize('modifiers, text', [
|
||||
(Qt.NoModifier, '2'),
|
||||
(Qt.KeypadModifier, 'num-2'),
|
||||
])
|
||||
def test_number_press_keypad(self, fake_keyevent, keyparser, config_stub,
|
||||
modifiers, text):
|
||||
"""Make sure a <Num+2> binding overrides the 2 binding."""
|
||||
config_stub.val.bindings.commands = {'normal': {
|
||||
'2': 'message-info 2',
|
||||
'<Num+2>': 'message-info num-2'}}
|
||||
keyparser._read_config('normal')
|
||||
keyparser.handle(fake_keyevent(Qt.Key_2, modifiers))
|
||||
command = 'message-info {}'.format(text)
|
||||
keyparser.execute.assert_called_once_with(command, None)
|
||||
assert not keyparser._sequence
|
||||
|
||||
def test_umlauts(self, handle_text, keyparser, config_stub):
|
||||
config_stub.val.bindings.commands = {'normal': {'ü': 'message-info ü'}}
|
||||
keyparser._read_config('normal')
|
||||
@ -215,6 +236,15 @@ class TestHandle:
|
||||
handle_text(Qt.Key_X)
|
||||
keyparser.execute.assert_called_once_with('message-info a', None)
|
||||
|
||||
def test_mapping_keypad(self, config_stub, fake_keyevent, keyparser):
|
||||
"""Make sure falling back to non-numpad keys works with mappings."""
|
||||
config_stub.val.bindings.commands = {'normal': {'a': 'nop'}}
|
||||
config_stub.val.bindings.key_mappings = {'1': 'a'}
|
||||
keyparser._read_config('normal')
|
||||
|
||||
keyparser.handle(fake_keyevent(Qt.Key_1, Qt.KeypadModifier))
|
||||
keyparser.execute.assert_called_once_with('nop', None)
|
||||
|
||||
def test_binding_and_mapping(self, config_stub, handle_text, keyparser):
|
||||
"""with a conflicting binding/mapping, the binding should win."""
|
||||
handle_text(Qt.Key_B)
|
||||
@ -296,6 +326,15 @@ class TestCount:
|
||||
assert sig1.args == ('4',)
|
||||
assert sig2.args == ('42',)
|
||||
|
||||
def test_numpad(self, fake_keyevent, keyparser):
|
||||
"""Make sure we can enter a count via numpad."""
|
||||
for key, modifiers in [(Qt.Key_4, Qt.KeypadModifier),
|
||||
(Qt.Key_2, Qt.KeypadModifier),
|
||||
(Qt.Key_B, Qt.NoModifier),
|
||||
(Qt.Key_A, Qt.NoModifier)]:
|
||||
keyparser.handle(fake_keyevent(key, modifiers))
|
||||
keyparser.execute.assert_called_once_with('message-info ba', 42)
|
||||
|
||||
|
||||
def test_clear_keystring(qtbot, keyparser):
|
||||
"""Test that the keystring is cleared and the signal is emitted."""
|
||||
|
@ -377,6 +377,15 @@ class TestKeySequence:
|
||||
with pytest.raises(keyutils.KeyParseError):
|
||||
seq.append_event(event)
|
||||
|
||||
def test_strip_modifiers(self):
|
||||
seq = keyutils.KeySequence(Qt.Key_0,
|
||||
Qt.Key_1 | Qt.KeypadModifier,
|
||||
Qt.Key_A | Qt.ControlModifier)
|
||||
expected = keyutils.KeySequence(Qt.Key_0,
|
||||
Qt.Key_1,
|
||||
Qt.Key_A | Qt.ControlModifier)
|
||||
assert seq.strip_modifiers() == expected
|
||||
|
||||
def test_with_mappings(self):
|
||||
seq = keyutils.KeySequence.parse('foobar')
|
||||
mappings = {keyutils.KeySequence('b'): keyutils.KeySequence('t')}
|
||||
|
Loading…
Reference in New Issue
Block a user