Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for long keybindings #705

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

jcjgraf
Copy link
Contributor

@jcjgraf jcjgraf commented Aug 23, 2023

This PR adds support for keybindings of arbitrary-length key sequences. Longer key sequences were actually almost supported, but due two bugs (probably you just never really thought about them) prevented their (proper) working.

How to test

Adds support for bindings like :bind abc log info success. Without this PR, such a binding does not work

Changes

Two things prevented the working of such a binding and required adoption:

Eventhandler only considered current and previous keystroke but forgot about older ones

Problem

gui.eventhandler.EventHandlerMixin._process_event() is called for each keystroke. That function calls self.partial_handler.keys.get_keys(), which in turn calls self._keys.clear(). On a partial match, self.partial_handler.keys.add_keys(*sequence) is run.

This means that for each new keypress the keys from the keystore are retrieved and the store is wiped. On a partial match, sequence, which is only the last pressed key, is added to the store again. This means, that only one key is stored in the keystore at the time.

Fix

I fixed that issue by removing self._keys.clear() in TempKeyStorage.keys.get_keys(). I really do not see why this call should be required. If however it is, the issue could also be fixed by adding not only sequence, but actually the full sequence (all previously pressed keys) to the keystore.

Keyhint shows wrong "already typed keys" (aka. prefix)

The keyhint always displays the most recently pressed key as the prefix and not the whole sequence of pressed keys.

Problem

In gui.eventhandler.EventHandlerMixin._process_event() on a partial match, the signal partial_matches is emitted. As argument name is passed. However, name is based solely on sequence, which is the currently pressed key` and not the whole sequence of pressed keys.

Solution

Pass all keys retrieved from the keystore as the first argument to the signal.

Keybindings of more than 2 chars were not possible, as the
`TempKeyStorage` was cleaned on every access to `get_keys`. `get_keys`
is invoked by every call of `_process_event`. Removing the call to
`clean` in `get_keys` leaves the code correct, as the keystore is
actively cleaned when no binding matches or on a timeout.
The keyhint always shows the last pressed key, instead of all previously
pressed keys. The reason was that for signal `partial_matches` only the
last pressed key was passed, instead of the full sequence.
@jcjgraf jcjgraf marked this pull request as ready for review August 23, 2023 10:43
@karlch
Copy link
Owner

karlch commented Aug 23, 2023

Seems reasonable to me, I will take some more time thinking why it cleared previously, especially as there was a dedicated test case, but I think everything is good as-is. Just need a bit more time to review and think 😊

@karlch
Copy link
Owner

karlch commented Mar 18, 2024

It's been a while, but I finally did some more testing and playing around, and to me this seems superior to the current behaviour in every way. So if you give me a quick thumbs up, happy to merge 😊

@jcjgraf
Copy link
Contributor Author

jcjgraf commented Mar 18, 2024

I am glad that you like it. It still looks good to me 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants