Practical Vim: Tip Summary

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


Table of Contents

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> / k$a<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:

Example motions include:

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:

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:

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:

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:

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.

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.

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:

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.

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:

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:

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:

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:

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.

When finished, delete or yank the macro back into the register, but don’t use dd or yy, since this puts the register in line mode and adds a newline (^J) character sequence to the end of the macro. Use 0"{register}D or 0"{register}y$ to take everything in the line excluding the trailing newline.

Sometimes it’s easier to run a vim script on the contents of the register instead of editing he file in a buffer. The above example replacement could be accomplished with :let @a=substitute(@a, '\~', 'vU', 'g').

Patterns

Matching Patterns and Literals

73. Tune the Case Sensitivity of Search Patterns

Set case sensitivity (or insensitivity) globally with the :h 'ignorecase' option. Use \c (ignore case) or \C (case-sensitive) in a search pattern to set locally for that pattern.

Set the :h 'smartcase' option to be case-insensitive by default, but switch to case-sensitive when a capital letter is detected in the pattern.

74. Use the \v Pattern Switch for Regex Searches

Vim’s default pattern engine doesn’t have many “special pattern characters” enabled by default, so they must be “escaped” to indicate they have special meaning. The “very magic” pattern switch (\v) uses a more PCRE-compatible regex engine that uses special characters by default.

For example, the pattern /#\([0-9a-fA-F]\{6}\|[0-9a-fA-F]\{3}\) matches CSS hex color codes, but adding the very magic flag simplifies the use of special characters: /\v#([0-9a-fA-F]{6}|[0-9a-fA-F]{3}) or even just /\v#(\x{6}|\x{3}).

75. Use the \V Literal Switch for Verbatim Searches

The \V literal switch does the opposite of what the \v very magic switch does: it cancels out most of the special meanings associated with non-alphanumeric characters in a pattern.

76. Use Parentheses to Capture Submatches

Submatches are most often used in substitutions, but they can also be used in search patterns. For example, \v<(\w+)\_s+\1> matches any duplicate words.

To use parentheses without capturing submatches, use %(...) instead.

77. Stake the Boundaries of a Word

In very magic (\v) patterns, the < and > characters represent the zero-width boundary between a word and its surrounding whitespace or punctuation. Without \v, these have to be escaped as \< and \>, respectively.

The * and # quick search commands add these delimiters automatically, but the g* and g# commands can be used to omit them if desired.

78. Stake the Boundaries of a Match

Vim differentiates between the pattern and the text that is matched by that pattern. Matches are easily visible when :h 'hlsearch' is enabled. Typically, the matched text is what matches the entirety of the pattern, but the special \zs and \ze flags can be used to set the start and end (respectively) match boundaries explicitly.

For example, /Practical Vim will match the entire string Practical Vim, but /Practical \zsVim will match just Vim as long as it has a preceding Practical . Another use case is to match the contents of a quoted string and not the quote delimiters themselves: /\v"\zs[^"]+\ze"

79. Escape Problem Characters

Even in verbatim (\V) mode, patterns still have some characters that must be escaped: the / character when searching forward with the / command, the ? character when searching backward with the ? command, and the \ in both.

