Vim annoyances

Like any highly interactive application, Vim has a few annoyances even for experienced users. Most of these consist of the editor doing something unexpected, particularly with motions or the behavior of regular expressions and registers. This is often due to vi and Vim being such venerable editors; their defaults sometimes make less sense decades after their creation.

Fortunately, Vim being the configurable editor that it is, many of the more common annoyances can be easily worked around. Bear in mind that not all of these are necessarily problems; if you actually prefer the way something behaves, you should stick with it.

Cursor jumps around while joining lines

If you want to keep the cursor in place when you join lines with J, you can do this, dropping a mark before the operation to which you return afterwards:

nnoremap J mzJ`z

Jumping lands on top or bottom of screen

If you’d like to center the window automatically around the cursor after jumping to a location with motions like n (next search pattern occurrence) or } (end of next paragraph), you can arrange that by remapping to add a zz after the motion:

nnoremap n nzz
nnoremap } }zz

If you don’t need the jump to land you in the exact middle of the screen, but just don’t want it to land right at the edge, you could also use scrolloff:

set scrolloff=10

Note that this also starts scrolling the window with single-line movements like j and k at this boundary, too, which you may not want.

Skipping lines when wrap is set

By default, the j and k keys don’t move by row; they move by line. This means that if you have the wrap option set, you might skip across several rows to reach the same point in an adjacent line.

This can be frustrating if you prefer the more intuitive behavior of moving up to the character immediately above the current one. If you don’t like this behavior, you can fix it by mapping j to gj, and k to gk, which moves by rows rather than lines:

nnoremap j gj
nnoremap k gk

If you think you might need the default behavior at some point, you might want to include reverse mappings so you can move linewise with gj and gk:

nnoremap gj j
nnoremap gk k

Wrapping breaks words

By default, setting wrap displays lines by breaking words if necessary. You can force it to preserve words instead by only breaking at certain characters:

set linebreak

You can define the characters at which Vim should be allowed to break lines with the breakat option. By default this includes spaces and tabs.

Backup files are a nuisance

If you’re developing with a version control system, you might find the in-place backups Vim keeps for saved files with the ~ suffix more annoying than useful. You can turn them off completely with nobackup:

set nobackup

Alternatively, you can set a single directory for them to keep them out of the way with backupdir:

set backupdir=~/.vim/backup

Swap files are a nuisance

Swap files can be similarly annoying, and unnecessary on systems with a lot of memory. If you don’t need them, you can turn them off completely:

set noswapfile

If you do find the swap files useful but want to prevent them cluttering your current directory, you can set a directory for them with directory:

set directory=~/.vim/swap

Accidentally hitting unwanted keys in normal mode

Some of the keys in normal mode bring up functions that aren’t terribly useful to a lot of people, and tend to accidentally get hit when Caps Lock is on, or when aiming for another key. Common nuisance keys are:

  • F1 for help; :help is generally more useful for the experienced user
  • Q to start ex mode; annoying when you intended to start recording a macro with q
  • K to bring up a man page for the word under the cursor; annoying when you’re not writing in C or shell script, and there isn’t a sensible choice of keywordprg for your chosen language

The simplest way to deal with these is to remap them to <nop> so that they don’t do anything:

nnoremap <F1> <nop>
nnoremap Q <nop>
nnoremap K <nop>

Startup message is irritating

If you don’t like the startup message that appears when you open Vim without a filename, you can remove it by adding the I flag to shortmess:

set shortmess+=I

Can’t backspace past start of operation

If you’re in insert mode, by default you can’t use backspace to delete text past the start of the insert operation; that is, you can’t backspace over where you first pressed insert. This is old vi behavior, and if you don’t like it, you can make backspace work everywhere instead:

set backspace=indent,eol,start

Flashing screen is annoying

If you don’t require the error feedback, you can turn off the flashing screen for the “visual bell”:

set visualbell t_vb=

Don’t know what mode I’m in

If you lose track of the current mode, you can get a convenient --INSERT-- indicator at the bottom of the screen with:

set showmode

If you’re having this problem a lot, however, you might want to take stock of how much time you’re spending in insert mode when you’re not actively typing; it’s good Vim practice to stay out of it otherwise, even when you stop to think.

Keep making typos of common commands

If you’re fat-fingering :wq and similar commands a lot due to a sticky shift key, take a look at the Vim command typos fix. Also, don’t forget about ZZ and ZQ as quicker alternatives to :wq and :q!.

Don’t want case sensitive patterns

If you don’t care for case-sensitive searches and substitutions, you can turn it off completely:

set ignorecase

You might find the slightly cleverer behavior of smartcase is better, though. This option only applies case sensitivity if at least one of the letters in the pattern is uppercase; otherwise, case is ignored.

set smartcase

Doesn’t replace all occurrences

The default behavior for the substitute operation, :s/pattern/replacement/, is to replace only the first occurrence of the pattern. To make it replace all occurrences on the appropriate lines, you add the g suffix. If you find that you never need to substitute for only the first occurrence of a pattern in a line, you can add that flag to the patterns by default:

set gdefault

If you do happen to need to replace only the first occurrence one day, you can get the default behavior back by adding the g suffix to your pattern; its meaning is reversed by this option.

Can’t move into blank space in visual block mode

If you need to define a block in visual block mode with bounds outside the actual text (that is, past the end of lines), you can allow this with:

set virtualedit=block

This will let you move around the screen freely while in visual block mode to define your selections. As an example, this can make selecting the contents of the last column in a formatted table much easier.

Filename completion on command line is confusing

If you’re used to the behavior of shell autocomplete functions for completing filenames, you can emulate it in Vim’s command mode:

set wildmode=longest,list

With this set, the first Tab press (or whatever your wildchar is set to) will expand a filename or command in command mode to the longest common string it can, and a second press will display a list of all possible completions above the command line.

Yanking lines is inconsistent

D deletes from the cursor to the end of the line; C changes from the cursor to the end of the line. For some reason, however, Y yanks the entire line, both before and after the cursor. If this inconsistency bothers you, you can fix it with a remapping:

nnoremap Y y$

New splits appear in unintuitive places

If your language of choice is read from left to right, you may find it annoying that by default Vim places new vertical splits to the left of the current pane, and horizontal splits above the current pane. You can fix both:

set splitbelow
set splitright

Caps Lock sends Vim crazy

Caps Lock in normal mode makes Vim go haywire. This isn’t really Vim’s fault; Caps Lock is generally a pretty useless key. It’s often useful for Vim users to remap it, so that it sends the same signal as a more useful key; Control and Escape are common choices. You might even find this reduces strain on your hands.

Several of these fixes were inspired by Steve Losh’s .vimrc file. Thanks also to commenters Alpha Chen and Rob Hoelz for suggestions.

17 thoughts on “Vim annoyances

  1. Instead of remapping n and } to center the screen, I like to use the scrolloff option to never have the cursor within 10 lines of the top or bottom of the screen.

  2. Hi there,

    A good list; the only one I would say I disagree with is turning off swap files. Swap files have saved me way more times than caused me problems; if they’re getting in the way of version control, you can always change where they’re stored via the directory option:

    set directory=/var/tmp
  3. Pingback: vim mappings for multiple files. | Linux and Photography Blog

  4. Pingback: Linux VI commands for beginners

  5. If you think you might need the default behavior at some point, you might want to include reverse mappings so you can move linewise with gj and gk

    Note that there is another pair of single-line move commands: <CR> (Enter) and -. They are equivalent to j^ and k^. I decided not to include reverse mappings for j and k in my .vimrc only because those commands are suitable alternatives. (I don’t mind the jump to the first non-blank character, because it’s hard to quickly predict which column the cursor would land on anyway when you move linewise past a wrapped line.)

    • How can you know that they are your top 5 didnt-realize-I-had-them vim annoyances? Maybe there are some more annoying ones, you just dont know about.

  6. This is a great list. I’ve been particularly annoyed by the behavior of Y and never seen the virtualedit=block trick. Very nice!

    I’ve also disabled the behavior of Q, but I’ve remapped it to this very useful keybinding that doesn’t exist elsewhere in vim: nnoremap Q ge

    This lets you hit Q to go to the end of the previous word.

Leave a Reply

Your email address will not be published. Required fields are marked *

You can use Markdown if you want.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>