# Practical Vim: Tip Summary

Drew Neil. 2nd Edition. ISBN 978-1-68050-127-8

# The Vim Way

## 1. Meet the Dot Command

Use the . command to repeat the last action whenever possible. If there’s more than one way to accomplish a task (e.g., deleting a word), prefer the method that is most composable with the dot command.

## 2. Don’t Repeat Yourself

Use “combined” commands to perform multiple actions at once:

Command Equivalent Command(s) Meaning
C c$delete to end of line and enter insert mode s cl / xi delete char under cursor and enter insert mode S ^C / ^c$ / ddO delete all line contents and enter insert mode
I ^i enter insert mode at start of line
A $a enter insert mode at end of line o A<CR> /$a<CR> add new line below and enter insert mode
O ko / kA<CR> / ka<CR> add new line below and enter insert mode ## 3. Take One Step Back, Then Three Forward In an effort to make an action repeatable, it might be best to delete something then retype at least part of it. This is probably best described with an example. Suppose we want to put spaces around + operators in an expression: use f+ to find the next occurrence; then s<Space>+<Space><Esc> to remove the existing operator and put it back with surrounding spaces; and then repeat both with ;. to replace other remaining occurrences. ## 4. Act, Repeat, Reverse Perform an action (change, delete, etc.), repeat it as necessary, and when you go too far, undo it or go backwards. Examples: Action Repeat Reverse insert/change . u search (/, ?) n N jump to char (f, F) ; , s/find/replace & u ## 5. Find and Replace by Hand Instead of using :substitute with the g flag to replace all occurrences blindly (which could be dangerous), be more “surgically precise” by searching with /, performing the change manually on the first occurrence, then using n and . to find each successive occurrence and repeat the change, respectively. ## 6. Meet the Dot Formula Strive for an ideal one keystroke to move, then one keystroke to repeat the change. # Modes ## Normal Mode ### 7. Pause with Your Brush Off the Page “Normal mode” is called “normal” for a reason: Vim users should be in normal mode more often than any other mode. Return to normal mode whenever it makes sense—and then some. ### 8. Chunk Your Undos When inserting text, the u command undoes the last complete i{text}<Esc> sequence. By leaving insert mode every once in a while, the user can control the granularity of the undo command. If you are wondering if you should leave insert mode, just do it. Note: Using the arrow cursor keys in insert mode will create a new undo chunk. ### 9. Compose Repeatable Changes When faced with more than one way to do something, opt for the most repeatable method. Try to keep the . command primed at all times. ### 10. Use Counts to Do Simple Arithmetic Use <C-a> and <C-x> to add and subtract values to the number under the cursor (or the next occurring number). Prefix these commands with a count to do simple arithmetic. This works with decimal-, binary- (0b), and hex- (0x) formatted numbers. See :h 'nrformats' for more details. ### 11. Don’t Count If You Can Repeat Counting the number of letters, words, lines, etc to change or delete is highly error-prone and problematic: if the count is off, the command has to be undone, modified, and/or retyped to correct. Instead, perform the command on a single element, then use . to repeat and u to undo when you go a little overboard. ### 12. Combine and Conquer Many Vim actions are composed by operators and motions. Learn to use these and think with them. Example operators are: • c to change • d to delete • y to yank • g~ to swap case • gu to make lowercase • gU to make uppercase • > to indent • < to un-indent • = to format (auto-indent) • ! to run through an external filter program Example motions include: • h, j, k, and l for character-wise • w, b, e, and ge for word-wise • ( and ) for sentence-wise • { and } for paragraph-wise • n and N for the text between the cursor and the next/previous match • gn for the next search match • i{object} and a{object} for text objects • {mark} and '{mark} for the text between the cursor and the given mark After typing an operator, Vim enters “operator-pending” mode as it waits for the next motion/command. Repeating the operator command typically operates on the entire line that the cursor is on. Operators and motions can be extended through plugins. ## Insert Mode ### 13. Make Corrections Instantly from Insert Mode To correct mistakes in insert mode, use the following delete commands: • <C-h> (or <BS>) to delete the last-typed character • <C-w> to delete the last-typed word • <C-u> to delete to the start of the current line These commands also typically work in the shell. ### 14. Get Back to Normal Mode When in insert mode, use <Esc> or <C-[> to get back to normal mode. Alternatively, <C-o> will enable “insert normal” mode, which will allow the user to perform a single normal-mode command, then re-enter insert mode. ### 15. Paste from a Register Without Leaving Insert Mode Use <C-r>{register} to paste the contents of a register while in insert mode. This has the effect of typing each of the characters in the register as if it were typed by hand (which could do weird things with wrapping or indentation). To prevent this, use <C-r><C-p>{register} instead, or just use a put command from normal mode. Note: With all of the recently-mentioned Ctrl commands, many Vim users remap the Caps Lock key to a Ctrl key. ### 16. Do Back-Of-The-Envelope Calculations in Place The = register (expression register) stores the result of a vim expression. Use <C-r>= to insert the result of simple arithmetic. ### 17. Insert Unusual Characters by Character Code Special characters can be entered by their hexadecimal Unicode character code with <C-v>u{code}. ### 18. Insert Unusual Characters by Digraph Some common special characters (e.g., accents and punctuation) have two-character digraphs that vim combines into a single character. These can be inserted with <C-k>{char1}{char2}. See :h digraph-table for a list of available digraphs. ### 19. Overwrite Existing Text with Replace Mode Sometimes it’s beneficial to overwrite text instead of inserting it. Use R to enter this mode. Replacing tab characters can be tricky since they take up more than one character’s space on the screen. Use gR to enter virtual replace mode, which takes into account character positioning on screen. If already in normal mode, single characters can be replaced with the r{char} command (or gr{char} command for virtual insert mode). ## Visual Mode ### 20. Grok Visual Mode Visual mode selections in Vim are different than text selections in other editors: Vim uses visual mode to allow the user to specify a custom range of text on which other commands can operate. In some cases, it can be better to use motions to operate on text rather than making a visual selection (e.g. caw is better than vawc for changing the word under the cursor) ### 21. Define a Visual Selection The following commands are used to enter the various visual selection modes: • v for visual mode (character granularity) • V for visual line mode (line granularity) • <C-v> for visual block mode (rows and columns) • gv to re-select the last visual selection Each of the v, V, and <C-v> commands can be used while in a visual selection mode to change to that mode or get out of visual selection mode (if the same mode key is pressed again). Typically, the visual selection is anchored where the cursor was when the user invoked visual mode. The o command will move the cursor to the other end of the selection and allow its position to be changed (leaving the former end anchored). ### 22. Repeat Line-Wise Visual Commands When performing an action over a multi-line visual selection, the . command will remember the number of lines that the action affected. ### 23. Prefer Operator Commands to Visual Commands Where Possible If an action can be accomplished by using an operator and motion combo, then use it instead (since operator and motion commands are more repeatable with the . command). ### 24. Edit Tabular Data with Visual-Block Mode Visual Block mode (<C-v>) is very useful for editing tabular data that is aligned using spaces. Text or space can be inserted with I (or appended with A), column delimiters can be added by replacing space in the selection with r|, and text or space can be deleted with d or x. ### 25. Change Columns of Text If text is aligned in such a way that the same change can be applied at the same column on multiple lines, then Visual block mode can be used to apply that same change via the I/A for insert/append, r for replace, c for change, or d/x for delete. ### 26. Append After a Ragged Visual Block Visual block mode is smart enough to append the same text to the end of multiple lines even if the line ends do not match. In a visual block, use to extend the selection to the ends of the lines in the range, and append text with A.

