-
-
Notifications
You must be signed in to change notification settings - Fork 154
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
Binding modes/binding submaps #846
Comments
xmonad's approach for subkeys is interesting which I used in many ways. for example I use it to bring up the gridSelect module ...
^++^ subKeys
"Grid Select (Super-g followed by a key)"
[ ("M1-g g", addName "grid select some bookmarks" $ spawnSelected' myBookmarkGrid),
... |
In my opinion instead of binding modes we should allow bindings to have multiple keys (like in @mastoca's example). This is more intuitive and matches other existing software (e.g. vim/neovim, vscode, zed, emacs, ghostty). They are both identical in functionally since they just represent a state machine, but multikey syntax lets bindings be local which is good for managing and sharing configs, and hands off the task of building the state machine to niri. I've started working on this, I've done the parsing and the syntax works really nicely by (ab)using arguments:
Code let keys =
iter::once(node.node_name.parse::<Key>().map_err(|e| {
DecodeError::conversion(&node.node_name, e.wrap_err("invalid keybind"))
}))
.chain(node.arguments.iter().map(|val| {
match &*val.literal {
knuffel::ast::Literal::String(s) => Ok(s),
_ => Err(DecodeError::unexpected(
&val.literal,
"argument type",
"expected argument to be a string",
)),
}?
.parse::<Key>()
.map_err(|e| {
DecodeError::conversion(&node.node_name, e.wrap_err("invalid keybind"))
})
}))
.collect::<Result<Vec<Key>, DecodeError<_>>>()?; This requires reworking bindings to a state machine, I've currently going with a naive approach of storing the index of the "active key" for each bind incrementing it when a key matches (going from longest to shortest sequence to allow bindings that end with the entire sequence of keys of another bind) and resetting all the indices once a bind is triggered, we can switch to a trie if this turns out to be a performance issue. I'm not sure what should happen when an unrelated key is pressed while a multikey binding is ongoing, should it:
We also need to think about how this interacts with release binds. Edit: I thought about it a bit more and this doesn't allow expressing modal bindings very well, you can simulate an insert mode with |
Hmm. What I don't like about this approach is that it's infectious in a way: you put one multi-key bind somewhere in your config (and forget about it), and suddenly pressing the first key just stops doing anything, or starts working with a big latency (the timeout). On the other hand, binding modes are much more explicit about this. You can also be explicit about the unrelated keys, since probably in different cases it makes sense to do different things about them. |
The ability to configure multiple binding modes with separate binds.
An example use-case is a "launcher" mode, where e.g. you press Super+D, then instead of the normal binds, you have binds to run applications, like F for firefox, N for nautilus, T for terminal, etc. So you press Super+D+F to run firefox.
There's a WIP implementation for binding modes: #532. The author's GitHub account had disappeared, but I remember about the PR and will get to it at some point.
The text was updated successfully, but these errors were encountered: