You can combine these operators with motions and counts (:h cursor-motions) to apply them to specific bits of text.

// motions
w - move to beginning of next word
b - move backwards to beginning of previous word
e - move to end of next word
ge - move backwards to the end of previous word
0 - move to beginning of the line
$ - move to the end of the line
etc...
// text objects
aw - around a word
iw - inside a word
etc...

A complete command will follow a pattern like this:

{operator}{count}{motion}

or

{count}{operator}{motion}

For instance:

dw - delete a word

cw - change a word

d2w - delete 2 words

cta - change until the next occurrence of the letter a (non inclusive)

Search

f - find next occurrence of character in current line (mnemonic find)

F - find previous occurrence of character in current line

t - find next occurrence of character in current line and place cursor before it (mnemonic till or until)

T - find previous occurrence of character in current line and place cursor after it

; - repeat last f,t,F,T commands

, - repeat last f,t,F,T commands in the opposite direction

/{pattern} - search forward for occurence of pattern

?{pattern} - search backward for occurence of pattern

n and N work with / and ? as ; and , above

* - go to next occurrence of pattern under cursor (repeat search)

# - go to previous occurrence of pattern (repeat search)

Notice how near the repeating commands are (;, . and ,), and how # and * are symmetric and correspond to the middle finger in each hand.

Replace

:%s/foo/bar/g replaces foo for bar in the whole document

&: repeats last substitution

File Navigation

:e# - go to previous buffer

:e#n - go to buffer number n (where n=1,2,3...)

gf - go to file (when the cursor is on top of a file)

CTRL+O - go back

:buffer - list buffers

Visual mode

Visual mode allows you to select bits of text and perform operations on them.

v - go into character-wise visual mode

V - go into line-wise visual mode

C-v - go into block-wise visual mode

When in visual mode you’ll move one of the ends of the selection while the other one remains fixed. In order to be able to change either end you can type o to change the current end you’re moving.

The Vim Way

Vim is optimized for repetition. Take this into account when editing and you’ll be that much efficient:

Use the . command to repeat the last change

Use the ;, ,, *, # commands to repeat motions

Use the @: to repeat Ex commands

Use the & to repeat substitution (:h :substitute)

Remove extraneous, unnecessary movement (f.i. use I instead of 0i or A instead of $a)

Use compound commands that leave you directly in insert mode instead of separate commands (f.i. use cw instead of dwi or C instead of d$i)

Attempt to make changes repeatable

The dot command (.) lets us repeat the last change. It is the most powerful and versatile command in vim.
From Practical Vim

What is a Change?

A change in Vim is any complete action that results in a text change when you are in normal mode (f.i. `d2w`) and all keystrokes when in insert mode until you go back to normal mode. (f.i. `cwhello`)

How to Configure and Customize Vim

You normally configure vim by adding configuration commands inside the .vimrc file which typically lives in ~/.vimrc. This file is loaded when you run vim and is where you want to place information such as the plugins you want to load, color schemes you want to you and custom key bindings that represent the personal way you use vim.

Key Mappings

Vim lets you define your own key mappings and change existing ones to your heart’s content. This is a powerful way to optimize the way that you write code and be more productive when using vim.

Vim offers two commands that let you create and modify mappings in different ways: map and noremap. You can use map to map a key sequence to any other key sequence or command:

map tab

The difference between map and noremap is that, the first one allows for recursive mappings whilst the second one (noremap - no recursive mappings) doesn’t. A recursive mapping means that vim will continue scanning the result of a mapping and seeing whether there are other mappings that correspond with this result. A non recursive mapping means that vim won’t scan the result of these mappings and will use vim’s default meaning of the result. For instance:

" map E to B, B is recursively mapped to G, go to the end of a file
map E B
noremap B G
" G maps to gg, go to the top of a file" This mapping doesn't affect the mappings above" because the second mapping is a no recursive mapping, that is," it will not be scanned for more mappings recursivelynoremap G gg

This is a list of all mapping commands:

map {lhs} {rhs}: Maps the key sequence {lhs} to {rhs} for the modes where the map command applies. The result, including {rhs}, is then further scanned for mappings. This allows for nested and recursive use of mappings.

noremap {lhs} {rhs}: As above but it disallows the mapping of {rhs}, to avoid nested and recursive mappings. Often used to redefine a command.

nnoremap {lhs} {rhs} - same but only normal mode and so on for inoremap, vnoremap, etc

unmap {lhs}: Remove mapping of {lhs} for the modes where the command applies

mapclear: Remove ALL mappings for the mode where the map command applies

map: List all key mappings for the modes where the map applies

map {lhs}: List the key mappings for the key sequence starting with {lhs} in the modes that apply

Note that you can prepend modes to these commands above to make the command apply to a specific mode. For instance, nmap applies to normal mode, imap applies to insert mode and so on.

You can use special characters in mappings with added functionality:

<Plug> - you may have seen some mapping including <Plug>. <Plug> allows plugin authors to make it easier for users of their plugin to map funcionality to new key-bindings. It allows you to temporarily bind <Plug>SomeAction to an action and then let the user map whichever sequence to that binding nnoremap wop <Plug>SomeAction

Vim plugin authors and other vim users usually have their vimrc (and other dotfiles) open to the public. That’s a great place to draw inspiration from. For example here’s Tim Pope’s, Shougo’s and noopkat. Just go into github and search for dotfiles, then find the .vimrc or init.vim for neovim.

vim-bootstrap.com can generate a vim configuration based on the type of development that you use. This can be helpful for finding useful plugins or mappings.

vimawesome.com is a huge repository of vim plugins. Just search by a keyword of interest and you’ll be able to find loads of plugins that can solve that problem you’re interested in.