Note: while in any of the visual modes, i and a serve as prefixes to specifying text objects, hence I and A are used to unambiguously insert and append.

## Command-Line Mode

### 27. Meet Vim’s Command Line

From normal mode, the : key brings up vim’s command line, where commands can be executed to perform just about any action imaginable. This command-line has its beginnings in the ex command-line editor, which preceded vi, which preceded vim. Much of the functionality available in ex is still available in vim today.

While typing in the command-line, most of the insert-mode commands (<C-r> for pasting from registers, <C-w> and <C-u> for deleting words and lines, and <C-v> and <C-k> for inserting characters.

### 28. Execute a Command on One or More Consecutive Lines

Most ex commands for editing text accept a range prefix. These ranges can be:

• 4, a specific line number
• $, the last line in the file • 0, “virtual line” above the first line in the file • 4,8, starting and ending line numbers (each start/end could, in turn, be an alternate type of range object) • %, all lines in the file • '<,'>, the start and end lines of the last visual selection (automatically inserted when entering command-line mode from visual mode • 'm, the line containing a mark • /{pattern}/, start or end line search patterns • +{number} and -{number}, appended to an existing range to offset the matched line ranges (or relative to the current cursor position if not appended but used as-is) • ., the current cursor position ### 29. Duplicate or Move Lines Using :t and :m Commands The :copy and :move commands (:t and :m for short) copy or move the lines referenced in the range prefix to the line referenced in the destination line suffix. These commands are useful for copying or moving text over long distances, even regardless of cursor position. ### 30. Run Normal Mode Commands Across a Range If we want to apply the same normal mode commands over all of the lines in a range, the :normal (or :norm for short) can do just this. For example, to append a semi-colon to all lines in a range, we could use :1,3norm A; instead of making a visual block selection or repeating j. over each line. ### 31. Repeat the Last Ex Command The @: macro for ex commands is analogous to the . command for normal mode actions. However, some ex commands are not straightforward to reverse (in keeping with the “act, repeat, reverse” mindset. ### 32. Tab-Complete Your Ex Commands The <Tab> key can be used to auto-complete ex commands, just like how filename and command completion work in the shell. The <C-d> command reveals a list of available options for completion. See :h command-complete for more details. The behavior and appearance of completion options can be adjusted with the :h 'wildmode' option. ### 33. Insert the Current Word at the Command Prompt Use <C-r><C-w> to copy the word (or <C-r><C-a> for WORD) under the cursor into the command prompt. This can be useful for looking up help while editing the vimrc file or inserting the current word for substitution. ### 34. Recall Commands from History Like in a shell, the <Up> and <Down> keys cycle through previously executed commands. A buffer containing vim’s command history can be opened with q: (often opened accidentally when users try to press :q too quickly). From the history buffer, pressing <CR> on a line will execute that command. The buffer is also editable, so we can change commands and press <CR> to execute the modified command. Vim also has a list of recently executed search expressions. This buffer can be opened with q/. To switch from the command line mode to the command window, use <C-f>. ### 35. Run Commands in the Shell From vim’s command line, prefixing a command with :! causes vim to execute that command in the shell. For example, :!ls will list the contents of vim’s working directory. In the command line, the % character represents the current file, so :!ruby % will execute the current file in ruby. The :shell command drops us into a shell inside vim. Neovim has an improved :terminal command that opens a buffer with a terminal in it. Alternatively, vim could be suspended with the <C-z> command, placing us back in the shell from which we executed vim. Buffer contents can also be piped to and from shell commands: • :write !{command} pipes the buffer contents to stdin of the shell program. This command optionally accepts a range prefix to control what gets piped to the shell command • :read !{command} pipes stdout of the command to the current cursor position in the buffer • :{range}!{command} filters the buffer contents through the command. The range is required (use % for all lines) to disambiguate the default shell execution. The !{motion} normal mode command helps to pre-populate the range. ### 36. Run Multiple Ex Commands as a Batch Instead of executing multiple vim commands one-by-one on the command line with :, all of the commands can be specified in a separate file (without the : prefix) and then executed with the :source command. To source the same file for multiple files in the arglist or buffer list, use :argdo source batch.vim or :bufdo source batch.vim # Files ## Manage Multiple Files ### 37. Track Open Files with the Buffer List When vim opens a file, it creates a buffer and copies the contents of the file into the buffer. • View the buffer list with :ls • Switch to a buffer with :buffer {number} • Go to the first/prev/next/last buffer with :bfirst/:bprevious/:bnext/:blast • Delete buffers with :bdelete ### 38. Group Buffers into a Collection with the Argument List When opening vim from the command line, any files passed as arguments will be opened as buffers, and those buffers will be grouped into the argument list. This list can be viewed with :args and populated/modified with :args file.... File globbing and shell backtick operators also work with this command. Use the :first, :last, :next, and :previous commands to traverse the argument list. ### 39. Manage Hidden Files By default, vim will not allow unmodified buffers to lose focus without a ! override suffix to the command. The :h 'hidden' option can be used to disable this behavior. If a modified buffer is hidden, then attempting to exit vim will cause a similar warning regardless of the :h 'hidden' option. This option should be set prior to executing any :bufdo or :argdo commands. These commands will execute the given command on every buffer in the buffer list and argument list, respectively. ### 40. Divide Your Workspace into Split Windows Vim has support for split editing on an arbitrary number of panes. Each pane can have its own buffer, or reference the same buffer. • <C-w>s and :split split the active pane into one above the other, focusing the top. • <C-w>v and :vsplit split the active pane into one next to the other, focusing the left The command variants take an optional file argument to open. To change focus, use <C-w>w to cycle; or <C-w>h, <C-w>j, <C-w>k, and <C-w>l to move directionally. All of these commands also work while holding down the Ctrl key for the second key (e.g. <C-w><C-s>, which is easier to execute, but uglier to read). ### 41. Organize Your Window Layouts with Tab Pages Vim’s tabs are different from other editors: other editors have an overall “context” with tabs that represent open files within that context. Vim tabs each have their own “context” and are primarily meant to have differing window layouts, different projects, and/or different working directories (i.e., one tab per area/task of focus). Move a window to a new tab with <C-w>T or open a new tab with an optional file with :tabedit. Use gt/:tabnext and gT/:tabprevious to cycle back and forth between tabs. Tabs will close automatically when their last buffer is closed, but an entire tab may be closed with :tabclose. All other tabs may be closed, leaving the currently focused tab with :tabonly. Tabs can be rearranged with :tabmove [N], where N is the position to move it (0 is front). If omitted, the tab is moved to the end. ## Open Files and Save Them to Disk ### 42. Open a File by Its Filepath using :edit Opens a file relative to vim’s working directory (use :pwd to view). %:h is the path to the directory containing the current buffer’s file. It may be beneficial to create a mapping for this in vimrc: cnoremap <expr> %% getcmdtype() == ':' ? expand('%:h').'/' : '%%' ### 43. Open a File by Its Filename Using :find :find searches for a file by name in in the path(s) set in the :h 'path' option. Add ** to it (set path+=**) to allow :find to open any file recursively under the current working directory by name. ### 44. Explore the File System with netrw Opening vim to a directory from the shell (vim /path/to/directory/) or with the :edit (e.g. :e. for the current directory) command will open the built-in netrw file explorer in that directory. :Explore, :Sexplore, and :Vexplore will open the file explorer in the current window, split window, or vertical split, respectively. ### 45. Save Files to Nonexistent Directories Attempting to save a file to a nonexistent directory with :saveas (or a priori with the :edit command) results in an error, but gives the buffer a path. Therefore we can use :!mkdir -p %:h to create the directory and call :write again. ### 46. Save a File as the Super User Use :write !sudo tee % > /dev/null to save a file as the super user: it pipes the content of the buffer through the sudo tee shell command, which then writes it to the current file path and mutes the echoed output. # Getting Around Faster ### 47. Keep Your Fingers on the Home Row Keep your fingers on the home row and use hjkl to move around. Keep your hand where it belongs (on jkl;), since finding the next occurrence of a letter (;) is more common than moving left one character (h). If you need help breaking the habit of going to the arrow keys, map them to <Nop> inside vimrc: nnoremap <Up> <Nop> nnoremap <Down> <Nop> nnoremap <Left> <Nop> nnoremap <Right> <Nop> ### 48. Distinguish Between Real Lines and Display Lines With the :h 'wrap' option enabled, motions might behave differently— especially j, k, ^, 0, and$—due to a single line of text occupying more than one line on the display. These commands can move relative to display lines by prefixing them with g: gj, gk, g^, g0, and g$. This behavior can be swapped if you prefer by remapping them in vimrc: nnoremap j gj nnoremap gj j nnoremap k gk nnoremap gk k ... ### 49. Move Word-Wise Moving by words are much faster than moving by individual characters: • w moves forward to start of next word • e moves forward to end of next word • b moves backward to start of current or previous word • ge moves backward to end of current or previous word A word is any sequence of letters, digits, and underscores (or otherwise a sequence of non-blank characters separated by whitespace). A WORD is simply a sequence of non-blank characters separated by whitespace. Use uppercase variants of the above commands to move even faster by WORDs: W, E, B, and gE. ### 50. Find by Character Use the f and t commands to move forward to the next occurrence of the given character (or “til” in the case of t), the ; command to repeat the search, and the , command to reverse. Use F and T to search backward. Think like a Scrabble player: infrequent characters work better. ### 51. Search to Navigate Searching with / and ? can cover long distances with a few keystrokes. It may not be necessary to search for the whole word of interest: start with a few characters, and press <CR> once the desired match is selected. Tip: enable the :h 'hlsearch' and :h 'incsearch' to highlight occurrences and automatically identify the next occurrence as the pattern is typed. Search can also be used as a motion and to extend a visual mode selection. ### 52. Trace Your Selection with Precision Text Objects Take advantage of delimiters and text structure to precisely identify motions. Text objects follow the pattern i for “in” (excluding delimiters) and a for “all” (including delimiters). A few sample text objects are identified below, but see :h text-objects for a complete list. • {/}, [/], (/), </> — Matching delimiters • ", ', , — quoted delimiters • b — parentheses • B — curly braces • w — word • W — WORD • s — sentence • p — paragraph • t — HTML/XML tag ### 53. Delete Around, or Change Inside When deleting, usually the a text object is preferred. When changing, usually the i text object is preferred. This is most apparent with words, since a includes the whitespace following a word. ### 54. Mark Your Place and Snap Back to It Use the m{a-z} command to set a local mark (in the buffer), or m{A-Z} to set a global mark (even across files). The '{mark} and {mark} commands can be used to snap back to a local or global mark location. The former can also be used with local markers to specify a range for an ex command. The following marks are created automatically: •  The cursor position before the last jump within the current file • . The location of the last change • ^ The location of the last insertion • [ The start of the last change or yank • ] The end of the last change or yank • < The start of the last visual selection • > The end of the last visual selection There are 26 local marks and 26 global marks, so use them liberally. ### 55. Jump Between Matching Parentheses Use the % command to jump from the opening or closing delimiter to the matching delimiter. When changing delimiters, use % to go to the other delimeter before changing it. That way, pressing  or <C-o> will snap back to the other delimiter. Tim Pope’s surround plugin is better for this action anyway. The matchit plugin included with vim can also match opening and closing HTML/XML tags. See :h matchit-install for more info. ### 56. Traverse the Jump List Every time the cursor changes position over a large distance, vim stores the cursor position history in the jump list. <C-o> traverses backward, and <C-i> traverses forward through this list. The following commands are considered jumps: • [count]G — going to the specified line number or end of file if omitted • searches (/, ?, n, and N) • % — jumping to a matching delimiter • ( / ) — jumping to the previous/next paragraph • { / } — jumping to the previous/next paragraph • H / M / L — moving the cursor to the top, middle, and bottom of the screen • gf — opening the file name under the cursor • <C-]> — jumping to the definition of the keyword/tag under the cursor. • '{mark} / {mark} — jumping to a marked location. ### 57. Traverse the Change List Vim also records the cursor location for each change. Instead of undoing and redoing a command to jump to the desired location, the g; and g, commands can be used to traverse the change list forward and backward, respectively. ### 58. Jump to the Filename Under the Cursor With the cursor over the path to a file, the gf command can be used to open that file in a new buffer. This is especially useful for languages that can include other files by path, but in many cases, the language omits the file extension for includes. Setting (or appending) values to the :h 'suffixesadd' option can allow us to open files for paths that do not contain an extension. For example, :set suffixesadd+=.rb will follow relative includes in ruby files. Vim will look for paths in directories specified in the :h 'path' option. ### 59. Snap Between Files Using Global Marks Set a global mark in vimrc (e.g. mV) to open it from anywhere. Use global marks to save the cursor location before code-diving with any of the :grep commands. There are 26 possible global marks, so use them liberally. # Registers ## Copy and Paste ### 60. Delete, Yank, and Put with Vim’s Unnamed Register Delete and yank operations place text in vim’s unnamed register by default (""). Transpose characters with xp and lines with ddp. Duplicate lines with yyp. ### 61. Grok Vim’s Registers Registers are addressed by character via "{char}. Use "a"z for custom (named) registers, since other characters are typically used for special registers: • "" - unnamed register: default register for delete, yank, and put operations • "0 - yank register: yanking text puts it in "" and "0 • "_ - black hole register: text goes in but never comes out • "+ - system clipboard (typically <C-v> to paste) • "* - system (X11 only) selection (typically middle-click to paste) • "= - expression register: returns the result of a VimL expression when fetched • "% - (read-only) the name of the current file • "# - (read-only) the name of the alternate file • ". - (read-only) last inserted text • ": - (read-only) last ex command • "/ - (read-only) last search pattern Using an uppercase letter ("A"Z) to append to the specified named register. ### 62. Replace a Visual Selection with a Register Executing put in visual mode will replace the selected text with the contents of the register and replace the register contents with the previously selected text (effectively swapping positions) Swapping words: 1. Delete the word (d{motion}), 2. Mark the position (m{mark}), 3. Go to the next word, 4. Visually select it (v{motion}), 5. Put the replacement word (p), 6. Jump back to the mark ({mark}), and 7. Put the other word (P) ### 63. Paste from a Register registers operate either in “character mode” or “line mode”, and this affects the behavior of the p and P commands: after/before the cursor column vs. after/before the cursor row. <C-r>{register} can be used to put the contents of a register while in insert mode. This is sometimes more intuitive than using p or P for a register in character mode. gp and gP behave just like p and P, but leave the cursor at the end of the pasted text instead of at the beginning. ### 64. Interact with the System Clipboard Applies only to terminal vim (not gvim). Pasting into the terminal (e.g. <C-S-v>) can do weird things if :h 'autoindent' is enabled since terminal-paste, just like <C-r> in insert mode, emulates typing each character manually. Prefer to use "+ to paste directly from the clipboard, but if this isn’t an option (e.g., when remotely editing over ssh or when vim is compiled without clipboard support), toggle :h 'paste' mode (e.g. :set paste / :set nopaste) to warn vim that the pasted text should be treated literally. Toggling paste mode can be made even easier by setting a :h 'pastetoggle' keybinding (e.g. :set pastetoggle=<F5>) to toggle from within insert mode, or by using the (yop) command from Tim Pope’s unimpaired plugin (you only paste once; YOPO). ## Macros ### 65. Record and Execute a Macro Use q{register} to start recording a macro, type the commands, then hit q again to stop. This copies the command character sequence to the designated register. Once recorded, use @{register} to play back the macro. After playing a macro, use @@ to replay the same macro. ### 66. Normalize, Strike, Abort When recording a macro, ensure that every command is repeatable. Follow these best practices: 1. Normalize the Cursor Position. Move the cursor to a well-known starting position, such as the beginning of the line (0 or ^, depending on whitespace), the end of the line ($), or the next search match (n).

2. Strike the Target with a Repeatable Motion. Use word- or sentence-wise motions, search, finding occurrences of a character, text objects, etc.

3. Abort when Motions Fail. If a motion fails, then vim will abort the rest of the macro. Use this to test whether the macro should apply (e.g. when replacing occurrences of a search, and there are no more matches.

### 67. Play Back with a Count

The dot formula (one keystroke to move, one keystroke to apply an edit) cannot be repeated with a count, so recording a quick macro and playing it back with a count can be beneficial. For example, suppose we want to add spaces around all of the + chars in x = "("+a+","+b+","+c+","+d+","+e+")";:

1. Prime the dot formula with f+ and s + <Esc>, replacing the first occurrence
2. Record the macro qq;.q, which replaces the second occurrence
3. Play back the macro with a count, which replaces the remaining occurrences. The ; motion fails when there are no more, so the macro aborts when done. Therefore the count doesn’t really matter.

### 68. Repeat a Change on Contiguous Lines

Add the j command to the end of the macro to advance to the next line, then the macro can be executed in series, aborting if a line encounters a problem with [count]@{register}.

If the abort behavior is unwanted, the trailing j command can be omitted, and the macro can be executed over a series of lines with the :normal command. This way, each invocation of the macro is executed standalone, so an abort on one line won’t stop the later invocations from executing.

### 69. Append Commands to a Macro

Like with the delete and yank commands, recording a macro to an upper-case register appends the commands to an existing macro instead of recording over it.

### 70. Act Upon a Collection of Files

First populate the arglist and go to the :first buffer. Record the macro to use by editing the first file (assume the macro is recorded in register "a). There are two ways to execute this macro across the remaining files in the arglist:

1. Use the :argdo command. Be sure to revert this file’s changes with :edit! before executing :argdo normal @a, otherwise the edits will be applied to the first file twice.
2. Append the :next command to the macro, so executing the macro automatically advances to the next one, then prefix the macro with a count.

Don’t forget to save all of the files with the :wall command.

### 71. Evaluate an Iterator to Number Items in a List

1. Initialize a counter by executing :let i = 1 (or whatever starting value you prefer) before recording a macro.
2. Inside the macro, insert the counter’s current value using the expression register (<C-r>=i)
3. At the end of the macro, increment the counter (:let i += 1, or whatever increment value you prefer).

### 72. Edit the Contents of a Macro

Note: use qAqZ to append commands to a macro instead of editing.

Since macros are stored as character sequences in a register, we can paste that register into a document. This register is in character mode, so use the :put {register} command to force vim to put the macro on a new line. The macro can now be edited as text.

Note: be sure to use keyboard codes for special sequences:

• <C-v><Esc> for <Esc> or <C-[>
• <C-v><CR> for <CR>

For example, replacing ~ (swap case of character under cursor) with vU or vu (set character under cursor to upper or lower) in a macro is easier than re-recording it.

:%s//\3,\2,\1

### 95. Perform Arithmetic on the Replacement

The replacement string can house a vim expression to do calculations on the replacement values. For example, to decrease the heading levels in an HTML document,

/\v\<\/?h\zs\d
:%s//\=submatch(0)-1/g

The submatch(0) expression grabs the match (which is just the number thanks to \zs).

### 96. Swap Two or More Words

A naïve attempt at swapping the positions of two words A and B might look like :%s/A/B/g|%s/B/A/g, but this ultimately changes all of the A’s and B’s to A’s.

Instead, create a lookup dictionary to hold the replacement values and swap all of them simultaneously:

/\v(<A>|<B>)
:%s//\={"A":"B","B":"A"}[submatch(1)]/g

The abolish plugin streamlines this even further with the following syntax:

:%S/{A,B}/{B,A}/g

### 97. Find and Replace Across Multiple Files

Search across multiple files with the :vimgrep command to populate the quicklist with all matches, then use :cfdo to execute a command across all files contained in the quickfix list (be sure to set the :h 'hidden' option first!):

/Pragmatic\ze Vim
:vimgrep // **/*.txt
:set hidden
:cfdo %s//Practical/gc
:cfdo update

Note: :update (:up for short) differs from :write in that :update saves the buffer only if it has changed.

## Global Commands

### 98. Meet the Global Command

The :global command (:g for short) executes an ex command for every line in the range that matches the pattern.

:[range] :global[!] /{pattern}/ [cmd]

Like :substitute, et al., if no pattern is given, the last-used search pattern is used by default. If no command is given, the :print command will be used by default.

:global differs from :substitute, et al. in that it operates on the entire file by default.

The trailing ! and the :vglobal command (:v for short) invert the behavior by executing the command for all lines that do not match the pattern.

Note the short form of this command: :g/re/p. This is where the term grep came from.

### 99. Delete Lines Containing a Pattern

Use :g//d to delete all lines that match the given pattern and :v//d to keep only the lines that match the given pattern.

### 100. Collect TODO Items in a Register

To aggregate all lines that are marked with a “TODO” comment, use :g/TODO. This will print out all matching lines, but it is more useful to use the :yank command to append them to a register for later use. First clear the "a register with qaq (record an empty macro), then :g/TODO/yank A.

Combine this with :argdo or :bufdo to collect TODO items from multiple files.

Alternatively, the :g/TODO/t$copies each matching line to the end of the file, but this is less effective across multiple files. ### 101. Alphabetize the Properties of Each Rule in a CSS File To alphabetize the CSS properties for every rule block delimited by { and }, use :g/{/ .+1,/}/-1 sort. What’s going on here? The :global command is of the form :g/{pattern}/[cmd], but [cmd] can in turn take the form [range][cmd]. In this case, the pattern is /{/, and the command is .+1,/}/-1 sort (sort all lines from the line after the cursor to the line before the one matching /}/). The :global command sets the cursor position to each matching line prior to executing the command. A similar command can be used to indent each line: :g/{/ .+1,/}/-1 >. This outputs a message for each time the > command is invoked. This can be suppressed with the :silent command: :g/{/silent .+1,/}/-1 >. # Tools ## Index and Navigate Source Code with ctags The ctags program must be installed prior to using these tips: • Universal ctags is the currently maintained version • Exuberant ctags is languishing • the older BSD/Unix ctags executable will probably work, but the format of the file it generates is different. ### 102. Meet ctags Assuming ctags is installed, generate a tags file by executing it over a series of files:$ ctags **/*.rb

The tags file contains an index of keywords, the type of the keyword (e.g. class or function), teh file in which the keyword is located, and a search pattern to identify the line on which the keyword is defined.

### 103. Configure Vim to Work with ctags

The :he 'tags' option tells vim where to look for tags files. The default value is ./tags,tags: the directory of the current file, and the working directory.

As files change, the tags file will need to be updated. We can do this without leaving vim: :!ctags -R. This could be mapped to a key for easier access (:nnoremap <f5> :!ctags -R<CR>) or even executed automatically whenever a file is saved (:autocmd BufWritePost * call system("ctags -R")).

### 104. Navigate Keyword Definitions with Vim’s Tag Navigation Commands

With the cursor over a keyword, the <C-]> command will jump to that keyword’s definition. This pushes the cursor location onto a stack that can be popped (equivalent to pushing a browser’s “back” button) with the <C-t> command.

If there are multiple matches for the tag under the cursor, the tag with the highest priority wins. Multiple matches can be disambiguated with the g<C-]> command, which presents a list of tags to choose from.

In addition to <C-]>, g<C-]>, and <C-t>, vim has the following ex commands for navigating with tags:

• :tag {keyword} - go to the first tag that matches the keyword
• :tjump {keyword} - prompt to select multiple matching keywords
• :pop - go back through tag history
• :tag - go forward through tag history (note lack of keyword)
• :tnext - go to next matching tag
• :tprev - go to previous matching tag
• :tfirst - go to first matching tag
• :tlast - go to last matching tag
• :tselect - prompt user to choose an item from the tag match list

## Compile Code and Navigate Errors with the Quickfix List

### 105. Compile Code Without Leaving Vim

If the current directory is a C/C++ project and has a Makefile, GNU make can be invoked from within vim with the :make command. This command accumulates compile errors into the Quickfix list and automatically jumps to the first record if the compiler encounters any errors.

To disable the auto-jump behavior, use :make! instead.

### 106. Browse the Quickfix List

The following commands can be used to navigate the quickfix list:

• :copen - open the quickfix window
• :cclose - close the quickfix window
• :cdo {cmd} - run a command on each line in the quickfix list
• :cfdo {cmd} - run a command on each file in the quickfix list

The :lmake, :lgrep, and :lvimgrep commands populate a location list for the active window. This list can be traversed with similar commands, substituting the c for l. (e.g. :lnext and :lprev)

The quickfix window behaves similarly to the command and search history windows: pressing <CR> on a line will jump to that location.

The unimpaired plugin maps [c, ]c, [C, ]C for navigating the quickfix list (among many other useful shortcuts).

### 107. Recall Results from a Previous Quickfix List

Each time the quickfix list is populated, vim saves the previous list. Older lists can be accessed with the :colder command, and newer lists can be accessed with the :cnewer command. It would be amusing to remap :warmer to :cnewer.

These act like “undo” and “redo”, but for the quickfix list: :make could be used to populate errors, then :grep could be used to search for something related to an error, then :colder could “undo” the list populated by :grep and recovering the list originally set by :make.

### 108. Customize the External Compiler

By default, :make calls make. The program and error parsing format can be changed to work with other utilities (e.g., nodelint) with the :h 'makeprg' and :h 'errorformat' options:

:setlocal makeprg=NODE_DISABLE_COLORS=1\ nodelint\ %
:setlocal errorformat=%A%f\,\ line\ %l,\ character %c:%m,%Z%.%#,%-G%.%#

Setting these for each buffer is not ideal, so they should be saved to a compiler plugin that can be loaded with the :compiler {program} command.

In general, :make and :compiler can be used to invoke any external utility from inside vim.

## Search Project-Wide with grep, vimgrep, and Others

### 109. Call grep Without Leaving Vim

The :grep command is just a wrapper for the grep program that would be used from inside the shell. Vim populates the quickfix list with the results. The :lgrep command populates the location list instead.

Be warned that grep’s expression language is not the same as vim’s.

### 110. Customize the grep Program

The syntax for executing the grep executable can be modified with the :h 'grepprg' and :h 'grepformat' options. For example, to use ack instead of grep:

:set grepprg=ack\ --nogroup\ \$*
:set grepformat=%f:%l:%c:%m

### 111. Grep with Vim’s Internal Search Engine

The :vimgrep command functions almost identically to :grep, only it allows the use of vim’s pattern expression language. If the pattern is omitted, it defaults to the last used search pattern.

In either :grep or :vimgrep, the ## sequence can be used to represent all files in the arglist.

One downside to :vimgrep is that it is much slower than :grep.

## Dial X for Autocompletion

### 112. Meet Vim’s Keyword Autocompletion

From insert mode, Vim populates keywords from various sources depending on the invocation used. The simplest invocations are generic keyword completion via <C-n> and <C-p>, which reference the next and previous occurrences of the string under the cursor.

Be careful if :h 'ignorecase' is set: this could cause a capitalized word to be suggested when one is not desired. This can be remedied with the :h 'infercase' option, which coerces the capitalization of keyword suggestions.

Other invocations include:

• <C-x><C-n> - keywords from the current buffer
• <C-x><C-i> - keywords from included files
• <C-x><C-]> - keywords from tags files
• <C-x><C-k> - dictionary lookup
• <C-x><C-l> - whole line completion
• <C-x><C-f> - filename completion
• <C-x><C-o> - omni-completion

