-
Notifications
You must be signed in to change notification settings - Fork 3.1k
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
Fix bugs occurring in complex multistroke keybindings #14445
Fix bugs occurring in complex multistroke keybindings #14445
Conversation
We require contributors to sign our Contributor License Agreement, and we don't have @haruleekim on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'. |
@cla-bot check |
The cla-bot has been summoned, and re-checked this pull request! |
|
@ConradIrwin Hi, this PR has passed all tests and addresses issues with complex multistroke keybindings. Could you please review it when you have a moment? If you think further improvements are needed, I am willing to dedicate additional time to ensure a complete solution. |
Hey @haruleekim! Thanks for submitting this. I think your fix is good, but I want to explore a bigger change of this system - there are a couple of other bugs and the code has become a bit messy. if I can’t get that over the line before the next preview I will merge this |
Simplify key dispatch code. Previously we would maintain a cache of key matchers for each context that would store the pending input. For the last while we've also stored the typed prefix on the window. This is redundant, we only need one copy, so now it's just stored on the window, which lets us avoid the boilerplate of keeping all the matchers in sync. This stops us from losing multikey bindings when the context on a node changes (#11009) (though we still interrupt multikey bindings if the focus changes). While in the code, I fixed up a few other things with multi-key bindings that were causing problems: Previously we assumed that all multi-key bindings took precedence over any single-key binding, now this is done such that if a user binds a single-key binding, it will take precedence over all system-defined multi-key bindings (irrespective of the depth in the context tree). This was a common cause of confusion for new users trying to bind to `cmd-k` or `ctrl-w` in vim mode (#13543). Previously after a pending multi-key keystroke failed to match, we would drop the prefix if it was an input event. Now we correctly replay it (#14725). Release Notes: - Fixed multi-key shortcuts not working across completion menu changes ([#11009](#11009)) - Fixed multi-key shortcuts discarding earlier input ([#14445](#14445)) - vim: Fixed `jk` binding preventing you from repeating `j` ([#14725](#14725)) - vim: Fixed `escape` in normal mode to also clear the selected register. - Fixed key maps so user-defined mappings take precedence over builtin multi-key mappings ([#13543](#13543)) - Fixed a bug where overridden shortcuts would still show in the Command Palette
I think #14942 fixed this and others. I incorporated your tests verbatim - thank you! |
Simplify key dispatch code. Previously we would maintain a cache of key matchers for each context that would store the pending input. For the last while we've also stored the typed prefix on the window. This is redundant, we only need one copy, so now it's just stored on the window, which lets us avoid the boilerplate of keeping all the matchers in sync. This stops us from losing multikey bindings when the context on a node changes (zed-industries#11009) (though we still interrupt multikey bindings if the focus changes). While in the code, I fixed up a few other things with multi-key bindings that were causing problems: Previously we assumed that all multi-key bindings took precedence over any single-key binding, now this is done such that if a user binds a single-key binding, it will take precedence over all system-defined multi-key bindings (irrespective of the depth in the context tree). This was a common cause of confusion for new users trying to bind to `cmd-k` or `ctrl-w` in vim mode (zed-industries#13543). Previously after a pending multi-key keystroke failed to match, we would drop the prefix if it was an input event. Now we correctly replay it (zed-industries#14725). Release Notes: - Fixed multi-key shortcuts not working across completion menu changes ([zed-industries#11009](zed-industries#11009)) - Fixed multi-key shortcuts discarding earlier input ([zed-industries#14445](zed-industries#14445)) - vim: Fixed `jk` binding preventing you from repeating `j` ([zed-industries#14725](zed-industries#14725)) - vim: Fixed `escape` in normal mode to also clear the selected register. - Fixed key maps so user-defined mappings take precedence over builtin multi-key mappings ([zed-industries#13543](zed-industries#13543)) - Fixed a bug where overridden shortcuts would still show in the Command Palette
Simplify key dispatch code. Previously we would maintain a cache of key matchers for each context that would store the pending input. For the last while we've also stored the typed prefix on the window. This is redundant, we only need one copy, so now it's just stored on the window, which lets us avoid the boilerplate of keeping all the matchers in sync. This stops us from losing multikey bindings when the context on a node changes (zed-industries#11009) (though we still interrupt multikey bindings if the focus changes). While in the code, I fixed up a few other things with multi-key bindings that were causing problems: Previously we assumed that all multi-key bindings took precedence over any single-key binding, now this is done such that if a user binds a single-key binding, it will take precedence over all system-defined multi-key bindings (irrespective of the depth in the context tree). This was a common cause of confusion for new users trying to bind to `cmd-k` or `ctrl-w` in vim mode (zed-industries#13543). Previously after a pending multi-key keystroke failed to match, we would drop the prefix if it was an input event. Now we correctly replay it (zed-industries#14725). Release Notes: - Fixed multi-key shortcuts not working across completion menu changes ([zed-industries#11009](zed-industries#11009)) - Fixed multi-key shortcuts discarding earlier input ([zed-industries#14445](zed-industries#14445)) - vim: Fixed `jk` binding preventing you from repeating `j` ([zed-industries#14725](zed-industries#14725)) - vim: Fixed `escape` in normal mode to also clear the selected register. - Fixed key maps so user-defined mappings take precedence over builtin multi-key mappings ([zed-industries#13543](zed-industries#13543)) - Fixed a bug where overridden shortcuts would still show in the Command Palette
Release Notes:
There is a bug in
gpui
when handling multiple multistroke key bindings.When strokes that could invoke different key bindings are adjacent, they do not behave as users typically expect.
For example, with Zed in vim mode and the following key bindings set through
workspace::SendKeystrokes
:If you type
dodog
, instead of gettingdo🐶
, you only get🐶
. This means the keystrokes that failed to invoke a keybinding are completely ignored.Additionally, if you type
docat
in the same setup, the expected result isdo🐱
, but what you actually get isdoca🐱
.Another example:
With Zed set up like this, if you type
pin
and wait for 1 second or typepineapple
without pausing, you get the expected 📌 and 🍍 emojis, respectively. However, if you typepine
without pausing and then wait for 1 second, you get 📌 instead of 🌲.Although I used Vim mode and emojis to illustrate the problem, this issue is not specific to Vim mode or Unicode emojis. The problem arises because
gpui
fails to properly handle the interactions between multiple multistroke key bindings.There are two issues:
gpui
ignores some keystrokes (part of the pending input) that failed to be replaced by an action. The correct behavior is to slice these keystrokes and add them toreplay_pending_input
.This pull request aims to fix the first issue and enforces sorting by the reverse order of keystroke lengths for the second issue.
I did not implement sorting by the hierarchy of the dispatch tree yet, as it requires further consideration.
Although this fix addresses a bug in
gpui
unrelated to Vim, I wasn't sure how to properly test keystrokes withingpui
, so I wrote the tests in thevim
crate.The
vim
crate will also need these tests anyway.