Merge BaseKeyParser._handle_key into .handle

This commit is contained in:
Florian Bruhin 2018-02-27 14:07:20 +01:00
parent 3a79f1293f
commit b85fe8f678
3 changed files with 78 additions and 101 deletions

View File

@ -88,69 +88,6 @@ class BaseKeyParser(QObject):
if self.do_log:
log.keyboard.debug(message)
def _handle_key(self, e):
"""Handle a new keypress.
Separate the keypress into count/command, then check if it matches
any possible command, and either run the command, ignore it, or
display an error.
Args:
e: the KeyPressEvent from Qt.
Return:
A QKeySequence match or None.
"""
key = e.key()
txt = keyutils.keyevent_to_string(e)
self._debug_log("Got key: 0x{:x} / text: '{}'".format(key, txt))
if not txt:
self._debug_log("Ignoring, no text char")
return QKeySequence.NoMatch
# if len(txt) == 1:
# category = unicodedata.category(txt)
# is_control_char = (category == 'Cc')
# else:
# is_control_char = False
# if (not txt) or is_control_char:
# self._debug_log("Ignoring, no text char")
# return QKeySequence.NoMatch
if (txt.isdigit() and self._supports_count and not
(not self._count and txt == '0')):
assert len(txt) == 1, txt
self._count += txt
return None
sequence = self._sequence.append_event(e)
match, binding = self._match_key(sequence)
if match == QKeySequence.NoMatch:
mappings = config.val.bindings.key_mappings
mapped = mappings.get(sequence, None)
if mapped is not None:
match, binding = self._match_key(mapped)
self._sequence = self._sequence.append_event(e)
if match == QKeySequence.ExactMatch:
self._debug_log("Definitive match for '{}'.".format(
self._sequence))
count = int(self._count) if self._count else None
self.clear_keystring()
self.execute(binding, count)
elif match == QKeySequence.PartialMatch:
self._debug_log("No match for '{}' (added {})".format(
self._sequence, txt))
elif match == QKeySequence.NoMatch:
self._debug_log("Giving up with '{}', no matches".format(
self._sequence))
self.clear_keystring()
else:
raise utils.Unreachable("Invalid match value {!r}".format(match))
return match
def _match_key(self, sequence):
"""Try to match a given keystring with any bound keychain.
@ -175,21 +112,70 @@ class BaseKeyParser(QObject):
return (QKeySequence.NoMatch, None)
def handle(self, e):
"""Handle a new keypress and call the respective handlers.
"""Handle a new keypress.
Separate the keypress into count/command, then check if it matches
any possible command, and either run the command, ignore it, or
display an error.
Args:
e: the KeyPressEvent from Qt
e: the KeyPressEvent from Qt.
Return:
True if the event was handled, False otherwise.
A QKeySequence match.
"""
match = self._handle_key(e)
key = e.key()
txt = keyutils.keyevent_to_string(e)
self._debug_log("Got key: 0x{:x} / text: '{}'".format(key, txt))
# don't emit twice if the keystring was cleared in self.clear_keystring
if self._sequence:
if not txt:
self._debug_log("Ignoring, no text char")
return QKeySequence.NoMatch
# if len(txt) == 1:
# category = unicodedata.category(txt)
# is_control_char = (category == 'Cc')
# else:
# is_control_char = False
# if (not txt) or is_control_char:
# self._debug_log("Ignoring, no text char")
# return QKeySequence.NoMatch
if (txt.isdigit() and self._supports_count and not
(not self._count and txt == '0')):
assert len(txt) == 1, txt
self._count += txt
return QKeySequence.ExactMatch
sequence = self._sequence.append_event(e)
match, binding = self._match_key(sequence)
if match == QKeySequence.NoMatch:
mappings = config.val.bindings.key_mappings
mapped = mappings.get(sequence, None)
if mapped is not None:
match, binding = self._match_key(mapped)
self._sequence = self._sequence.append_event(e)
if match == QKeySequence.ExactMatch:
self._debug_log("Definitive match for '{}'.".format(
self._sequence))
count = int(self._count) if self._count else None
self.clear_keystring()
self.execute(binding, count)
elif match == QKeySequence.PartialMatch:
self._debug_log("No match for '{}' (added {})".format(
self._sequence, txt))
self.keystring_updated.emit(self._count + str(self._sequence))
elif match == QKeySequence.NoMatch:
self._debug_log("Giving up with '{}', no matches".format(
self._sequence))
self.clear_keystring()
else:
raise utils.Unreachable("Invalid match value {!r}".format(match))
return match != QKeySequence.NoMatch
return match
@config.change_filter('bindings')
def _on_config_changed(self):

View File

