Sane Vim Defaults

6 minute read


Assertions

I'm not a Vim evangelist. I'm apathetic toward the editor itself, and instead view Vim's keybindings as its edge. I'd actually argue the case for VSCode as the better out-of-the-box lightweight editing experience, and VSCode with Vim keybindings as a better text editor than native Vim or Neovim.

That said, while most of Vim's default keybindings are great, a select few aren't. Thankfully most inconsistencies have heretical remaps that I'd encourage even the purist Vim users give a chance.

Reference

All remaps mentioned are visible in my public dotfiles. For a Vimscript reference, go here and have a read through remaps_common.vim and remaps_nvim.vim. For those acquainted with Lua configuration in Neovim, go here.

Navigation

hjkl makes sense for arrow-key movements: each key is on or near the home row and vertical movements are under the strongest fingers. It wouldn't be unreasonable to expect vertical movements by paragraph to follow the same pattern. They don't - the defaults are { and }. These keys are at a distance from the home row, and their usage is delegated to the right pinky. The fix is simple:

noremap J }
noremap K {

Remapping K is no big deal, since all the original command did was run man on the word under the cursor. This is a feature that's rarely used. The second incurred cost is from remapping J. This originally joined lines, which is something most will not want to lose. We can both retain the functionality and honour the original mnemonic with M for merge lines:

noremap M J

The net cost is now the use of M to center the cursor in the middle of the screen. M as originally designed is a relatively unused feature with viable alternatives. It could be mapped to a less frequently used keybinding such as <leader>M, although the total loss of the functionality would is arguably still worth the improved movement by paragraphs regardless.

An added benefit is that { and } are freed up to be remapped. I remap them to pageup and pagedown:

noremap } <C-f>
noremap { <C-b>

Upholding consistency, movements to the BOL or EOL would be better imagined as extensions to horizontal movement by a single character:

noremap H ^
noremap ^ H
noremap L $
noremap $ L

Yank, Paste, Till and Replace

y is an awkward character key to reach, yet it's given an important role of yanking text. p isn't much better, being handled by the pinky if you type with 'correct' touch typing form, or the right ring finger if using the pinky isn't comfortable. The two keys are also often used in quick succession, an example being yyp to duplicate the current line.

On the flip side, both t and r can be comfortably reached by the left index finger. Given till and replace aren't quite as vital as yank and paste, they are good candidates for remapping. In the spirit of Vim's mnemonics, we can move yank to t for take, and paste to r for resolve:

noremap t y

noremap r p
noremap R P
noremap ]r ]p

You might have noticed noremap T Y is missing. This needs a special mention, because the default functionality assigned to Y is inconsistent. D deletes to EOL, A appends to EOL, C changes to EOL, and if you've adopted the navigation remaps earlier, H and L will move the cursor to BOL and EOL respectively. But by default, Y yanks the entire line irrespective of the cursor location.

There is no real reason for this. The use of Y to yank a line dates back to the first version of vi, released on January 1st, 1978. When you go this far back, you'll find that yy as an abbreviation for y applied to the entire line isn't featured. That's fine. The issue is that once yy was introduced, Y was never reassigned to align with the other shifted line-wise commands. Let's fix that by remapping T to yank (now take) to EOL:

noremap T y$

With these remaps in place, we need to move the original functionality for till and replace over to where yank and paste used to be. We can again try to maintain some resemblance of a mnemonic by using y for yet, and p for place:

noremap y t
noremap Y T

noremap p r
noremap P R

Extensions

The remaps that follow provide functionality you might assume Vim has by default, but doesn't. These aren't as heretical as those mentioned above, but they do alter the default keybindings.

Vim doesn't have a keybinding to clear the content of the line you're on, without deleting the line entirely. Easily fixed:

nnoremap X 0D

The cost here is the loss of normal mode backspace. But on that note, why was normal mode backspace mapped to X to begin with?

Every keyboard has a backspace key, so let's use it:

nnoremap <BS> X

Another missing feature is the insertion of newlines above or below the cursor, without entering normal mode as a side effect. Again, straightforward fix:

nnoremap <CR> o<Esc>
nnoremap <leader><CR> O<Esc>

In most software that allows freeform text input, pressing enter when text is selected will replace the text with a newline character. I don't think it's unreasonable to expect Vim to behave in a similar way.

Instead of replacing the text with a newline character, let's have <CR> delete the text and leave the cursor on the same line as the start of the original selection:

vnoremap <CR> d

By default, U will undo changes made only to the line under the cursor. This isn't very useful. With u as undo, U as redo makes more sense:

nnoremap U <C-r>

Conclusion

Along with the remaps above, there are other defaults worth a mention. S is a duplication of cc, Q is rarely used and is a good candidate for reassignment, and there aren't any undo breakpoints set for symbols that perhaps ought to be, such as ,, . and !.

Most heretical Vim remaps are just logical corrections and extensions of long-standing inconsistencies and missing features, and better yet, they be introduced with almost no net cost to core functionality.