vim: (BREAKING) clean up keymap contexts (#14233)
Release Notes: - vim: (BREAKING) Improved vim keymap contexts. Previously `vim_mode == normal` was true even when operators were pending, which led to bugs like #13789 and a requirement for custom keymaps to exclude various conditions like (`!VimObject` and `!VimWaiting`) to avoid bugs. Now `vim_mode` will be set to `operator` or `waiting` in these cases as described in [the docs](https://zed.dev/docs/vim#keybindings). For most custom keymaps this change will be a no-op or an improvement, but if you were deliberately relying on the old behaviour (if you were relying on `VimObject` or `VimWaiting` becoming true) you will need to update your keymap. --------- Co-authored-by: Thorsten <thorsten@zed.dev>
This commit is contained in:
+15
-35
@@ -85,36 +85,22 @@ Finally, Vim mode's search and replace functionality is backed by Zed's. This me
|
||||
## Custom key bindings
|
||||
|
||||
You can edit your personal key bindings with `:keymap`.
|
||||
For vim-specific shortcuts, you may find the following template a good place to start:
|
||||
For vim-specific shortcuts, you may find the following template a good place to start.
|
||||
|
||||
> **Note:** We made some breaking changes in Zed version `0.145.0`. For older versions, see [the previous version of this document](https://github.com/zed-industries/zed/blob/c67aeaa9c58619a58708722ac7d7a78c75c29336/docs/src/vim.md#L90).
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"context": "Editor && (vim_mode == normal || vim_mode == visual) && !VimWaiting && !menu",
|
||||
"context": "VimControl && !menu",
|
||||
"bindings": {
|
||||
// put key-bindings here if you want them to work in normal & visual mode
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Editor && vim_mode == normal && !VimWaiting && !menu",
|
||||
"context": "vim_mode == insert",
|
||||
"bindings": {
|
||||
// put key-bindings here if you want them to work only in normal mode
|
||||
// "down": ["workspace::SendKeystrokes", "4 j"]
|
||||
// "up": ["workspace::SendKeystrokes", "4 k"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Editor && vim_mode == visual && !VimWaiting && !menu",
|
||||
"bindings": {
|
||||
// visual, visual line & visual block modes
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Editor && vim_mode == insert && !menu",
|
||||
"bindings": {
|
||||
// put key-bindings here if you want them to work in insert mode
|
||||
// e.g.
|
||||
// "j j": "vim::NormalBefore" // remap jj in insert mode to escape.
|
||||
// "j k": "vim::NormalBefore" // remap jk in insert mode to escape.
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -122,7 +108,6 @@ For vim-specific shortcuts, you may find the following template a good place to
|
||||
"bindings": {
|
||||
// put key-bindings here (in addition to above) if you want them to
|
||||
// work when no editor exists
|
||||
// e.g.
|
||||
// "space f": "file_finder::Toggle"
|
||||
}
|
||||
}
|
||||
@@ -133,20 +118,15 @@ If you would like to emulate vim's `map` (`nmap` etc.) commands you can bind to
|
||||
|
||||
You can see the bindings that are enabled by default in vim mode [here](https://github.com/zed-industries/zed/blob/main/assets/keymaps/vim.json).
|
||||
|
||||
The details of the context are a little out of scope for this doc, but suffice to say that `menu` is true when a menu is open (e.g. the completions menu), `VimWaiting` is true after you type `f` or `t` when we’re waiting for a new key (and you probably don’t want bindings to happen). Please reach out on [GitHub](https://github.com/zed-industries/zed) if you want help making a key bindings work.
|
||||
#### Contexts
|
||||
|
||||
### Examples
|
||||
Zed's keyboard bindings are evaluated only when the `"context"` matches the location you are in on the screen. Locations are nested, so when you're editing you're in the `"Workspace"` location is at the top, containing a `"Pane"` which contains an `"Editor"`. Contexts are matched only on one level at a time. So it is possible to combine `Editor && vim_mode == normal`, but `Workspace && vim_mode == normal` will never match because we set the vim context at the `Editor` level.
|
||||
|
||||
Binding `jk` to exit insert mode and go to normal mode:
|
||||
Vim mode adds several contexts to the `Editor`:
|
||||
|
||||
```
|
||||
{
|
||||
"context": "Editor && vim_mode == insert && !menu",
|
||||
"bindings": {
|
||||
"j k": ["vim::SwitchMode", "Normal"]
|
||||
}
|
||||
}
|
||||
```
|
||||
* `vim_mode` is similar to, but not identical to, the current mode. It starts as one of `normal`, `visual`, `insert` or `replace` (depending on your mode). If you are mid-way through typing a sequence, `vim_mode` will be either `waiting` if it's waiting for an arbitrary key (for example after typing `f` or `t`), or `operator` if it's waiting for another binding to trigger (for example after typing `c` or `d`).
|
||||
* `vim_operator` is set to `none` unless `vim_mode == operator` in which case it is set to the current operator's default keybinding (for example after typing `d`, `vim_operator == d`).
|
||||
* `"VimControl"` indicates that vim keybindings should work. It is currently an alias for `vim_mode == normal || vim_mode == visual || vim_mode == operator`, but the definition may change over time.
|
||||
|
||||
### Restoring some sense of normality
|
||||
|
||||
@@ -155,7 +135,7 @@ that you can't live without. You can restore them to their defaults by copying t
|
||||
|
||||
```
|
||||
{
|
||||
"context": "Editor && !VimWaiting && !menu",
|
||||
"context": "Editor && !menu",
|
||||
"bindings": {
|
||||
"ctrl-c": "editor::Copy", // vim default: return to normal mode
|
||||
"ctrl-x": "editor::Cut", // vim default: increment
|
||||
@@ -304,7 +284,7 @@ Subword motion is not enabled by default. To enable it, add these bindings to yo
|
||||
|
||||
```json
|
||||
{
|
||||
"context": "Editor && VimControl && !VimWaiting && !menu",
|
||||
"context": "VimControl && !menu",
|
||||
"bindings": {
|
||||
"w": "vim::NextSubwordStart",
|
||||
"b": "vim::PreviousSubwordStart",
|
||||
@@ -318,7 +298,7 @@ Surrounding the selection in visual mode is also not enabled by default (`shift-
|
||||
|
||||
```json
|
||||
{
|
||||
"context": "Editor && vim_mode == visual && !VimWaiting && !VimObject",
|
||||
"context": "vim_mode == visual",
|
||||
"bindings": {
|
||||
"shift-s": [
|
||||
"vim::PushOperator",
|
||||
|
||||
Reference in New Issue
Block a user