└── README.md
/README.md:
--------------------------------------------------------------------------------
1 | # iBhagwan's (n)vim cheatsheet
2 |
3 | \*\*This cheatsheet was inspired by [Hackjutsu's Vim cheatsheet](https://github.com/hackjutsu/vim-cheatsheet) and Laurent Gregoire's excellent [Vim Quick Reference Card](http://tnerual.eriogerg.free.fr/vimqrc.html).
4 |
5 | I've been using vi for over 20 years but always limited it's use for basically only editing \*nix system config files, recently I (re-)discovered (n)vim as the magical editor that it is and decided to make it my main editor for coding, writing markdown and the likes so down the rabbit hole I went. The more I researched the more I fell in love with the software, the below is the accumulation of all my notes and findings.
6 |
7 | The cheatsheet assumes at least minimal understanding of motions and operators, to better understand motions, operators and how it all comes together in what is referred to as "the vim language" I highly recommend reading [Jim Denis's stackoverflow answer: Your problem with Vim is that you don't grok vi](https://gist.github.com/nifl/1178878).
8 |
9 | Note that everything below works with vanilla vim/nvim and does not require the use of any plugins. I am not opposed to plugins and even use a few which I find extremely helpful but as a philosophy I try to use as much built-in functionality (with minimal keymap changes) as I can before turning to plugins. As you can see below there is **so much** you can do with vanilla Vim that I decided to leave plugins out of the scope of this document. If you'd like to take a look at my custom mappings and plugins, refer to my nvim lua configuration at [nvim-lua](https://github.com/ibhagwan/nvim-lua).
10 |
11 | If you'd like to take your Vim to the next level, I highly recommend watching all of [Drew Neil's VimCasts](http://vimcasts.org/episodes/page/8/) they are absolutely wonderful and will blow your mind. When you're ready to jump in the water and test your skills [Vimgolf](http://www.vimgolf.com) is fantastic exercise which will cement all your Vim knowledge and add new tricks to your arsenal. Download [Vimgolf client from here](https://github.com/igrigorik/vimgolf) or it's [lesser known python client by Daniel Stein](https://github.com/dstein64/vimgolf) if you wish to avoid the ruby dependencies.
12 |
13 | **Thanks to [/u/-romainl-](https://www.reddit.com/user/-romainl-/) for [his great feedback](https://www.reddit.com/r/vim/comments/gha79v/i_wrote_an_advanced_comprehensive_cheatsheet_for/fq7qeop?utm_source=share&utm_medium=web2x) correcting previous inaccuracies.**
14 |
15 |
16 | ### Table of contents:
17 |
18 | - [Saving & Exiting Vim](#saving-exiting-vim)
19 | - [Navigation](#navigation)
20 | + [Movement](#movement)
21 | + [Scrolling](#scrolling)
22 | - [Editing](#Editing)
23 | + [Insert & Exit](#insert-exit)
24 | + [Undo & Repeat](#undo-repeat)
25 | + [Basic Editing](#basic-editing)
26 | + [INSERT mode](#insert-mode)
27 | + [Cut, copy & paste](#cut-copy-and-paste)
28 | - [VISUAL mode](#visual-mode)
29 | + [Selections](#selections)
30 | + [Operators](#operators)
31 | - [Text Objects](#text-objects)
32 | - [Search & Replace](#search-replace)
33 | + [REGEX Examples](#regex-examples)
34 | + [Multiple Files](#multiple-files)
35 | - [Macros](#macros)
36 | + [Recursive Macros](#recursive-macros)
37 | - [Marks](#marks)
38 | - [Files and Windows](#files-and-windows)
39 | - [Tabs](#tabs)
40 | - [Terminal](#term)
41 | - [Spellcheck](#spellcheck)
42 | - [Misc Commands](#misc-commands)
43 | - [Ctrl-R and the Expression Register](#ctrl-r-and-the-expression-register)
44 | - [Comparing buffers with vimdiff](#comparing-buffers-with-vimdiff)
45 | - [Folding](#folding)
46 |
47 | ## Saving & Exiting Vim
48 | ```vim
49 | :w " write the current file
50 | :w {file} " write to {file}
51 | :wq {file} " write to {file} and quit
52 | :saveas {file} " write to {file}
53 | :update {file} " write only if buffer was modified
54 | :w !sudo tee % " write the current file using sudo
55 | :wq :x ZZ " write the current file and quit
56 | :q " quit (fails if there are unsaved changes)
57 | :q! ZQ " quit and throw away unsaved changes
58 | :cq " quit Vim with exit code
59 | ```
60 |
61 | **NOTE:** the `:cq` command is useful in situations when we need to exit-cancel, for example when running `v` in bash shell `set -o vi`, when exiting using `:cq` the command won't be executed automatically. Another example is when exiting the output window of `git rebase`, `:cq` will cancel the rebase operation.
62 |
63 | ## Navigation
64 | ### Movement
65 | ```vim
66 | k " up
67 | h l " left, right
68 | j " down
69 | ```
70 | ```vim
71 | + - " first non-blank char line above, below
72 | H M L " [H]igh, [M]iddle, [L]ow line of the window
73 | {n}H {n}L " line {n} from the top, bottom of the window
74 | b w " beginning of word left, right (punctuation considered words)
75 | B W " beginning of WORD left, right (spaces separate words)
76 | e ge " end of word left, right (punctuation considered words)
77 | E gE " end of WORD left, right (spaces separate words)
78 | 0 g0 " start of the line, visual-line
79 | ^ g^ " first non-blank character of the line, visual-line
80 | $ g$ " last character of the line, visual-line (include )
81 | _ g_ " first, last non-blank character of the line (not including )
82 | {n}_ " down {n-1} lines on first non-blank character
83 | gm " middle of the line
84 | {n}gg {n}G " goto line {n}, default first, last line of buffer
85 | :{n} " goto line {n}, (ex mode)
86 | {n}% " jump to buf % (e.g. 50% jump to middle of buffer)
87 | {n}| " jump to screen column {n} of current line
88 | f{c} F{c} " next, previous occurrence of character {c}
89 | t{c} T{c} " before ([t]ill) next, previous occurrence of {c}
90 | ; , " repeat last fFtT in the same, opposite direction
91 | ( ) " previous, next sentence (jumps after the next '.' or EOL)
92 | { } " previous, next paragraph (jumps to next empty line)
93 | % " jump to matching parenthesis ([{}])
94 | [[ ]] " backward, forward start section
95 | [] ][ " backward, forward end of section
96 | [( ]) " backward, forward unclosed (, )
97 | [{ ]} " backward, forward unclosed {, }
98 | ```
99 | **Note:** When navigating lines with `hjkl^$`, if a line is too long and is wrapped, pressing `j` will move down to the next line even if the current line is wrapping 2 or more lines, to go down 1 "visual" line use `gj` instead. The `g` prefix works the same for other navigation commands `hjkl^$` (`g^` and `g$` for start and end of visual line). A very useful mapping is to map `` or `jk` to move by visual lines as long as they aren't prefixed with {count} so we can still use up and down motions (e.g. `10j`) for whole lines:
100 |
101 | ```
102 | nnoremap (v:count == 0 ? 'g' : '')
103 | vnoremap (v:count == 0 ? 'g' : '')
104 | nnoremap (v:count == 0 ? 'g' : '')
105 | vnoremap (v:count == 0 ? 'g' : '')
106 | ```
107 |
108 | ### Scrolling
109 | ```vim
110 | zz or z. " center screen on cursor
111 | zb or z- " scroll the screen so the cursor is at the (b)ottom
112 | zt or z " scroll the screen so the cursor is at the (t)op
113 | zh zl " scroll one character to the left, right
114 | zH zL " scroll half screen to the left, right
115 | " move back one full screen
116 | " move forward one full screen
117 | " move forward 1/2 a screen
118 | " move back 1/2 a screen
119 | " scroll the screen up
120 | " scroll the screen down
121 | " jump to previous location in :jumps
122 | " jump to next location in :jumps
123 | `` " jump to last jump location
124 | `. " jump to last edit location
125 | '. " jump to start of line of last edit
126 | g; g, " cycle backwards, forwards in `:changes` (edit locations)
127 | ```
128 |
129 | ## Editing
130 | ### Insert & Exit
131 | ```vim
132 | " exit insert mode
133 | " exit insert mode
134 | i a " insert before, after the cursor
135 | I A " insert at beginning, end of line
136 | gi gI " insert at last insert location, first column
137 | o O " open a new line below, above the current line
138 | R " enter REPLACE mode, cursor overwrites everything
139 | gR " like R but without affecting layout
140 | ```
141 |
142 | ### Undo & Repeat
143 | ```vim
144 | u U " undo last command, restore last changed line
145 | " redo
146 | . " repeat last edit
147 | {n}. " repeat last edit {n} times
148 | ```
149 |
150 | ### Basic Editing
151 | ```vim
152 | x X " delete a single character under, before cursor
153 | {n}x {n}X " repeat x, X {n} times
154 | r{c} " replace character under cursor with {c}
155 | gr{c} " like r, without affecting layout
156 | ~ " switch case a single character
157 | g~{m} " switch case of motion {m} (i.e. `g~iw~` for word)
158 | gu{m} gU{m} " lower, upper case of motion {m}
159 | J gJ " join current line with next, without space
160 | dd D " delete (cut) entire line, to end of line
161 | dw " delete (cut) to the next word
162 | cc C " change (replace) entire line, to end of line
163 | cw " change (replace) to the end of the current word
164 | caw " change (replace) the current word (including spaces)
165 | ciw " change (replace) the current word (not including spaces)
166 | ce " change (replace) forwards to the end of a word
167 | cb " change (replace) backwards to the start of a word
168 | c0 " change (replace) to the start of the line
169 | c$ " change (replace) to the end of the line
170 | c/pattern " change (replace) to first occurrence of 'pattern'
171 | s " delete character and substitute text (equal to `cl`)
172 | S " delete line and substitute text (equal to `cc`)
173 | xp " transpose two letters (delete and paste)
174 | ylxp " transpose two letters (yank, delete and paste)
175 | vyxp " transpose two letters (yank, delete and paste)
176 | >> " indent current line right
177 | << " indent current line left
178 | == " re-indent line (using 'equalprg' if specified)
179 | =% " indent current block of code
180 | gg=G " re-indent entire buffer
181 | " find number in current line and increment by 1
182 | " find number in current line and decrement by 1
183 | {num} " find number in current line and increment by {num}
184 | {count}: " will translate {count} to :{range} in ex mode
185 | ```
186 | **Notes:**
187 | - All (c)hange commands end with the editor in INSERT mode
188 |
189 | - All double-char commands (i.e. `dd`, `cc`, `yy`, etc) can be thought of as a shortcut to `0{operator}$`, the breakdown is as follows:
190 | ```vim
191 | 0 " go to the start of the line
192 | {operator} " {operator} of your choice
193 | $ " go the end of the line
194 | ```
195 |
196 | - The above can also be combined with a {count} prefix, for example 2dd will delete 2 lines below. A similar result could also be achieved using the full expression of the operator and motion: `{operator}{count}{motion}`, i.e. `d1j` will delete 2 lines down (cursor line + 1 down) and `y2w` will yank 2 words forward. In similar fashion the VISUAL mode operator `v` can be used, e.g. `vi}` will visually select everything inside the curly braces.
197 |
198 | ### INSERT mode
199 | ```vim
200 | " delete a word backwards
201 | " undo edit on current line, on empty lines
202 | " shift left one shift width
203 | " put text from the above line column
204 | " put text from the below line column
205 | {reg} " put register {reg}
206 | u " break the (u)ndo chain
207 | {c} " insert char {c} literally
208 | {n} " insert char by decimal value
209 | u{n} " insert unicode char by decimal value
210 | " insert previously inserted text (equal to `.`)
211 | " same as + exit INSERT mode
212 | " auto-complete after cursor
213 | " auto-complete before cursor
214 | {cmd} " execute one NORMAL mode command (see below note)
215 | " like , does not work on all keyboards
216 | ^x^e ^x^y " scroll up, down
217 | ```
218 | **Note:** Any NORMAL mode motion can be run from INSERT mode by using `{op}` or `` (only works on some keyboards). Alternatively, if we're in ex mode we can use `:norm {cmd}`. For example: say we want to append text at the end of the line we can simply press `` or `A` which will take us to the end of the line, all without leaving INSERT mode. The same can be achieved from ex mode with `:norm A`, even though the latter isn't useful for this specific example it can be useful in many other cases where more complex commands are required (e.g. using the `global` command: `:g/regex/norm >>` will indent all lines matching the regex)
219 |
220 | ### Cut, copy and paste
221 | ```vim
222 | p P " (p)ut or (p)aste clipboard after, before cursor
223 | ]p [P " like p, P with indent adjusted
224 | gp gP " like p, P leaving cursor after new text
225 | yy " yank (copy) a line
226 | {n}yy " yank (copy) {n} lines
227 | yl " yank a single character (l = to the right)
228 | vy " yank a single character (using VISUAL mode)
229 | yw " yank (copy) to the next word
230 | yiw " yank (copy) (i)nner word (entire word)
231 | yaw " yank (copy) (a) word (entire word, including spaces
232 | y$ " yank (copy) to end of line
233 | dd " delete (cut) a line
234 | {n}dd " delete (cut) {n} lines
235 | dw " delete (cut) to the next word
236 | D " delete (cut) to the end of the line
237 | d$ " delete (cut) to the end of the line
238 | d^ " delete (cut) to the first non-blank character of the line
239 | d0 " delete (cut) to the beginning of the line
240 | d/pattern " delete (cut) to first occurrence of 'pattern'
241 | x X " delete (cut) character under, before the cursor
242 | "+p " paste the `+` register (the clipboard)
243 | "0p " paste the yank `0` register
244 | "{reg}p " paste {reg} (:registers)
245 | "{reg}yy " yank current line into {reg} (:registers)
246 | "_dd " delete line into the 'blackhole' register (no clipboard)
247 |
248 | ```
249 | **Copy paste using ex mode:**
250 | ```vim
251 | :{range}y " yank {range} into the default register
252 | :{range}m{line} " move {range} below {line}
253 | :{range}co{line} " copy {range} to below {line}
254 | :{range}t{line} " shortcut to the `:co[opy]` command above
255 | :-2co . " copy line 2 above cursor to line below cursor
256 | :+2t 0 " copy line 2 below cursor to start of file
257 | :.,$t $ " copy all lines from the cursor to end of file to end of file
258 | :1,3co 5 " copy lines 1-3 to below line 5
259 | ```
260 |
261 | **Notes:**
262 | - To paste a register directly from INSERT or ex mode use `` followed by a register name.
263 |
264 | - By default the `Y` command is mapped to `yy` (yank line) which isn't consisnt with the behaviors of `C` and `D` (from cursor to end of line), a very useful mapping for both NORMAL and VISUAL mode is:
265 |
266 | ```vim
267 | nnoremap Y y$
268 | xnoremap Y y$gv
269 | ```
270 |
271 | - By default all modification operators `d c x` copy the modified text to the unnamed `"` register (unless `set clipboard` was set) which can be confusing at first. For example, let's say we want to overwrite a word with yanked text, we would naturally do `ciwp` or `ciw"` only to find out the same word would be pasted (and not our yanked text), to work around that we can tell the `c` operator to copy the text into the 'blackhole' register instead: `"_ciw`. Alternatively we can also use the yank register `0` which contains the content of the last yank operation using `"0p` or `"0P` (to paste before the cursor). A few useful mappings for my leader key (by default `\`, personally I use `\`) are below, so if I want to change a word without it polluting my registers I would run `bciw`, similarly if I wish to delete a line I would run `dd`:
272 |
273 | ```vim
274 | nnoremap b "_
275 | nnoremap d "_d
276 | nnoremap D "_D
277 | nnoremap dd "_dd
278 | xnoremap b "_
279 | xnoremap D "_D
280 | xnoremap D "_D
281 | xnoremap x "_x
282 | ```
283 |
284 | - In addition to being copied to the default register (`"` or `*`), every 'deleted' text is also copied into the 'small delete' registers {1-9}. To view the latest deletes run `:reg[isters]` or `:di[splay]`. A neat trick to cycle through the delete registers is to use `"1p` and then run `u.`, the undo+repeat advances the 'pasted register' so it will perform `"2p`, `"3p` and so forth.
285 |
286 | ## VISUAL mode
287 | ### Selections
288 | ```vim
289 | " exit visual mode
290 | " exit visual mode
291 | v " start VISUAL mode in 'character' mode
292 | V " start VISUAL mode in 'line' mode
293 | " start VISUAL mode in 'block' mode
294 | o " move to other end of marked area
295 | O " move to other corner of block
296 | $ " select to end of line (include newline)
297 | g_ " select to end of line (exclude newline)
298 | aw " select a word
299 | ab " select a block with ()
300 | aB " select a block with {}
301 | ib " select inner block with ()
302 | iB " select inner block with {}
303 | gv " NORMAL mode: reselect last visual selection
304 | ```
305 |
306 | **Notes:**
307 | - The above are just some of the available commands as any text object or motion can be used, e.g. `viw` will visually select current word or `vat` will select an entire tag: `some text`
308 |
309 | - A neat trick you can do with VISUAL mode is using visual modes as motion operators, If you perform `d2j`, it will delete all three lines. That’s because `j` is a linewise motion. If you instead pressed `d2j`, it would convert the motion to blockwise and delete just the column characters instead. For more information read [Hillel Wayne's blog: At least one Vim trick you might not know](https://www.hillelwayne.com/post/intermediate-vim/).
310 |
311 | - VISUAL mode has a nice feature to expand selection based on blocks, say we wanted to select the inside of an `if` condition in C, we do so with `vi(` or `vi)`, if we wanted to expand the selection to the outer block we can just run `i{` or `i}` (without having to cancel the selection and press `v` again).
312 |
313 | ### Operators
314 | ```vim
315 | ~ " switch case
316 | d " delete
317 | c " change
318 | y " yank
319 | > " indent right
320 | < " indent left
321 | ! " filter through external command
322 | = " re-indent line (using 'equalprg' if specified)
323 | gq " format lines to 'textwidth' length (cursor moves to end)
324 | gw " format lines to 'textwidth' length (cursor stays in place)
325 | gu " make selection lower-case
326 | gU " make selection UPPER-case
327 | v " increment digit under the cursor
328 | {num} " increment current selection by {num} (lines separately increment)
329 | {num} " decrement current selection by {num} (lines separately decrement)
330 | {num}g " increment current selection by {num} (lines serially increment)
331 | ```
332 |
333 | **Notes:**
334 | - Some operators, namely the repeat `.` and paste `pP` operators have unique behaviors when used after a VISUAL 'block' mode edit, that is extremely useful when editing text as blocks. Say we wanted to append semicolon to the end of a paragraph we could simply do `}A;` we can then repeat the operation using `.` which will replicate the change to the same block range under the cursor. Similarly we can use the paste before and after the cursor `p` and `P` to paste entire columns, the following will duplicate the first column of a paragraph: `}yp` which you can easily undo as an atomic operation with `u`.
335 |
336 | - If you want to preform an {ex} command on visual selection press `:` (with selected visuals), vim will automatically prefix your ex command with the visual range `:'<,'>` so you can execute any command on the selected text, e.g. `:'<,'>norm @q` will execute macro `q` on all visually selected lines.
337 |
338 | - A shortcut to the above can be done with the bang `!` operator, this will automatically put is in ex command mode with the visual selection already entered, the equivalent of `:'<,'>!` ready for entering a command, this is useful in many situations, for example to sort a visual block we can just do `viB!sort` which is the equivalent `viB:!sort`. The same can also be done from NORMAL mode using `!iBsort`.
339 |
340 | - When indenting (or any other operation) in VISUAL mode with `<>` you will find that once indented you lose the current selection, to visually reselect the text you can use `gv`, so to indent while keeping current selection use `gv` respectively. Personally I never want to lose my selection when indenting hence I use the below mappings in [my keymaps](https://github.com/ibhagwan/nvim-lua/blob/main/lua/keymaps.lua):
341 |
342 | ```vim
343 | vmap < >gv
345 | ```
346 | ## Text Objects
347 | ```vim
348 | aw " a word (includes surrounding white space
349 | iw " inner word (does not include surrounding white space)
350 | as " a sentence
351 | is " inner sentence
352 | ap " a paragraph
353 | ip " inner paragraph
354 | a" " a double quoted string
355 | i" " inner double quoted string
356 | a' " a single quoted string
357 | i' " inner single quoted string
358 | a` " a back quoted string
359 | i` " inner back quoted string
360 | a) or ab " a parenthesized block
361 | i) or ib " inner parenthesized block
362 | a] " a bracketed block
363 | i] " inner bracketed block
364 | a} or aB " a brace block
365 | i} or iB " inner brace block
366 | at " a tag block e.g.
367 | it " inner tag block e.g.
368 | a> " a single tag
369 | i> " inner single tag
370 | gn " next occurrence of search pattern
371 | ```
372 | **Notes:**
373 | - Text objects can be used with any operator, e.g. `dit` will delete "some text" from `some text` and `yat` will copy the entire tag into the clipboard. For more information [Jared Caroll's: Vim Text Objects: The Definitive Guide](https://blog.carbonfive.com/vim-text-objects-the-definitive-guide/).
374 |
375 | - `gn` is a very useful text object, few examples: `cgn` will change the next search pattern match, `vgn` will visually select all text from the cursor to the next match. For more information read [Bennet Hardwick's blog: 8 Vim tips and tricks for advanced beginners](https://bennetthardwick.com/blog/2019-01-06-beginner-advanced-vim-tips-and-tricks/).
376 |
377 | - Any text object can also be used with a count. For example, we have the below text (cursor at ^):
378 | ```vim
379 | if (function(param1, param2, param3)) {
380 | ^
381 | ```
382 | If we run `di)` we will delete all 3 parameters. However we can also run `d2i(` to delete inside the parent parenthesis, thus deleting the entire condition and resulting in the text `if () {`. I found this very useful tip (and others) in [Antoyo's blog](https://blog.antoyo.xyz/vim-tips).
383 |
384 | ## Search & Replace
385 | ```vim
386 | # * " search word under cursor backward, forward
387 | g# or g* " like #, * but also find partial matches
388 | /pattern " search for pattern
389 | /pattern " go to next match without exiting search mode `/`
390 | /pattern " go to prev match without exiting search mode `/`
391 | /pattern/{-+n} " put cursor {-+n}th line below/above the match
392 | /pattern/e{-+n} " put cursor {-+n}th char before/after match (e)nd
393 | /pattern/b{-+n} " put cursor {-+n}th char before/after match (b)egin
394 | ?pattern " search backward for pattern
395 | / " repeat search in same direction
396 | ? " repeat search in opposite direction
397 | // " put last search pattern into search mode
398 | / " put word under cursor into search mode
399 | / " put WORD under cursor into search mode
400 | /\v{pattern} " Search forwards using Vim's 'very magic' pattern
401 | " special characters can be used without esc seq
402 | n N " repeat search in same, opposite direction
403 | & or :&& " repeat last substitute in the same line
404 | g& " repeat last substitute on all lines
405 | :noh " remove highlighting of search matches
406 | :s/old/new/ " replace first occurrence of old with new
407 | :s/old/new/i " replace first occurrence of old with new (case insensitive)
408 | :s/old/new/g " replace all old with new throughout line ('globally')
409 | :%s/old/new " replace first occurrence of old with new throughout file
410 | :%s/old/new/g " replace all old with new throughout file ('globally')
411 | :%s/old/new/gc " replace all old with new throughout file with confirmations
412 | :%s/old/'&'/g " surround all occurrences of old with ' (i.e. 'old')
413 | :s/\%Vold/new/ " replace all occurrences of old with new in visual selection
414 | :{range} s/old/new/ " replace all old with in {range} (e.g. `:10,20s/...`)
415 | :{num},$ s/old/new/ " replace all old with new from line {num} to last line
416 | :g/regex/{ex} " run :{ex} for every line matching regex
417 | :g!/regex/{ex} " run :{ex} for every line NOT matching regex
418 | :v/regex/{ex} " same as above, shortcut to `:g!`
419 | :g/regex/y {reg} " copy all matching lines to register {reg}
420 | " capitalize {reg} to append to {reg}
421 | :g/regex/m $ " move all matching lines to end of file
422 | :g/regex/-1j " for every matching line, go up one line and join
423 | :%s/\s\+$//e " remove all trailing whitespaces throughout buffer
424 | :g/^/m0 " reverse order of all lines in current buffer
425 | :v/./d " delete all empty lines (same as `:g!/./d`)
426 | /\%>10l\%<20l{regex} " search for regex between lines 10-20 (excluding ln 20)
427 | /\v%>10l%<20l{regex} " same as above using 'very magic'
428 | /\%u{xxxx} " search for unicode character `u+{xxxx}` (e.g. `u+0061` for `a`)
429 | ```
430 |
431 | **Notes:**
432 |
433 | - You can repeat the last substitute interactively with `g&`
434 |
435 | - For more information on the different `.../g` modifiers read `:help s_flags`
436 |
437 | - For more information on the "very magic" pattern read [Vim fandom: Simplifying regular expressions using magic and no-magic](https://vim.fandom.com/wiki/Simplifying_regular_expressions_using_magic_and_no-magic).
438 |
439 | - The `g` and `v` ex commands are extremely useful, few examples: `:g/pattern/d` or `:g/pattern/norm dd` will delete all lines matching `pattern`, you can also supply a range to the command: `:g/pattern/-1d` will delete one line above all lines matching `pattern`, same can be achieved with `:g/pattern/norm 1jdd`
440 |
441 | - `:y {reg}` copies the range to the register {reg}. If {reg} is a capital letter register, this appends to the existing register, i.e. if we do `let @a = '' | %g/regex/y A` it will copy all lines matching regex in the entire file to register a. We can then copy the register to the system clipboard with `let @+ = @a`.
442 |
443 | - Important note regarding the use of `:s` vs `:g`: `s` is a shortcut for `substitute` and `g` is a shortcut for `global`, therefore `s` should be used when doing search and replace (substitution) and `g` should be used when you'd like to execute a command for every match (not necessarily substitution), each has it's strength and it's a matter of using the right tool for the job. Example: say we wanted to substitute `bar` with `blah` for every line containing `foo`, we could achieve the same result with both but as you can see the `g` command would be a better fit in this case:
444 |
445 | ```vim
446 | g/foo/s/bar/blah/g
447 |
448 | :%s/foo/\=substitute(getline('.'), 'bar','blah','g')
449 | ```
450 |
451 | ### REGEX Examples
452 | ### Search examples
453 | ```vim
454 | /^fred.*joe.*bill " line beginning with fred, followed by joe then bill
455 | /^[A-J] " line beginning A-J
456 | /^[A-J][a-z]\+\s " line beginning A-J then one or more lowercase characters then space or tab
457 | /fred\_.\{-}joe " fred then anything then joe (over multiple lines)
458 | /fred\_s\{-}joe " fred then any whitespace (including newlines) then joe
459 | /fred\|joe " fred OR joe
460 | ```
461 |
462 | ### Substitution examples
463 | ```vim
464 | :%s/fred/joe/igc " general substitute command
465 | :%s/\r//g " delete DOS Carriage Returns (^M)
466 | :'a,'bg/fred/s/dick/joe/gc " VERY USEFUL
467 | :s/\(.*\):\(.*\)/\2 : \1/ " reverse fields separated by :
468 | " non-greedy matching \{-} " `:help /\{-}`
469 | :%s/^.\{-}pdf/new.pdf/ " to first pdf)
470 | :s/fred/a/g " substitute 'fred' with contents of register 'a'
471 | :%s/^\(.*\)\n\1/\1$/ " delete duplicate lines
472 | " running multiple commands
473 | :%s/suck\|buck/loopy/gc " ORing
474 | :s/__date__/\=strftime("%c")/ " insert datestring
475 | :%s/\f\+\.gif\>/\r&\r/g | v/\.gif$/d | %s/gif/jpg/
476 | ```
477 |
478 | ### Multiple Files
479 |
480 | > To learn more I recommend watching
481 | > [Drew Neil: Searching Multiple Files with vimgrep](http://vimcasts.org/episodes/search-multiple-files-with-vimgrep/)
482 |
483 | ```vim
484 | :vimgrep /pattern/ {file} " search for a pattern using vimgrep
485 | :grep /pattern/ {file} " search for a pattern using an external program
486 | :copen " open the 'quickfix` window containing all matches
487 | :cn " jump to the next match
488 | :cp " jump to the previous match
489 | :cdo " execute a command for each quickfix entry
490 | :cfdo " execute a command for each quickfix file
491 | ```
492 |
493 | When just starting to use vim search and replace an entire project at first
494 | seems overly complex, plugins can definitely help here (fzf comes to mind) but
495 | once you understand how to use the quickfix list it's actually quite easy.
496 |
497 | Vim comes builtin with the `vimgrep` utility which searches for a regex patter
498 | and populates the quickfix list accordingly. From there, you can manipulate
499 | matches using the `cdo|cfdo` combo.
500 |
501 | Searching the project is as easy as:
502 | ```vim
503 | " search the current file
504 | :vimgrep /foo/ %
505 | " search the entire project
506 | :vimgrep /foo/ **/*
507 | ```
508 |
509 | Personally I prefer to use `:grep` in conjunction with the
510 | [`rg`](https://github.com/BurntSushi/ripgrep) utility, to do so add the below
511 | to your `init.vim`:
512 | ```vim
513 | set grepprg=rg\ --vimgrep\ --no-heading\ --smart-case\ --hidden
514 | set grepformat=%f:%l:%c:%m
515 | ```
516 |
517 | And then run the same search:
518 | ```vim
519 | " search the current file
520 | :grep 'foo' %
521 | " search the entire project
522 | :grep 'foo'
523 | " or if you prefer to use the location-list
524 | :lgrep 'foo'
525 | ```
526 |
527 | From here it's very easy to search and replace all matches with
528 | [any substitute command](#search-replace):
529 | ```vim
530 | " if you want to run the command once for each entry use `cdo`
531 | " otherwise the below should suffice as `%s` searches the entire file
532 | :cfdo %s/foo/bar/g
533 | " save all changes
534 | :wall
535 | ```
536 |
537 | ## Macros
538 | ```vim
539 | q{a-z} " start recording macro to register {a-z}
540 | q{A-Z} " append recording macro to register {a-z}
541 | q " stop macro recording
542 | @{a-z} " execute macro {a-z}
543 | {count}@{a-z} " execute macro {a-z} on {count} lines
544 | @@ " repeat execution of last macro
545 | :@{reg} " execute {reg} as an ex command
546 | @: " repeat execution of last ex command e.g. `:s/...`
547 | @. " execute last inserted text as macro
548 | @='[cmds]' " execute commands through the expression register
549 | :'<,'>normal @q " execute macro `q` on visual selection
550 | "{a-z}p " paste macro {a-z} (register)
551 | "{a-z}y$ " yank into macro {a-z} to end of line
552 | ```
553 |
554 | **Notes:**
555 | - Macros are essentially just a saved series of keystrokes, if you’re recording a macro and make a mistake, don’t start over, instead, undo it and keep going normally, using macro `q` as an example (recorded with `qq`), once you’re finished with the macro, press `"qp` to paste it to an empty line, remove the mistaken keystrokes and the undo and copy it back into the `q` register with `"qy$`.
556 |
557 | - Don’t leave undos in your macro. If you undo in a macro to correct a mistake, always be sure to manually remove the mistake and the undo from the macro. In replay mode, an undo will undo the entire macro up until that point, erasing all of your hard work and bleeding the macro out into the rest of your text.
558 |
559 | - The above was taken from [Hillel Wayne's blog: Vim Macro Tricks](https://www.hillelwayne.com/vim-macro-trickz/).
560 |
561 | - Alternatively, you can resume recording a macro using the capitalized version of the registers, say we started recording into the `q` register with `qq` we can "pause" the macro recording with `q` and later resume recording with `qQ` (note the capitalized `Q`).
562 |
563 | - Macros are not limited to the current buffer, if you wish to transform text between windows just add a windows switch command to your macro (e.g. `w`). This makes it very useful to mass manipulate text between different buffers.
564 |
565 | - A neat trick to running macros quickly is to use the `.` register which is the last inputed text. Let's say we want to run a macro that does the simple task of transposing two adjacent characters `xp`, what we can do is enter INSERT mode, enter the macro keys, press `u` for undo and then execute the macro with `@.`, thus the entire sequence equals `ixpu` and now we can run our macro with `@.`. Alternatively, if you'd like your macro to contain a `` (down one line) you can run `O~$~dd` and then run the macro with `2@"` (since our text was 'cut' into the default register) - this will toggle capitalization of the first and last character in 2 subsequent lines.
566 |
567 | - Building on the above, the same `xp` macro can be run using the expression register by running `@='xp'` and then repeat the macro execution with `@@`. You can run more complex commands using the full format `{count}@='[commands]'`. For example, running `3@='v2w'` on the text `1 5 8` will increment each digit by 2 resulting in `3 7 10`. This example is equivalent to `qqv2wq2@q`: which records the edit to macro `q` and then executes it two more times. (note: if you wish to input special characters (``, ``, etc.) in the command line, prefix the special character with `` e.g. ``.
568 |
569 |
570 | ### Recursive Macros
571 |
572 | A recursive macro, as the name suggests, is a macro that calls itself, in Vim, the call is usually done at the end of the macro, so a recursive macro will usually end with a call to itself `@q` followed by `q` to stop the macro recording. A simple recursive macro that deletes all vimscript comments in an entire buffer would look like this:
573 | ```vim
574 | qqq " empty the q register, VERY IMPORTANT, read below why
575 | qqf"D+@qq " execute on one line and record our recursive macro
576 | @q " execute until fail
577 | ```
578 |
579 | If you wish to test your macro before executing on the entire buffer you can take advantage of appending to a register using a capitalized register letter, let's re-do our example from above while also testing our macro:
580 | ```vim
581 | qqq " empty the q register, VERY IMPORTANT, read below why
582 | qqf"D+q " execute on one line and record our macro
583 | @q " execute one time and check the results
584 | qQ@qq " execute one more time and add the recursion call
585 | @q " execute until fail
586 | ```
587 |
588 | As you can see from above, recursive macros can be very useful if you wish to run a macro on the entire buffer without having to worry about the number of times required to run the macro, it's similar to running `9999@q` (in a file with less than 9999 lines). Note that this is different than running the ex command `:%norm @q`, in the latter case the macro would run on the entire buffer regardless if there are some lines with errors (e.g. can't find the `"`), this gives us the flexibility to choose between the two approaches, if we want to run until failure we use a recursive macro, if we wish to run on the entire buffer regardless of errors we use the `:%norm @{reg}` or `:0,$norm @{reg}` variant.
589 |
590 | **Note:** It is VERY IMPORTANT to clean the destination register (`q` in our case) by running `q{reg}q` **before we start the recording**, the reason for this is when you're recording the macro for first time you are also running it when you're adding the recursion call `@q`, if our register isn't empty the register commands will be executed and most likely mess up our edit.
591 |
592 | ## Marks
593 | ```vim
594 | :marks " list current marks
595 | m{a-z,A-Z} " set mark at cursor position
596 | " {a-z} = local file marks
597 | " {A=Z} = cross file marks
598 | '{a-z,A-Z} " goto first non-blank character in mark {a-z,A-Z}
599 | `{a-z,A-Z} " goto exact cursor position of mark {a-z,A-Z}
600 | ```
601 |
602 | ## Files and Windows
603 | ```vim
604 | :e {file} " edit a file in a new buffer
605 | :find {file} " find and open file in &path (set path?)
606 | gf " find and open the file under the cursor
607 | gF " find and open the file under the cursor with line number
608 | :cd %:h " change pwd to folder of current buffer (all buffers)
609 | :lcd %:h " change pwd to folder of current buffer (local buffer)
610 | :ls " list all open buffers
611 | :bnext or :bn " go to the next buffer
612 | :bprev or :bp " go to the previous buffer
613 | :bd " delete a buffer (close a file)
614 | :sp {file} " open a file in a new buffer and split window
615 | :vsp {file} " open a file in a new buffer and vertically split window
616 | :windo {ex} " run :{ex} on all windows (e.g. :windo q - quits all windows)
617 | :bufdo {ex} " same as above for buffers
618 | :on " make current window the 'only' window (close all others)
619 | :hide or :q " hide (close) current window
620 | :new " new window in a horizontal split
621 | :vnew " new window in a vertical split
622 | o " same as `:on` above
623 | w " jump to next window
624 | r " swap windows
625 | q " quit a window
626 | s " split window horizontally
627 | v " split window vertically
628 | h " move cursor to the left window (vertical split)
629 | l " move cursor to the right window (vertical split)
630 | j " move cursor to the window below (horizontal split)
631 | k " move cursor to the window above (horizontal split)
632 | " jump to previous buffer
633 | " display filename of current buffer (file)
634 | 1 " display full path of current buffer (file)
635 | 2 " display buf # and full path of current buffer (file)
636 | ```
637 |
638 | **Notes:**
639 | - `:bufdo` and `:windo` can be used for multiple file/window operations, for example to search and replace in all open buffers you can run `:bufdo %s/old/new/g`
640 |
641 | - `:find` and `gf` are both dependent on the `&path` variable which by default contains `.` which is the current working directory (`:pwd`), for said commands to be effective be sure to always open Vim from your project directory or use `cd` to change Vim's working directory (best done using `cd %:h`). If you would like `:find` and `gf` to find files recursively in all folders specified by `&path` be sure `path` contains `**`. Use `:set path+=**` if you wish to add `**` to the current `&path`. Personally, I define my path as: `set path=.,,,$PWD/**` (search current directory and project directory recursively).
642 |
643 |
644 | ## Tabs
645 | ```vim
646 | :tabnew or :tabnew {file} " open a file in a new tab
647 | T " move the current split window into its own tab
648 | gt or :tabnext or :tabn " goto to the next tab
649 | gT or :tabprev or :tabp " goto to the previous tab
650 | {num}gt " goto to tab {num}
651 | :tabmove {num} " move current tab to the {num}th position (indexed from 0)
652 | :tabclose or :tabc " close the current tab and all its windows
653 | :tabonly or :tabo " close all tabs except for the current one
654 | :tabdo {ex} " run :{ex} on all tabs (e.g. :tabdo q - closes all opened tabs)
655 | ```
656 |
657 | ## Terminal
658 | ### Vim:
659 | ```vim
660 | :term " open terminal window inside vim (default shell)
661 | :term zsh " open terminal window inside vim (zsh)
662 | :vert term zsh " opens a new terminal in a horizontal split (zsh)
663 | ```
664 | ### Neovim:
665 | ```vim
666 | :term " open terminal window inside vim
667 | :split term://zsh " opens a new terminal in a horizontal split
668 | :vsplit term://zsh " opens a new terminal in a vertical split
669 | :new term://bash " alternates for above commands
670 | :vnew term://bash " alternates for above commands
671 | " go back to NORMAL mode
672 | ```
673 | ### Both:
674 | ```vim
675 | " suspend vim to background, `fg` in term to resume
676 | :sus[pend][!] or st[op][!] " suspend vim (equal to ctrl-z) if `!` is specified
677 | " vim will write changes to all buffers before suspend
678 | ```
679 |
680 | ## Spellcheck
681 | ```vim
682 | :set spell " enable spellcheck for current buffer
683 | :set nospell " disable spellcheck for current buffer
684 | :set spelllang={lang} " set spellcheck lang, i.e. `en_us`
685 | [s " find previous misspelled word
686 | ]s " find next misspelled word
687 | z= " see spellcheck suggestions
688 | {num}z= " automatically accept (change) suggestion {num}
689 | zg " add current word to dictionary
690 | zw " add current word to dictionary as a 'bad' word
691 | zug " undo `zg`
692 | zuw " undo `zw`
693 | ```
694 |
695 | ## Misc commands
696 | ```vim
697 | K " lookup keyword under cursor with `man`
698 | ga " display dec/hex/oct values of character under cursor
699 | g8 " display hex value of utf-8 character under cursor
700 | g? " rot13 a character (cycle 13 alphanumeric chars backwards)
701 | ggg?G " rot13 entire buffer
702 | g< " view last command (:!) output
703 | " redraw window, clear status message (error messages, search, etc)
704 | " display filename and position
705 | g " display cursor, line and column position
706 | ```
707 | ```vim
708 | :help {keyword} " view help for {keyword}
709 | :help {keyword} " list help of matching {keyword}
710 | :helpgrep {keyword} " help search for {keyword}, open results with :cwindow
711 | :read {file} " read {file} below the cursor
712 | :!{cmd} " execute shell command {cmd}
713 | :!% " execute current file
714 | :!%:p " execute current file (use full path)
715 | :.!{cmd or !!{cmd} " filter current line through {cmd}
716 | !!date " replace current line with output of `date`
717 | :read !{cmd} " read output of {cmd} below cursor
718 | : or q: " enter command line window, or :q to exit
719 | q/ or q? " same as above but for searches
720 | :echo &{opt} " echo Vim option to command line (expand values)
721 | :set {opt}? " echo Vim option to commend line (no expand)
722 | :source " 'source': execute a file as a series of commands
723 | :source $MYVIMRC " source your $MYVIMRC
724 | :retab " retab current buffer according to `expandtab` and `shiftwidth`
725 | :earlier {time} " revert a file to earlier time, e.g. `earlier 1m`
726 | :later {time} " revert a file to later time
727 | :visual :edit " leave :Ex mode
728 | : " go to start of line in command line mode
729 | : " go to end of line in command line mode
730 | ```
731 |
732 | ## Ctrl-R and the Expression Register
733 |
734 | The expression register (`=`) is used to evaluate expressions and can be accessed using `"=` from NORMAL and VISUAL modes and `` from INSERT and ex command modes, it is very useful to insert registers and other input into the command line or directly to the document when you don't want to leave INSERT mode (useful so you can repeat the entire edit with `.`):
735 |
736 | ### INSERT and ex modes:
737 | ```vim
738 | :registers {reg} " display registers {reg} and their values
739 | :display "0 " display value of registers `"` and `0'
740 | :{line}put " put clipboard register under {line}
741 | :put{reg} " put value of {reg} in the line below
742 | :put={expr} " put value of {expr} in the line below
743 | :let @{reg}={expr} " manually assign value to {reg}
744 | :let @*=expand('%') " expand current file path into `*` (clipboard)
745 | {reg} " put register {reg}
746 | ={expr} " put the value of {expr}
747 | =[1,2,3] " put 123
748 | % " put file path of current buffer
749 | - " put last deleted text
750 | : " put word under cursor
751 | : " put WORD under cursor (includes punctuation)
752 | : " put current cursor line
753 | : " put file path under cursor (does not expand ~)
754 | : " put file path under cursor (expands ~)
755 | ```
756 |
757 | ### NORMAL and VISUAL modes:
758 | ```vim
759 | "={expr} " evaluate {expr} into the expression register
760 | "={expr}p " evaluate {expr} and paste (also saved in the register)
761 | "={expr}P " save as above, paste before the cursor
762 | ```
763 |
764 | **Notes:**
765 | - For more information on evaluating expressions `:help expression`. For even more information read [Aaron Bieber's: Master Vim Registers With Ctrl R](https://blog.aaronbieber.com/2013/12/03/master-vim-registers-with-ctrl-r.html) and watch [Vimcasts: Simple calculations with Vim's expression register calculations with Vim's expression register](http://vimcasts.org/episodes/simple-calculations-with-vims-expression-register/)
766 |
767 | - When inserting a register with `{reg}` and then repeating the edit with `.` you will find out that same text will be entered even if the register contents has changed, to have the actual command enter the `.` register we need to use `{reg}` instead. Best shown with an example, say we have the below text and we wish to add parens around the text
768 |
769 | ```vim
770 | one " we want to change this to => (one)
771 | two " we want to change this to => (two)
772 | ```
773 |
774 | We can modify the first line using `ciw(+)` which will result in "(one)" but when we repeat the action for "two" the result would still be "(one)" as the actual text is saved in the register. To circumvent this we can use `ciw(+)` instead which inserts the actual command `^R^O+` into the register, that way when we repeat the action with `.` the result would be as expected "(two)".
775 |
776 | - For more information regarding `` read `:help i_ctrl-r_ctrl-o` and watch [Drew Neil's vimcast: Pasting from INSERT mode](http://vimcasts.org/episodes/pasting-from-insert-mode/)
777 |
778 | ## Comparing buffers with vimdiff
779 | ```vim
780 | :windo diffthis " Edit current windows in diff mode
781 | :windo diffoff " Exit diff mode
782 | :diffput {bufspec} " Put diff into {bufspec} from current buffer
783 | :diffget {bufspec} " Pull diff from {bufspec} into current buffer
784 | do " diff (o)btain, NORMAL mode for `:diffget`
785 | dp " diff (p)ut, NORMAL mode for `:diffput`
786 | [c " jump to previous (c)hange
787 | ]c " jump to next (c)hange
788 | :windo set scrollbind " bind all current windows scrolling
789 | :windo set noscrollbind " unbind all current windows scrolling
790 | ```
791 |
792 | **NOTE:**
793 |
794 | - The shortcuts `do` and `dp` also run `:diffupdate`, so the equivalent of `dp` can be thought of as `:diffput {target buffer} | diffupdate`
795 |
796 | - `{targetbuffer}` above is automatically resolved as the 'other buffer' on a 2-way split, that works for both `do` and `dp`. However, `do` cannot sensibly decide which buffer to use in a 3-way split (git merge conflict resolution) and therefore cannot be used in this case. `dp` assumes we always want to 'push' changes to the working copy which is always the middle buffer and therefore can be used in a 3-way split from either the left (target) or right (merge) buffers.
797 |
798 | ## Folding
799 | Fold methods (set with `set foldmethod=`:
800 |
801 | ```vim
802 | manual " folds must be defined by commands (i.e. `zf`)
803 | indent " folds are defined by lines of equal indent
804 | expr " folds are defined by `foldexpr`
805 | marker " folds are defined by `{{{` and `}}}`
806 | syntax " folds are defined by syntax highlighting
807 | diff " folds are defined by non-modified text
808 | ```
809 |
810 | ```vim
811 | zo " open fold under cursor
812 | zO " open folds under cursor recursively
813 | zc " close fold under cursor
814 | zC " close folds under cursor recursively
815 | za " toggle fold under cursor
816 | zA " toggle folds under cursor recursively
817 | zM " close all folds, set `foldlevel` to 0
818 | zR " open all folds, set `foldlevel` to highest level
819 | zn " sets `nofoldenable`, disable folding
820 | zN " set `foldenable`, restore all previous folds
821 | zi " toggle between `foldenable` and `nofoldenable`
822 | ```
823 |
824 | Fold management when `foldmethod` is set to `manual` or `marker`:
825 |
826 | ```vim
827 | zf{motion} " create a fold from current line to motion
828 | {visual}zf " create a fold around visual selection
829 | {count}zF " create a fold for {count} lines
830 | :{range}fo[ld] " create a fold for {range} (e.g. `:.,+3fo`)
831 | zd " delete surrounding fold at the cursor
832 | zD " recursively delete surrounding fold
833 | zE " delete all folds in current window
834 | ```
835 |
--------------------------------------------------------------------------------