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