Currently if multiple matching shortcut handlers are found (after filtering) only one handler is called (the one that was defined last). This is implemented by this logic of key processor:
In other words currently the bindings (after filtering) are always exclusive.
There are some limitations with this approach:
Sometimes, it is beneficial to execute two actions on the same keystroke press (but allow user to override one without affecting the other).
Sometimes defining a filter to handle all edge cases is too difficult as it does not have an access to current state (application nor event), but the handler can get both as it gets the event as an argument
Would it be in scope to have a new option for bindings that allows the handler to be called even if another binding matches? This could have public interface similar to eager option, for example:
@bindings.add('a', exclusive=False) # default would be `exclusive=True`
def binding_2(event):
...
and the logic could be adapted to:
# Exact matches found, call handler.
if not is_prefix_of_longer_match and matches:
exclusive_matches = [match for match in matches if match.exclusive]
non_exclusive_matches = [match for match in matches if not match.exclusive]
# fire only one exclusive match (this guarantees backward-compatibility)
if exclusive_matches:
self._call_handler(exclusive_matches[-1], key_sequence=buffer[:])
# call all non-exclusive matches (regardless of the exclusive matches)
for match in non_exclusive_matches:
self._call_handler(match, key_sequence=buffer[:])
The proposed logic does not stop after the exclusive match is found as stopping there would still lead to the problem that motivates this proposal: newly added handler would suppress a built-in handler. This suggests that a different name could be more appropriate, for example unconditional=True.
Currently if multiple matching shortcut handlers are found (after filtering) only one handler is called (the one that was defined last). This is implemented by this logic of key processor:
https://github.com/prompt-toolkit/python-prompt-toolkit/blob/07412a37b38dd70a3d63f2966a21f0a645133264/src/prompt_toolkit/key_binding/key_processor.py#L185-L187
In other words currently the bindings (after filtering) are always exclusive.
There are some limitations with this approach:
Would it be in scope to have a new option for bindings that allows the handler to be called even if another binding matches? This could have public interface similar to
eager
option, for example:and the logic could be adapted to:
The proposed logic does not stop after the exclusive match is found as stopping there would still lead to the problem that motivates this proposal: newly added handler would suppress a built-in handler. This suggests that a different name could be more appropriate, for example
unconditional=True
.For context, here is the downstream issue: https://github.com/ipython/ipython/issues/14070 and workaround: https://github.com/ipython/ipython/pull/14080