A practical use case is to do a verbatim search for the string contained in a register. If that string contains any of these characters, then it will need to be escaped. Vim can do this automatically with the expression register and the escape() function: /\V<C-r>=escape(@u, '/?\')<CR> (see tip 87 for a way to automate this).

80. Meet the Search Command

From normal mode, / initiates a forward search, ? initiates a backward search, n repeats the search in the same direction, and N repeats the search in the opposite direction. gn and gN create a visual selection of the matched text in the corresponding direction.

81. Highlight Search Matches

The :h 'hlsearch' option will highlight all occurrences of the last search pattern. This is great for picking out occurrences in the text, but can be annoying when not needed. The :nohlsearch command (:noh for short) temporarily turns off hlsearch until the next search command. It’s very beneficial to create a shortcut in vimrc for doing so:

nnoremap <silent> <C-l> :<C-u>nohlsearch<CR><C-l>

This builds on the <C-l> command to redraw the screen by removing search highlights.

82. Preview the First Match Before Execution

When at the / or ? pattern prompt, the :h 'incsearch' option jumps the view forward (or backward) to the first match and highlights it. This provides instant feedback for what the pattern is going to match. The cursor will not jump to the match until <CR> is pressed. Pressing <Esc> will leave the cursor at its original location and return the view to where it was before.

Even though the cursor is technically at its original position, the <C-r><C-w> command can be used to autocomplete the word under the highlighted incsearch match. This has unexpected behavior when doing a pattern search because it inserts the whole word instead of inserting the remainder of the word.

83. Offset the Cursor to the End of a Search Match

Vim positions the cursor on the first character of a match by default. The e flag placed after the terminating search character (e.g., /word/e or ?word?e) will place the cursor at the end of the match instead of at the beginning.

84. Operate on a Complete Search Match

The gn and gN commands, if used by themselves, create a visual selection of the next match in the corresponding direction (forward or backward). They can also be used as motions or text objects with operators. For example, gUgn will uppercase the next search match, dgn will delete the next match`, etc.

Using gn or gN is a big improvement over the dot formula since . is the only keystroke necessary to operate on successive potential changes.

85. Create Complex Patterns by Iterating upon Search History

Search history can be traversed like a shell with <Up> and <Down> at the search prompt and as an editable buffer (that executes when <CR> is pressed over a line) with the q/ and q? windows. This allows patterns to be edited iteratively, hopefully improving with each iteration.

When the search pattern is finished, it can be used easily with the substitute command by automatically recalling the last search pattern: :s//replace. This is much better than trying to get everything right in one shot.

86. Count the Matches for the Current Pattern

The substitute command can be used to count the number of occurrences: :%s///gn. The n flag suppresses the “replace” behavior and will echo the count in the command line.

:vimgrep can also be used to count occurrences, even across multiple files: :vimgrep //g % will operate on the current file, but the % can be replaced with a list of files or glob. This also populates the quickfix list that can be traversed to inspect each match.

87. Search for the Current Visual Selection

By default, the * command in normal mode acts as a motion to the beginning of the next occurrence of the word under the cursor. This is seldom useful, but populating the search pattern with the current visual selection is often more useful. Placing the following snippet in vimrc will do so:

xnoremap * :<C-u>call <SID>VSetSearch('/')<CR>/<C-R>=@/<CR><CR>
xnoremap # :<C-u call <SID>VSetSearch('?')<CR>?<C-R>=@/<CR><CR>

function! s:VSetSearch(cmdtype)
  let temp = @s
  norm! gv"sy
  let @/ = '\V' . substitute(escape(@s, a:cmdtype.'\'), '\n', '\\n', 'g')
  let @s = temp
endfunction

Substitution

88. Meet the Substitute Command

The basic syntax of the command is :[range]s/{pattern}/{replacement}/[flags]. The range and pattern inputs are the same as have been discussed in tips 28 and 73–79, respectively. The replacement string is taken literally except for the following special character sequences:

The flags can be one or more of the following:

89. Find and Replace Every Match in a File

:substitute replaces the first match on the current line by default. To expand this scope, we can provide a range to operate on more than just the current line and/or set the g global flag to replace all occurrences, not just the first per line.

To replace every match in a file, use the % range to apply to every line and the g flag to replace every occurrence on each line: :%s/{pattern}/{replacement}/g.

90. Eyeball Each Substitution

To confirm a substitution at each occurrence instead of doing so blindly, use the c flag: e.g., :%s/{pattern}/{replacement}/gc. When prompted for confirmation, we can perform one of the following actions:

91. Reuse the Last Search Pattern

If the {pattern} is omitted from the substitute command (i.e., :[range]s//{replacement}/[flags]), then the previously used search pattern is taken instead. Note that the substitute command is saved as-is in the command history: that is, without the pattern. If the substitute command is likely to be repeated from history in the future, it might be best to insert the pattern with <C-r>/.

92. Replace with the Contents of a Register

If the replacement value is already in a register, the value can be pasted in with <C-r>{register} or referenced with \=@{register} in the replacement string. For example, suppose the replacement text is in register "r. Then both of the following would work: :%s//<C-r>r/g and :%s//\=@r/g. Be careful when using the unnamed ("") or yank ("0) registers since they are overwritten frequently. Also, if using the <C-r>{register} method, beware of characters that need to be escaped in the replacement string.

93. Repeat the Previous Substitute Command

Each part of a substitute command has a means of reuse:

Combined, the following command simply re-executes the last used substitution for the current line: :s//~/&.

Alternatively, the following command re-executes the last used substitution over the entire file: :%s//~/&. The g& normal mode command does just this.

To modify the range, use :[range]&&: the synonymous :& and :s ex commands repeat the last substitute command (except for the flags), and the trailing & appends the previous flags. The g& command above could also be described as a shorthand for :%&&.

The & normal mode command is the same as calling :& or :s, so the flags are omitted. To “fix” this, it might be beneficial to add the following lines to vimrc:

nnoremap & :&&<CR>
xnoremap & :&&<CR>

The :~ ex command calls substitute combining the last used search pattern with the previous replacement value (and no flags).

94. Rearrange CSV Fields Using Submatches

Use parentheses to create submatches within a pattern, then use \1, \2, etc. in the replacement string to repeat each numbered submatch. The fields of a three-field CSV could be reversed with the following command(s):

/\v^([^,]*),([^,]*),([^,]*)$
:%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:

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:

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:

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:

113. Work with the Autocomplete Pop-Up Menu

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

<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:

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):

setlocal spellfile += ~/path/to/jargon.utf-8.add

With more than one file in spellfile, prefixing zg with a count will save that word to the indexed file (1zg for the first/default, 2zg for the second, and so on).

123. Fix Spelling Errors from Insert Mode

In insert mode, use <C-x>s to scan backwards for spelling errors. This opens a special autocomplete pop-up with suggestions. Unfortunately, this changes the cursor position.

List of Tips

  1. Meet the Dot Command
  2. Don’t Repeat Yourself
  3. Take One Step Back, Then Three Forward
  4. Act, Repeat, Reverse
  5. Find and Replace by Hand
  6. Meet the Dot Formula
  7. Pause with Your Brush Off the Page
  8. Chunk Your Undos
  9. Compose Repeatable Changes
  10. Use Counts to Do Simple Arithmetic
  11. Don’t Count If You Can Repeat
  12. Combine and Conquer
  13. Make Corrections Instantly from Insert Mode
  14. Get Back to Normal Mode
  15. Paste from a Register Without Leaving Insert Mode
  16. Do Back-Of-The-Envelope Calculations in Place
  17. Insert Unusual Characters by Character Code
  18. Insert Unusual Characters by Digraph
  19. Overwrite Existing Text with Replace Mode
  20. Grok Visual Mode
  21. Define a Visual Selection
  22. Repeat Line-Wise Visual Commands
  23. Prefer Operator Commands to Visual Commands Where Possible
  24. Edit Tabular Data with Visual-Block Mode
  25. Change Columns of Text
  26. Append After a Ragged Visual Block
  27. Meet Vim’s Command Line
  28. Execute a Command on One or More Consecutive Lines
  29. Duplicate or Move Lines Using :t and :m Commands
  30. Run Normal Mode Commands Across a Range
  31. Repeat the Last Ex Command
  32. Tab-Complete Your Ex Commands
  33. Insert the Current Word at the Command Prompt
  34. Recall Commands from History
  35. Run Commands in the Shell
  36. Run Multiple Ex Commands as a Batch
  37. Track Open Files with the Buffer List
  38. Group Buffers into a Collection with the Argument List
  39. Manage Hidden Files
  40. Divide Your Workspace into Split Windows
  41. Organize Your Window Layouts with Tab Pages
  42. Open a File by Its Filepath using :edit
  43. Open a File by Its Filename Using :find
  44. Explore the File System with netrw
  45. Save Files to Nonexistent Directories
  46. Save a File as the Super User
  47. Keep Your Fingers on the Home Row
  48. Distinguish Between Real Lines and Display Lines
  49. Move Word-Wise
  50. Find by Character
  51. Search to Navigate
  52. Trace Your Selection with Precision Text Objects
  53. Delete Around, or Change Inside
  54. Mark Your Place and Snap Back to It
  55. Jump Between Matching Parentheses
  56. Traverse the Jump List
  57. Traverse the Change List
  58. Jump to the Filename Under the Cursor
  59. Snap Between Files Using Global Marks
  60. Delete, Yank, and Put with Vim’s Unnamed Register
  61. Grok Vim’s Registers
  62. Replace a Visual Selection with a Register
  63. Paste from a Register
  64. Interact with the System Clipboard
  65. Record and Execute a Macro
  66. Normalize, Strike, Abort
  67. Play Back with a Count
  68. Repeat a Change on Contiguous Lines
  69. Append Commands to a Macro
  70. Act Upon a Collection of Files
  71. Evaluate an Iterator to Number Items in a List
  72. Edit the Contents of a Macro
  73. Tune the Case Sensitivity of Search Patterns
  74. Use the \v Pattern Switch for Regex Searches
  75. Use the \V Literal Switch for Verbatim Searches
  76. Use Parentheses to Capture Submatches
  77. Stake the Boundaries of a Word
  78. Stake the Boundaries of a Match
  79. Escape Problem Characters
  80. Meet the Search Command
  81. Highlight Search Matches
  82. Preview the First Match Before Execution
  83. Offset the Cursor to the End of a Search Match
  84. Operate on a Complete Search Match
  85. Create Complex Patterns by Iterating upon Search History
  86. Count the Matches for the Current Pattern
  87. Search for the Current Visual Selection
  88. Meet the Substitute Command
  89. Find and Replace Every Match in a File
  90. Eyeball Each Substitution
  91. Reuse the Last Search Pattern
  92. Replace with the Contents of a Register
  93. Repeat the Previous Substitute Command
  94. Rearrange CSV Fields Using Submatches
  95. Perform Arithmetic on the Replacement
  96. Swap Two or More Words
  97. Find and Replace Across Multiple Files
  98. Meet the Global Command
  99. Delete Lines Containing a Pattern
  100. Collect TODO Items in a Register
  101. Alphabetize the Properties of Each Rule in a CSS File
  102. Meet ctags
  103. Configure Vim to Work with ctags
  104. Navigate Keyword Definitions with Vim’s Tag Navigation Commands
  105. Compile Code Without Leaving Vim
  106. Browse the Quickfix List
  107. Recall Results from a Previous Quickfix List
  108. Customize the External Compiler
  109. Call grep Without Leaving Vim
  110. Customize the grep Program
  111. Grep with Vim’s Internal Search Engine
  112. Meet Vim’s Keyword Autocompletion
  113. Work with the Autocomplete Pop-Up Menu
  114. Understand the Source of Keywords
  115. Autocomplete Words from the Dictionary
  116. Autocomplete Entire Lines
  117. Autocomplete Sequences of Words
  118. Autocomplete Filenames
  119. Autocomplete with Context Awareness
  120. Spell Check Your Work
  121. Use Alternate Spelling Dictionaries
  122. Add Words to the Spell File
  123. Fix Spelling Errors from Insert Mode