Vim Tips & Tricks
As a long-term Vim user myself, here are some of my favourite tips n’ tricks that I have picked up along the journey.
Note, by no means is this an exclusive list, many of these tips will be well known to the Vim community at large. However, even the most seasoned of Vim users can sometimes learn a trick or two from posts like this.
Quite a few of these tips n’ tricks are baked into my vimrc.
I encourage Vim users to enable relative line numbering. This setting makes it easy to figure out how many lines up or down you have to jump, via j and k movements, to get to where you want to go when in normal mode.
One time normal mode command whilst in insert mode
Whilst in insert mode you can quickly execute a single normal operation with:
When the normal mode command has completed you will be returned back to insert mode where you were last editing.
A useful example would be centering the text being edited in the current window:
Expression register in insert mode
Use the expression register, whilst in insert mode, to edit-in simple math values.
Control-r= <<math expression>>
An example could be:
Control-r= 43 + 139 + 761
The inserted value would be 943.
Set global replacement as the default
Force Vim to always do global substitutions.
This removes the need to tack on g to the end of substitute commands.
gdefault is set the following will be a global substitute command:
All the following substitute examples will assume
gdefault has been set.
Substitute in a visual block
Do the following to substitute old with new only within a rectangular
visual block, that being a
Control-v style visual selection:
Count the number of pattern matches
substitute command to count the number of matches for a particular
First, execute a search:
Then execute a counting substitute:
Note, this particular form of substitute will not actually substitute anything, it will instead just print out the number of matches.
UPDATE: In the comments Smylers suggested this even more compact variant:
sort command to sort a selection, say a visual selection:
By default lines starting with 0-9 will be sorted before A-Z followed lastly by lines starting with a-z.
i option to ignore case when sorting, more often than not you want to
! to reverse the sort:
u option can be used to remove duplicates much like the uniq
Project wide substitution using cfdo
Historically it has been awkward to carry out multi-file substitutions in
Vim. Many possibilities exist, some involving
argo, others involving
sed, but all are convoluted and none are elegant.
cfdo command is ideal for substituting, or refactoring in programmer
speak, across multiple files. The
cfdo command allows a normal mode command,
such as a substitute, to be invoked only on the files in the quickfix list.
cfdo is only available in relatively recent versions of Vim or Neovim.
Please upgrade to Vim 8 or the newest version of Neovim.
To carry out a
cfdo substitute one must first populate the quickfix list
with a candidate set of files containing the term wanting to be refactored.
:vimgrep oldterm **
Or using the excellent ripgrep utility via the vim-grepper plugin:
:GrepperRg -i oldterm
From there one simply executes the desired substitution over the list of files in the quickfix list.
Using standard Vim substitution:
:cfdo %s/oldterm/newterm/ | update
Or using Tim Pope’s superb case-smart Abolish plugin:
:cfdo %S/oldterm/newterm/ | update
Change word under cursor and dot repeat
nnoremap c* *Ncgn nnoremap c# #NcgN
The relatively new
gn command allows for easy operation on the next match
of a completed search. These
c# mappings make use of
gn to provide
easy word-under-cursor changing, aka in-file refactoring. Best of all simply
. (dot) to repeat that change for the next match instead of
n. as has
usually been necessary in Vim when doing such changes.
Complete a line with Control-x Control-l
Sometimes in insert mode you may wish to repeat an existing full line; omni line completion is up to the task:
The above is a little difficult to type, I prefer to use the following mapping:
inoremap <C-l> <C-x><C-l>
One only need type Control-l whilst in insert mode to complete the current line by repeating an existing line.
Dictionary complete current word with Control-x Control-k
Complete the current word with omni dictionary completion:
This requires that the
dictionary option be set, for Unix-based systems I
The above is a little difficult to type, I prefer to use the following mapping:
inoremap <C-k> <C-x><C-k>
One only need type Control-k whilst in insert mode to complete the current word by using dictionary-based completion.
Repeat last visual selection with gv
gv to reselect the last visual selection.
Launch browser with gx command
Launch a browser window by moving the cursor, in normal mode, into a URL text
area and simply enter the
gx command. I only recently came across this nice
tip, I wish I knew this one years ago!
Delete all lines containing pattern
Use the global command with the delete option to remove all lines that contain the desired pattern.
Delete all lines not containing pattern
Use the vglobal command to achieve the opposite effect, that is to delete all lines not containing the pattern:
Vim as a sed replacement
A Vim script file can be used as a poor man’s sed replacement.
Create a file with the desired operations. For example this file, do.vim, will substitute new for old:
Then use the -es option of Vim to execute the Vim script.
This example will execute the above do.vim script over all Ruby files in the current directory tree:
vim -es $(find . -name '*.rb') < do.vim
Better wrapping with breakindent
The relatively new
breakindent indent option is an excellent way to wrap
long code lines. When set, long lines will wrap with an indentation thus
preserving the clean indented look of code.
Note, a very modern version of Vim, and Neovim, will be required. All the more reason to upgrade!
Set the following options to wrap long lines with indentation:
set breakindent set showbreak=\\\\\
Smarter j and k navigation
When any form of wrapping is in effect, I recommend
breakindent as noted
above, then it is natural to convert the j and k movement commands from
strict linewise movements to onscreen display line movements via the gj and
gk commands. However when preceded with a count, useful when
relativenumber is in effect, then we want to go back to strict linewise
The following mapping achieves both aims, display line movements unless preceded by a count:
nnoremap <expr> j v:count ? 'j' : 'gj' nnoremap <expr> k v:count ? 'k' : 'gk'
UPDATE: In the comments p1xelHer0 suggested this enhancement:
nnoremap <expr> j v:count ? (v:count > 5 ? "m'" . v:count : '') . 'j' : 'gj' nnoremap <expr> k v:count ? (v:count > 5 ? "m'" . v:count : '') . 'k' : 'gk'
Similar to the first version except this version will automatically save
movements larger than 5 lines to the jumplist. Use
navigate backwards and forwards through the jumplist. Yes, a nice
enhancement, thanks p1xelHer0.
Most folks set
ignorecase when searching. However that option does not play
nicely with completion which will then completely ignore case. Set the
infercase option for smarter completions that will be case aware:
Improve performance for files with long lines
Very long lines will cause performance problems with Vim. One of the main culprits for this performance issue is the syntax highlighter. I recommend only syntax highlighting the first 200 characters of each line.
relativenumber settings can also cause problems with files with long
lines. I suggest having a quick toggle to disable
Enable wildmenu and wildmode
wildmenu option makes setting an option, or opening new files via
breeze with TAB expansion.
I recommend these options.
set wildmenu set wildmode=full
For example, once set you can quickly tab complete an option via:
The TAB invocation will then list the available options in the status line,
use TAB again to quickly scroll through the options (left and right arrows
also work). Note, when opening a file via
:e use up and down arrows to
enter or leave directories.
Make dot work over visual line selections
By default the . repeat operator does not work on visual selections.
Add this mapping in your vimrc file to enable a simple form of dot repetition over visual line selections.
xnoremap . :norm.<CR>
It is recommended that only simple operations that start from the beginning of
a line be dot repeated. For example
ct= (change up until =) or
(delete the first five words of the line) are good candidates for visual dot
Execute a macro over visual line selections
Somewhat related to the previous tip is having the ability to run a macro only over a visual line selection.
I use the
xnoremap Q :'<,'>:normal @q<CR>
Q with a visual line selection in effect will execute the
over just the selected lines.
Automatically equalize splits when Vim is resized
It is an annoyance to have to manually equalize Vim splits that have been munged by some type of resize event, for example zooming in and out a tmux pane.
autocmd will take care of split equalization for you:
autocmd VimResized * wincmd =
Add the following snippet to your vimrc to enable functional autoread behaviour in terminal Vim:
set autoread augroup autoRead autocmd! autocmd CursorHold * silent! checktime augroup END
Autoread will automatically update an open buffer if it has been changed outside the current edit session, usually by an external program.
A natural companion for this tip is the autosaving vim-auto_save plugin. For more details please refer to the appropriate section of the Vim Plugins I Like post.
Recompute syntax highlighting
nnoremap <silent> <leader>s :syntax sync fromstart<CR> autocmd FileType markdown syntax sync fromstart
This mapping is used to force a full syntax recompute for the current buffer.
By default, syntax highlighting is calculated only for the visible set of lines
and a variable amount of lines surrounding that visible set. However, sometimes
when large navigation jumps are done the syntax highlighting can get jumbled
up. The mapping above,
<leader>s in my case, will
syntax sync the
complete buffer, this will fix any syntax highlight errors caused by large
Separately, the above
autocmd is used to always force a full file syntax
computation when opening Markdown files. In my experience Markdown files
are just about the likeliest to have their syntax broken by large navigation