@ -157,7 +157,7 @@ class ModeManager(QObject):
if curmode != usertypes.KeyMode.insert:
log.modes.debug("got keypress in mode {} - delegating to "
"{}".format(curmode, utils.qualname(parser)))
handled = parser.handle(event)
match = parser.handle(event)
is_non_alnum = (
event.modifiers() not in [Qt.NoModifier, Qt.ShiftModifier] or
@ -165,7 +165,7 @@ class ModeManager(QObject):
forward_unbound_keys = config.val.input.forward_unbound_keys
if handled:
if match:
filter_this = True
elif (parser.passthrough or forward_unbound_keys == 'all' or
(forward_unbound_keys == 'auto' and is_non_alnum)):
@ -178,10 +178,10 @@ class ModeManager(QObject):
if curmode != usertypes.KeyMode.insert:
focus_widget = QApplication.instance().focusWidget()
log.modes.debug("handled: {}, forward_unbound_keys: {}, "
log.modes.debug("match: {}, forward_unbound_keys: {}, "
"passthrough: {}, is_non_alnum: {} --> "
"filter: {} (focused: {!r})".format(
handled, forward_unbound_keys,
match, forward_unbound_keys,
parser.passthrough, is_non_alnum, filter_this,
focus_widget))
return filter_this

View File

@ -153,8 +153,8 @@ class HintKeyParser(keyparser.CommandKeyParser):
self._read_config('hint')
self.keystring_updated.connect(self.on_keystring_updated)
def _handle_special_key(self, e):
"""Override _handle_special_key to handle string filtering.
def _handle_filter_key(self, e):
"""Handle keys for string filtering.
Return True if the keypress has been handled, and False if not.
@ -162,10 +162,8 @@ class HintKeyParser(keyparser.CommandKeyParser):
e: the KeyPressEvent from Qt.
Return:
True if event has been handled, False otherwise.
A QKeySequence match.
"""
# FIXME rewrite this
# FIXME should backspacing be a more generic hint feature?
log.keyboard.debug("Got special key 0x{:x} text {}".format(
e.key(), e.text()))
hintmanager = objreg.get('hintmanager', scope='tab',
@ -178,7 +176,7 @@ class HintKeyParser(keyparser.CommandKeyParser):
if self._last_press == LastPress.filtertext and self._filtertext:
self._filtertext = self._filtertext[:-1]
hintmanager.filter_hints(self._filtertext)
return True
return QKeySequence.ExactMatch
elif self._last_press == LastPress.keystring and self._sequence:
self._sequence = self._sequence[:-1]
self.keystring_updated.emit(str(self._sequence))
@ -187,18 +185,18 @@ class HintKeyParser(keyparser.CommandKeyParser):
# in numeric mode after the number has been deleted).
hintmanager.filter_hints(self._filtertext)
self._last_press = LastPress.filtertext
return True
return QKeySequence.ExactMatch
else:
return False
return QKeySequence.NoMatch
elif hintmanager.current_mode() != 'number':
return False
return QKeySequence.NoMatch
elif not e.text():
return False
return QKeySequence.NoMatch
else:
self._filtertext += e.text()
hintmanager.filter_hints(self._filtertext)
self._last_press = LastPress.filtertext
return True
return QKeySequence.ExactMatch
def handle(self, e):
"""Handle a new keypress and call the respective handlers.
@ -209,25 +207,18 @@ class HintKeyParser(keyparser.CommandKeyParser):
Returns:
True if the match has been handled, False otherwise.
"""
# FIXME rewrite this
match = self._handle_key(e)
match = super().handle(e)
if match == QKeySequence.PartialMatch:
# FIXME do we need to check self._sequence here?
self.keystring_updated.emit(str(self._sequence))
self._last_press = LastPress.keystring
return True
elif match == QKeySequence.ExactMatch:
self._last_press = LastPress.none
return True
elif match is None: # FIXME
return None
elif match == QKeySequence.NoMatch:
# We couldn't find a keychain so we check if it's a special key.
return self._handle_special_key(e)
return self._handle_filter_key(e)
else:
raise ValueError("Got invalid match type {}!".format(match))
return match != QKeySequence.NoMatch
return match
def update_bindings(self, strings, preserve_filter=False):
"""Update bindings when the hint strings changed.
@ -285,15 +276,16 @@ class RegisterKeyParser(keyparser.CommandKeyParser):
Return:
True if event has been handled, False otherwise.
"""
# FIXME rewrite this
if super().handle(e):
return True
match = super().handle(e)
if match:
return match
key = e.text()
if key == '' or keyutils.keyevent_to_string(e) is None:
# this is not a proper register key, let it pass and keep going
return False
# FIXME can we simplify this when we refactor keyutils.py?
return QKeySequence.NoMatch
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=self._win_id)
@ -315,5 +307,4 @@ class RegisterKeyParser(keyparser.CommandKeyParser):
message.error(str(err), stack=traceback.format_exc())
self.request_leave.emit(self._mode, "valid register key", True)
return True
return QKeySequence.ExactMatch