-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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 a sticky mode for keymaps #635
Conversation
I think(?) I was the one that originally suggested sticky modes. But I'm not totally sure that's actually what we want in the long term to solve this kind of thing. Still great for the time being, though! I'll write up an RFC at some point about the other approach I've been thinking about. |
@cessen Ah yeah you mentioned them in the multi key remap PR :) One problem I noticed with having a sticky mode (for debug mode specifically) is that movement keys will not be usable while in sticky mode. What is the other approach you were thinking of (as a quick summary) ? |
I don't think it's worth doing quite yet, because it would be a bigger change, and I'd like to get consensus before anyone codes it up (hence wanting to write up an RFC). But the short version is: Users can create custom modes, which essentially are just named keymaps. Each mode can be of either a "normal" type or "insert" type, which determines what unmapped keys do: in normal-type they do nothing, in insert-type they insert text. And with this system, the standard built-in normal and insert modes would also just be internally-defined "custom" modes. The desire for a new debug mode actually makes this seem even more useful than I was initially thinking. Initially I was just thinking of it as being part of letting the user customize how Helix works, but it seems core Helix will also want to define additional modes. |
) => { | ||
keymap!({ $label $($($key)|+ => $value,)+ }) | ||
keymap!({ $label $(sticky=$sticky)? $($($key)|+ => $value,)+ }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we turn this into keymap!(sticky; { })
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I see, it needs to be per submap. I was thinking we could use a better format there too, maybe
"g" => (STICKY "Goto" {
// keys..
})
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried something to that effect in the first pass but couldn't figure out how to do it. This is what I have right now:
(
{ $label:literal $(sticky=$sticky:literal)? $($($key:literal)|+ => $value:tt,)+ }
) => {
// ...
let mut _node = $crate::keymap::KeyTrieNode::new($label, _map, _order);
$( _node.is_sticky = $sticky; )?
$crate::keymap::KeyTrie::Node(_node)
}
Here $sticky
is just a boolean literal so this works all okay. Is there any way to set is_sticky
to true if the STICKY
token is present in the macro input ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could either split it into two branches, or have one branch call the other one. I'm also fine with just duplicating the branches.
i.e., you could call the non-sticky branch, then set node.0.is_sticky = true
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think duplicating the rules is a good idea since it'll make the macro even longer and force the duplication of new rules if we add them in the future. Also the gains from all that duplication doesn't seem very large in terms of readability or maintainability.
I still think it might be useful to just overlay the sticky mode over the toplevel. That's what |
Yeah, for example the view mode becomes a lot more useful if you're able to start it in sticky mode ( |
(Sidenote: I found an analogy in emacs, it's called hydra: https://github.com/abo-abo/hydra) |
Hydra is supplanted by Transient, a more powerful and flexible technology invented for Magit. Transient is now built in to Emacs 28. Another cool example of what can be done with it is Sharper, a dotnet compiler frontend for Emacs. Hydra is still used for the cool debugging interface of dap-mode, though! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's get this merged so it can be used for DAP 👍🏻
Regression due to helix-editor#635 where escape key in insert mode would not exit normal mode. This happened due to hard coding the escape key to cancel a sticky keymap node.
Regression due to #635 where escape key in insert mode would not exit normal mode. This happened due to hard coding the escape key to cancel a sticky keymap node.
Adds an option to turn keymap nodes sticky, which will temporarily make the sticky node the base keymap. Subsequent keys will be looked up from this sticky keymap node for commands to be executed. Pressing
Escape
will exit out of this sticky mode.Usage with the
keymap!
macro:Use case includes keybindings for debug mode (#574), sticky view mode, etc.