### 113. Work with the Autocomplete Pop-Up Menu

The following commands can be used to navigate the autocomplete pop-up menu:

• <C-n> / <Down> - next match in the list
• <C-p> / <Up> - previous match in the list
• <C-y> - accept the currently selected item (yes)
• <C-e> - revert to originally typed text (exit)
• <C-h> / <BS> - delete character from current match
• <C-l> - add one character from current match
• {char} - stop completion and insert the character

<Up> and <Down> merely highlight the word in the list without updating the document, but <C-n> and <C-p> select it and update the document to reflect that word. Once the desired word is selected, additional typing will close the pop-up menu.

<C-n><C-p> summons the autocomplete list, but will filter in real-time as additional characters are entered.

### 114. Understand the Source of Keywords

Generic keyword completion (<C-n> and <C-p>) uses a bunch of sources to generate suggestions. Other invocations use more targeted sources.

<C-x><C-n> is useful when the keyword is known to be in the current buffer.

<C-x><C-i> is useful to load keywords from externally loaded libraries. The locations from which to load these libraries can be changed with the :h 'include' option (but this is often handled by filetype plugins).

<C-x><C-]> autocompletes classes, functions, etc., from the tags file.

The keyword sources used by generic keyword completion can be set with the :h 'complete' option.

### 115. Autocomplete Words from the Dictionary

