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 and language servers 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# Language server
 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 s   Find symbol in current file
 25g S   Find symbol in entire project
 26
 27g ]   Go to next diagnostic
 28g [   Go to previous diagnostic
 29g h   Show inline error (hover)
 30g .   Open the code actions menu
 31
 32# Treesitter
 33] x   Select a smaller syntax node
 34[ x   Select a larger syntax node
 35
 36# Multi cursor
 37g l   Add a visual selection for the next copy of the current word
 38g L   The same, but backwards
 39g >   Skip latest word selection, and add next.
 40g <   The same, but backwards
 41g a   Add a visual selection for every copy of the current word
 42
 43# Pane management
 44g <space>  Open the current search excerpt
 45<ctrl-w> <space>  Open the current search excerpt in a split
 46<ctrl-w> g d      Go to definition in a split
 47<ctrl-w> g D      Go to type definition in a split
 48
 49# Insert mode
 50ctrl-x ctrl-o  Open the completion menu
 51ctrl-x ctrl-c  Request GitHub Copilot suggestion (if configured)
 52ctrl-x ctrl-a  Open the inline AI assistant (if configured)
 53ctrl-x ctrl-l  Open the code actions menu
 54ctrl-x ctrl-z  Hides all suggestions
 55
 56# Ex commands
 57:E[xplore]    Open the project panel
 58:C[ollab]     Open the collaboration panel
 59:Ch[at]       Open the chat panel
 60:A[I]         Open the AI panel
 61:No[tif]      Open the notifications panel
 62:fe[edback]   Open the feedback window
 63:cl[ist]      Open the diagnostics window
 64:te[rm]       Open the terminal
 65:Ext[ensions] Open the extensions window
 66```
 67
 68Vim 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.
 69
 70Vim mode emulates visual block mode using Zed's multiple cursor support. This again leads to some differences, but is much more powerful.
 71
 72Finally, 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.
 73
 74## Custom key bindings
 75
 76You can edit your personal key bindings with `:keymap`.
 77For vim-specific shortcuts, you may find the following template a good place to start:
 78
 79```json
 80[
 81  {
 82    "context": "Editor && (vim_mode == normal || vim_mode == visual) && !VimWaiting && !menu",
 83    "bindings": {
 84      // put key-bindings here if you want them to work in normal & visual mode
 85    }
 86  },
 87  {
 88    "context": "Editor && vim_mode == normal && !VimWaiting && !menu",
 89    "bindings": {
 90      // put key-bindings here if you want them to work only in normal mode
 91      // "down": ["workspace::SendKeystrokes", "4 j"]
 92      // "up": ["workspace::SendKeystrokes", "4 k"]
 93    }
 94  },
 95  {
 96    "context": "Editor && vim_mode == visual && !VimWaiting && !menu",
 97    "bindings": {
 98      // visual, visual line & visual block modes
 99    }
100  },
101  {
102    "context": "Editor && vim_mode == insert && !menu",
103    "bindings": {
104      // put key-bindings here if you want them to work in insert mode
105      // e.g.
106      // "j j": "vim::NormalBefore" // remap jj in insert mode to escape.
107    }
108  }
109]
110```
111
112If you would like to emulate vim's `map` (`nmap` etc.) commands you can bind to the [`workspace::SendKeystrokes`](/docs/key-bindings#remapping-keys) action in the correct context.
113
114You 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).
115
116The 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.
117
118### Examples
119
120Binding `jk` to exit insert mode and go to normal mode:
121
122```
123{
124  "context": "Editor && vim_mode == insert && !menu",
125  "bindings": {
126    "j k": ["vim::SwitchMode", "Normal"]
127  }
128}
129```
130
131## Command palette
132
133Vim 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.
134
135Additionally 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.
136
137We 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.
138
139As mentioned above, one thing to be aware of is that the regex engine is slightly different from vim's in `:%s/a/b`.
140
141Currently supported vim-specific commands:
142
143```
144# window management
145:w[rite][!], :wq[!], :q[uit][!], :wa[ll][!], :wqa[ll][!], :qa[ll][!], :[e]x[it][!], :up[date]
146    to save/close tab(s) and pane(s) (no filename is supported yet)
147:cq
148    to quit completely.
149:vs[plit], :sp[lit]
150    to split vertically/horizontally (no filename is supported yet)
151:new, :vne[w]
152    to create a new file in a new pane above or to the left
153:tabedit, :tabnew
154    to create a new file in a new tab.
155:tabn[ext], :tabp[rev]
156    to go to previous/next tabs
157:tabc[lose]
158    to close the current tab
159
160# navigating diagnostics
161:cn[ext], :cp[rev], :ln[ext], :lp[rev]
162    to go to the next/prev diagnostics
163:cc, :ll
164    to open the errors page
165
166# jump to position
167:<number>
168    to jump to a line number
169:$
170    to jump to the end of the file
171:/foo and :?foo
172    to jump to next/prev line matching foo
173
174# replacement (/g is always assumed and Zed uses different regex syntax to vim)
175:%s/foo/bar/
176  to replace instances of foo with bar
177:X,Ys/foo/bar/
178    to limit replcaement between line X and Y
179    other ranges are not yet implemented
180
181# editing
182:j[oin]
183    to join the current line (no range is yet supported)
184:d[elete][l][p]
185    to delete the current line (no range is yet supported)
186:s[ort] [i]
187    to sort the current selection (with i, case-insensitively)
188```
189
190As any Zed command is available, you may find that it's helpful to remember mnemonics that run the correct command. For example:
191
192```
193:cpp  [C]o[p]y [P]ath to file
194:crp  [C]opy [r]elative [P]ath
195:reveal [Reveal] in finder
196:zlog Open [Z]ed Log
197```
198
199## Settings
200
201Some vim settings are available to modify the default vim behavior:
202
203```json
204{
205  "vim": {
206    // "always": use system clipboard
207    // "never": don't use system clipboard
208    // "on_yank": use system clipboard for yank operations
209    "use_system_clipboard": "always",
210    // Lets `f` and `t` motions extend across multiple lines
211    "use_multiline_find": true
212  }
213}
214```
215
216There are also a few Zed settings that you may also enjoy if you use vim mode:
217
218```json
219{
220  // disable cursor blink
221  "cursor_blink": false,
222  // use relative line numbers
223  "relative_line_numbers": true,
224  // hide the scroll bar
225  "scrollbar": { "show": "never" },
226  // allow cursor to reach edges of screen
227  "vertical_scroll_margin": 0,
228  "gutter": {
229    // disable line numbers completely:
230    "line_numbers": false
231  }
232}
233```
234
235If you want to navigate between the editor and docks (terminal, project panel, AI assistant, ...) just like you navigate between splits you can use the following key bindings:
236
237```json
238{
239  "context": "Dock",
240  "bindings": {
241    "ctrl-w h": ["workspace::ActivatePaneInDirection", "Left"],
242    "ctrl-w l": ["workspace::ActivatePaneInDirection", "Right"],
243    "ctrl-w k": ["workspace::ActivatePaneInDirection", "Up"],
244    "ctrl-w j": ["workspace::ActivatePaneInDirection", "Down"]
245    // ... or other keybindings
246  }
247}
248```
249
250Subword motion is not enabled by default. To enable it, add these bindings to your keymap.
251
252```json
253  {
254    "context": "Editor && VimControl && !VimWaiting && !menu",
255    "bindings": {
256      "w": "vim::NextSubwordStart",
257      "b": "vim::PreviousSubwordStart",
258      "e": "vim::NextSubwordEnd",
259      "g e": "vim::PreviousSubwordEnd"
260    }
261  },
262```
263
264## Supported plugins
265
266Zed has nascent support for some Vim plugins:
267
268- From `vim-surround`, `ys`, `cs` and `ds` work. Though you cannot add new HTML tags yet.
269- From `vim-commentary`, `gc` in visual mode and `gcc` in normal mode. Though you cannot operate on arbitrary objects yet.
270- From `netrw`, most keybindings are supported in the project panel.
271- From `vim-spider`/`CamelCaseMotion` you can use subword motions as described above.
272
273## Regex differences
274
275Zed uses a different regular expression engine from Vim. This means that you will have to use a different syntax for some things.
276
277Notably:
278
279- Vim uses `\(` and `\)` to represent capture groups, in Zed these are `(` and `)`.
280- On the flip side, `(` and `)` represent literal parentheses, but in Zed these must be escaped to `\(` and `\)`.
281- When replacing, Vim uses `\0` to represent the entire match, in Zed this is `$0`, same for numbered capture groups `\1` -> `$1`.
282- Vim uses `/g` to indicate "all matches on one line", in Zed this is implied
283- 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`.
284
285To 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".
286
287For the full syntax supported by Zed's regex engine see the [regex crate documentation](https://docs.rs/regex/latest/regex/#syntax).