Having a more comfortable leader key

The <Leader> key in vim allows for additional custom mappings in a convenient way by providing another modifier key (like CTRL, SHIFT, etc) that you can use in combination with other keys.

By default the <Leader> is assigned to \\ which can be slightly inconvenient since it is quite far for your right pinkie finger. If that is the case, consider remapping it to another key. By far the most common custom mapping for the <Leader> key is , but I find more <space> to be more convenient (it’s always under my right thumb) and less intrussive (as it doesn’t shadow any common vim binding that I know of). To remap <Leader> to <space> add this to your .vimrc:

let mapleader="\<Space>"

Now whenever you define new bindings like this one:

nnoremap <leader><space>:noh<cr>

You can use <space> as your leader. In this case typing <space> twice will clear all highlighted text which you’ll typically want to do after a search.

Custom Navigation

You can add these mappings to be able to move faster than with the normal jk commands:

nmap J 5j
nmap K 5k

This lets you move up and down in a fine grained fashion with kj and also move faster by using KJ just by keeping SHIFT pressed.

There’s a caveat which is that this removes the default :join mapping to join lines which is pretty handy (particularly when writing markdown). You can remap this using your <Leader> key which will make joining lines more convenient:

nnoremap <Leader>j J

By default j and k will move up a line. However, if there is text that it is wrapped (that is, when the text is too long for the width of the window), then j and k will bring you up and down the complete line without taking into account wrapped lines. This is very unintuitive behavior and veeeery irritating. By default, vim offers additional mappings gj and gk to go down and up a “visual line”, that is, taking into account wrapped lines. You can add these mappings to your vim configuration to remap j to gj, etc and have a more intuitive default behavior:

nnoremap j gj
nnoremap k gk
nnoremap 0 g0
nnoremap ^ g^
nnoremap $ g$

Moving between windows (or buffers):

nmap gh <C-w>h
nmap gj <C-w>j
nmap gk <C-w>k
nmap gl <C-w>l

Moving between tabs:

nmap <C-l> gt
nmap <C-h> gT

Mappings To Experiment With

" using ; as : from http://stevelosh.com/blog/2010/09/coming-home-to-vim/" that way you avoid the need to type two letters everytime you want to" access command mode." It's slightly irritating that you'll lose forward searches though
nnoremap ;:" You can escape with <ESC> C-C or C-[ but the one below is much quicker" Quicker escaping from http://stevelosh.com/blog/2010/09/coming-home-to-vim/
inoremap jj <ESC>" This doesn't work in visual mode. But in that case C-C is pretty ok

Markdown

If you don’t see syntax highlighting inside fenced code blocks you may need to install a specific plugin that provides syntax highlighting for that specific language. For instance, elm-vim

Miscellaneous tips

Run vim With Factory Settings

To run with with factory settings use the -u option to point vim to the following configuration file (vim -u factory.vimrc):

# factory.vimrc
set notcompatible
filetype plugin on

or alternatively run vim -u NONE -N (the -N sets notcompatible) and then run :filetype plugin on manually once vim is opened.

Count words

To find the number of words in the whole document type g and then C-g

It also works with a selection (if you select some text first)

You can use externals programs as well :w !wc

For more info :h word-count

Spellchecking

Select language :set spelllang=en

Enable current session :set spell

Enable current buffer :setlocal spell

]s to move to the next misspelled word

[s to move backwards

zg to add word under cursor as a good word

zb to add word under cursor as a bad word

z= to get suggestions for bad words (awesome!!)

You can use counts to 2zg set two words as good words, or 1z= select the first suggestion for a bad word

You can run autocorrection within insert mode by running C-x and then s (also C-xC-s). The cool thing about this one is that you don’t need to have the cursor on top of the word for it to work. You can run it at the end of a line while you’re typing and suddenly realize you made a mistake

You can set multiple spellfiles to save your own custom words based on the context or on the project you’re working on :set spellfile+={path}/{filename}.{encoding}.add

Recovering Fleeting Error Messages When Starting Vim

If you ever run into fleeting error messages on startup try any of these:

Using the :messages command which shows all warnings, errors, and informational messages that have ever appeared in the vim statusline. (:h messages)

The :echo errmsg command prints the most recent error message.

Use g< to see the last page of previous command output. Find out more here :h g<.

Showing messages in vim

Alternatively, you can use :echom which shows a message just like :echo and it also saves it in the history so that it can be later accessed via :messages.

Inserting Unicode Characters in Vim

You can insert unicode characters in vim using the unicode character code by typijng: <C-V>u{code}. This is super helpful when you want to insert unicode code characters for icon fonts to make your vim experience be nicer.

Interesting Tips from Vim’s Help

Jump to a subject: Position the cursor on a tag (e.g. |bars|) and hit CTRL-]. Use CTRL-T or CTRL-O to come back to the original position

Getting Specific Help With Context

It is possible to go directly to whatever you want help on, by giving an argument to the |:help| command. It is possible to further specify the context:

Would you like to receive more articles like this one on programming, web development, JavaScript, Angular, developer productivity, tools, UX and even exclusive content like free versions of my books in your mailbox? Then sign up to my super duper awesome inner circle.

Did Ya Know I've Written Some Books?

I have! The JavaScript-mancy series is the lovechild of three of my passions: JavaScript, writing and Fantasy. In the pages of each one of the books of the series you’ll find a breadth of JavaScript knowledge, delivered with a humorous and casual style of writing and sprinkled with Fantasy at every turn.

They are the weirdest and quirkiest JavaScript books you'll ever find. There's nothing out there quite like it.