Dictionary completion <C-x><C-k> filters suggestions from a word list. The easiest way to load a word list is to enable the :h 'spell' option. Alternatively, the :h 'dictionary' option can be used to point to custom files containing word lists.

### 116. Autocomplete Entire Lines

<C-x><C-l> can be used to duplicate lines (even from far away) within insert mode. Indentation is ignored.

### 117. Autocomplete Sequences of Words

Vim remembers the context of words selected using autocomplete and can be used to insert entire phrases instead of just words by repeatedly pressing, for example, <C-x><C-p>. The same is true for lines: repeatedly pressing <C-x><C-l> can be used to repeat several lines.

### 118. Autocomplete Filenames

Filename completion (<C-x><C-f>) is always relative to the current working directory. The :cd command can be used to change the working directory. After changing, the :cd - command can be used to “pop” the directory (go back).

### 119. Autocomplete with Context Awareness

Omni-completion (<C-x><C-o>) is able to determine the context of the text to be completed depending on the file type. Plug-ins can be used to expand vim’s knowledge of autocompletion contexts.

## Find and Fix Typos with Vim’s Spell Checker

### 120. Spell Check Your Work

Enable spell checking with :set spell. With spell checking enabled, the following commands can be used to check spelling:

• z= - suggest spelling corrections for the current word
• zg - add the current word to the spell file
• zw - remove the current word from the spell file
• zug - revert the zg or zw command for the current word

### 121. Use Alternate Spelling Dictionaries

Vim supports regional variations of English by default. The regional language variant can be set with the :h 'spelllang' option: e.g., :set spelllang=en_us.

If spelllang is set to a language that is not installed, vim will prompt to install it automatically.

### 122. Add Words to the Spell File

If vim’s spell checker doesn’t recognize a word that is spelled correctly, the zg command can be used to add it.

If vim’s spell checker thinks a word is spelled properly, but it is actually misspelled, the zw command can be used to remove it.

If zg or zw is used accidentally, zug can be used to undo it. These customizations are saved to :h 'spellfile'. This option can contain multiple files (useful for storing jargon related to a certain context):