configuring_zed__configuring_vim.md

  1# Vim Mode
  2
  3Zed includes a vim emulation layer known as “vim mode”. This document aims to describe how it works, and how to make the most out of it.
  4
  5## Philosophy
  6
  7Vim mode in Zed is supposed to primarily "do what you expect": it mostly tries to copy vim exactly, but will use Zed-specific functionality when available to make things smoother.
  8
  9This means Zed will never be 100% vim compatible, but should be 100% vim familiar! We expect that our vim mode already copes with 90% of your workflow, and we'd like to keep improving it. If you find things that you can’t yet do in vim mode, but which you rely on in your current workflow, please leave feedback in the editor itself (`:feedback`), or [file an issue](https://github.com/zed-industries/zed/issues).
 10
 11## Zed-specific features
 12
 13Zed is built on a modern foundation that (among other things) uses tree-sitter to understand the content of the file you're editing, and supports multiple cursors out of the box.
 14
 15Vim mode has several "core Zed" key bindings, that will help you make the most of Zed's specific feature set.
 16
 17```
 18# Normal mode
 19g d   Go to definition
 20g D   Go to type definition
 21c d   Rename (change definition)
 22g A   Go to All references to the current word
 23
 24g <space>  Open the current search excerpt in its own tab
 25
 26g s   Find symbol in current file
 27g S   Find symbol in entire project
 28
 29g n   Add a visual selection for the next copy of the current word
 30g N   The same, but backwards
 31g >   Skip latest word selection, and add next.
 32g <   The same, but backwards
 33g a   Add a visual selection for every copy of the current word
 34
 35g h   Show inline error (hover)
 36
 37# Insert mode
 38ctrl-x ctrl-o  Open the completion menu
 39ctrl-x ctrl-c  Request GitHub Copilot suggestion (if configured)
 40ctrl-x ctrl-a  Open the inline AI assistant (if configured)
 41ctrl-x ctrl-l  Open the LSP code actions
 42ctrl-x ctrl-z  Hides all suggestions
 43```
 44
 45Vim mode uses Zed to define concepts like "brackets" (for the `%` key) and "words" (for motions like `w` and `e`). This does lead to some differences, but they are mostly positive. For example `%` considers `|` to be a bracket in languages like Rust; and `w` considers `$` to be a word-character in languages like Javascript.
 46
 47Vim mode emulates visual block mode using Zed's multiple cursor support. This again leads to some differences, but is much more powerful.
 48
 49Finally, Vim mode's search and replace functionality is backed by Zed's. This means that the pattern syntax is slightly different, see the section on [Regex differences](#regex-differences) for details.
 50
 51## Custom key bindings
 52
 53Zed does not yet have an equivalent to vim’s `map` command to convert one set of keystrokes into another, however you can bind any sequence of keys to fire any Action documented in the [Key bindings documentation](https://zed.dev/docs/key-bindings).
 54
 55You can edit your personal key bindings with `:keymap`.
 56For vim-specific shortcuts, you may find the following template a good place to start:
 57
 58```json
 59[
 60  {
 61    "context": "Editor && VimControl && !VimWaiting && !menu",
 62    "bindings": {
 63      // put key-bindings here if you want them to work in normal & visual mode
 64    }
 65  },
 66  {
 67    "context": "Editor && vim_mode == normal && !VimWaiting && !menu",
 68    "bindings": {
 69      // put key-bindings here if you want them to work only in normal mode
 70    }
 71  },
 72  {
 73    "context": "Editor && vim_mode == visual && !VimWaiting && !menu",
 74    "bindings": {
 75      // visual, visual line & visual block modes
 76    }
 77  },
 78  {
 79    "context": "Editor && vim_mode == insert && !menu",
 80    "bindings": {
 81      // put key-bindings here if you want them to work in insert mode
 82    }
 83  }
 84]
 85```
 86
 87You can see the bindings that are enabled by default in vim mode [here](https://zed.dev/ref/vim.json).
 88
 89The 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.
 90
 91### Examples
 92
 93Binding `jk` to exit insert mode and go to normal mode:
 94
 95```
 96{
 97  "context": "Editor && vim_mode == insert && !menu",
 98  "bindings": {
 99    "j k": ["vim::SwitchMode", "Normal"]
100  }
101}
102```
103
104## Subword motion
105
106Subword motion is not enabled by default. To enable it, add these bindings to your keymap.
107
108```json
109  {
110    "context": "Editor && VimControl && !VimWaiting && !menu",
111    "bindings": {
112      "w": "vim::NextSubwordStart",
113      "b": "vim::PreviousSubwordStart",
114      "e": "vim::NextSubwordEnd",
115      "g e": "vim::PreviousSubwordEnd"
116    }
117  },
118```
119
120## Command palette
121
122Vim mode allows you to enable Zed’s command palette with `:`. This means that you can use vim's command palette to run any action that Zed supports.
123
124Additionally vim mode contains a number of aliases for popular vim commands to ensure that muscle memory works. For example `:w<enter>` will save the file.
125
126We do not (yet) emulate the full power of vim’s command line, in particular we special case specific patterns instead of using vim's range selection syntax, and we do not support arguments to commands yet. Please reach out on [GitHub](https://github.com/zed-industries/zed) as you find things that are missing from the command palette.
127
128As mentioned above, one thing to be aware of is that the regex engine is slightly different from vim's in `:%s/a/b`.
129
130Currently supported vim-specific commands (as of Zed 0.106):
131
132```
133# window management
134:w[rite][!], :wq[!], :q[uit][!], :wa[ll][!], :wqa[ll][!], :qa[ll][!], :[e]x[it][!], :up[date]
135    to save/close tab(s) and pane(s) (no filename is supported yet)
136:cq
137    to quit completely.
138:vs[plit], :sp[lit]
139    to split vertically/horizontally (no filename is supported yet)
140:new, :vne[w]
141    to create a new file in a new pane above or to the left
142:tabedit, :tabnew
143    to create a new file in a new tab.
144:tabn[ext], :tabp[rev]
145    to go to previous/next tabs
146:tabc[lose]
147    to close the current tab
148
149# navigating diagnostics
150:cn[ext], :cp[rev], :ln[ext], :lp[rev]
151    to go to the next/prev diagnostics
152:cc, :ll
153    to open the errors page
154
155# jump to position
156:<number>
157    to jump to a line number
158:$
159    to jump to the end of the file
160:/foo and :?foo
161    to jump to next/prev line matching foo
162
163# replacement
164:%s/foo/bar/
165    to replace instances of foo with bar (/g is always assumed, the range must always be %, and Zed uses different regex syntax to vim)
166
167# editing
168:j[oin]
169    to join the current line (no range is yet supported)
170:d[elete][l][p]
171    to delete the current line (no range is yet supported)
172:s[ort] [i]
173    to sort the current selection (with i, case-insensitively)
174```
175
176## Vim settings
177
178Some vim settings are available to modify the default vim behavior:
179
180```json
181{
182  "vim": {
183    // "always": use system clipboard
184    // "never": don't use system clipboard
185    // "on_yank": use system clipboard for yank operations
186    "use_system_clipboard": "always",
187    // Enable multi-line find for `f` and `t` motions
188    "use_multiline_find": false,
189    // Enable smartcase find for `f` and `t` motions
190    "use_smartcase_find": false
191  }
192}
193```
194
195## Related settings
196
197There are a few Zed settings that you may also enjoy if you use vim mode:
198
199```json
200{
201  // disable cursor blink
202  "cursor_blink": false,
203  // use relative line numbers
204  "relative_line_numbers": true,
205  // hide the scroll bar
206  "scrollbar": { "show": "never" }
207}
208```
209
210## Regex differences
211
212Zed uses a different regular expression engine from Vim. This means that you will have to use a different syntax for some things.
213
214Notably:
215
216- Vim uses `\(` and `\)` to represent capture groups, in Zed these are `(` and `)`.
217- On the flip side, `(` and `)` represent literal parentheses, but in Zed these must be escaped to `\(` and `\)`.
218- When replacing, Vim uses `\0` to represent the entire match, in Zed this is `$0`, same for numbered capture groups `\1` -> `$1`.
219- Vim uses `\<` and `\>` to represent word boundaries, in Zed these are both handled by `\b`
220- Vim uses `/g` to indicate "all matches on one line", in Zed this is implied
221- Vim uses `/i` to indicate "case-insensitive", in Zed you can either use `(?i)` at the start of the pattern or toggle case-sensitivity with `cmd-option-c`.
222
223To help with the transition, the command palette will fix parentheses and replace groups for you when you run `:%s//`. So `%s:/\(a\)(b)/\1/` will be converted into a search for "(a)\(b\)" and a replacement of "$1".
224
225For the full syntax supported by Zed's regex engine see the [regex crate documentation](https://docs.rs/regex/latest/regex/#syntax).