Github light

Welcome to my Vim Tutorial!

How To Use this Tutorial

I’ve placed Javascript-simulated Vim boxes below each section so you can practice each new command. The only way you will remember all of these commands is to use them repeatedly, so spend some time playing and experimenting with each command you learn.

Check out the Manual

Vim comes with an incredibly detailed built in manual. Just type :help <command> to get all the information about a specific command. The manual will open in a horizontal split. Type :q<enter> to close the manual.

Learning the motions is the first step in mastering Vim. Motions specify a direction and a distance. When used alone they simply move the cursor. However, they can also be combined with actions, as we’ll see later.

Basic Motion

Let’s start with basic motions. Try these out:

h moves one character left

l moves one character right

j moves one character down (think “jump down”)

k moves one character up (think “kick it up”)

You can hold these keys down to keep moving.

You can get around a file with just h, j, k, and l, but it’s not very efficient. Lets go over a few ways to get around faster.

Speedy Motion

} moves one paragraph down

{ moves one paragraph up

Now we’re screaming! } and { are great for getting around methods and functions quickly.

Scrolling

Ctrl-u scrolls up (think “u for up”)

Ctrl-d scrolls down (think “d for down”)

You might want to consider changing your Caps Lock key to Control. If you use Vim, having easy access to Control will be much more valuable to you than having a Caps Lock key. In Mac OS X you can do this by going to System Preferences > Keyboard > Modifier Keys.

Top / Bottom of File

gg takes you to the top of the file

G takes you to the bottom of the file

Line Motion

^ moves you to the first character in a line

0 moves you to the beginning of the entire line (think “0 is the beginning”)

$ moves you to the end of the line (think “the buck stops here”)

Word Motion

w, e, and b are good for crusing through words.

w moves you to the first character of the next word (w for word)

e moves you to the last character of the next word (e for end)

b moves you to the first character of the previous word (b for beginning)

You can capitalize any of these motions and they will skip across special characters. For example, E will skip across parentheses, whereas e will stop at each special character.

Precise motion with f and t

The things I’ve shown you so far are great, but you would still have to use h or l to get to a specific character if it’s not at the beginning or end of the word. That can add up to a lot of keystrokes. That’s where f and t come in.

f is for find

f<character> moves you to the next occurrence of <character> in your current line (think “f is find”)

You can go to the next and previous occurences of the character you searched for:

; moves to the next occurrence

, moves to the previous occurrence

t is for till

t is like f, but it takes you up till the character you search for.

t<character> moves you to the spot immediately before the next occurrence of <character> (think “t is till”)

f and t are some of the most useful motions. You’ll see their true power once we combine them with actions in future chapters.

Motions Wrap Up

The main goal with Vim motions is to get to your desired location with the fewest keystrokes possible. Knowing all of these motions will help you.

Vim has multiple modes. Keys do different things in different modes. The mode you’re in when you’re just moving around is called Normal Mode. To insert new text you’ll need to switch into Insert Mode.

Undo / Redo

Before we start modifying text, you should know these two things:

u is undo

Ctrl-r is redo

Now you can undo any craziness that occurs. Just hold u until you’re back to where you started.

Basic Insert

i switches you into insert mode at the cursor

a puts you in insert mode one space after the cursor

escape puts you back in Normal Mode.

Advanced Insert

The neat thing about Insert Mode is that there are many ways to get into it, each of which will put you in Insert Mode and move you to the right spot to insert code.

I puts you in insert mode at the beginning of a line

A puts you in insert mode at the end of a line

o puts you in insert mode on a new line (think “open”)

O puts you in insert mode on a new line above your current line.

Alternate Escape Routes

If you find your pinky getting tired of hitting escape you can use one of these instead:

Ctrl-c

Ctrl-[

Actions are the verbs of Vim – they actually do things. They can be combined with motions to get the exact result you want. Delete is the first action I’ll show you.

Basic Actions

x deletes the character under the cursor

Delete

While x is good for simple character deletions, what if you need to delete more than that? Use d instead:

d<motion> will delete text covered by <motion>

Examples:

dw deletes a word

db deletes to the beginning of the word

d$ deletes to the the end of the line

d0 deletes to the beginning of the line.

Delete with t and f

d is works really well with t and f.

df<character> will delete everything from the cursor to (and including) the first occurence of that character

dt<character> will delete everything from the cursor till the first occurence of that character

Prepending a Count

dd will delete the current line

You can prepend a count to this command to repeat it on multiple lines:

<count>dd will delete <count> lines

2dd or 3dd can remove a paragraph, but you’re probably better off using a text object for that, which we’ll cover shortly.

Delete to End of Line

D will delete from your cursor’s location to the end of the line. It’s a handy shortcut for d$.

The change action functions exactly the same as delete but with one major difference: it puts you in Insert Mode after doing the delete. This is helpful when you want to delete text then immediately start adding new text.

Basic Usage

c<motion> will change the text specified by that motion.

Examples:

cw changes a word.

c$ changes to the end of a line

c0 changes to the beginning of a line

Change to End of Line

C will change text to the end of the current line

Use Change with t and f

ct<character> changes up till that character

cf<character> changes up to (and including) that character

Basic Usage

Text objects are Vim’s representation of groups of text.

These are some of the text objects you’ll use the most:

w represents a word

s represents a sentence

p represents a paragraph

You specify how you want an action to be applied with a or i:

a means all, and the action will be applied to the text object and succeeding white space

i means in, and the action will be applied only to the text

You can use text objects with the following pattern:

<action><specifier><text object>

Examples:

dap will delete an entire paragraph

ciw will change a word

String-based Text objects

You can also use delimiters to specify text objects.

Available delimiters:

"

'

) or (

] or [

} or {

Examples:

ci" Change inside closest double quote

ci' Change inside closest single quote

ci) Change inside closest parentheses

ci] Change inside closest brackets

ci} Change inside closest braces

Note that if you do ca) instead of ci) then the parentheses will be deleted.

Replace and substitute are two additional actions.

Replace

r<character> will replace the character under cursor with the new character. It keeps you in Normal Mode.

R puts you in Replace Mode. In Replace Mode anything you type will overwrite what’s currently on the line.

You can hit escape to exit replace mode.

Substitute

s will delete the character under cursor then place you in insert mode so you can continue typing.

S will delete the text on the current line and place you in insert mode at the beginning of the line.

I use S whenver I need to change an entire line and I’m not at the beginning of that line. The neat thing about S is that it respects tab alignment. It’s essentially ^c$ combined into one command.

Ex Commands

Ex commands are commands you type after typing :. If you hit : then start typing you will see your text appear on the command line. You can hit enter to execute a command or escape to get out.

Substitute Ex Command

:%s/old/new/g will replace “old” with “new” everywhere in your current file.

The g stands for global.

Add c to the end to be prompted before making each change. This is great for search and replace where you need to check each match and choose whether or not to make the replacement.

:%s/old/new/gc

Basic Usage

Search is an invaluable tool that’s very easy to use in Vim.

Hit / and you will see / appear in the tray at the bottom of Vim. Start typing what you are searching for, then hit enter to go to the first match.

/<string> will search for next occurrences of that string.

?<string> will search for previous occurrences that string.

enter takes you to the first match.

Cycle through matches:

n go to next match

N go to previous match

A Primer on Options

You can turn an option on like this:

:set <option>

Some options are boolean. To turn them off, type:

:set no<option>

Other options take a parameter:

:set <option>=<parameter>

You can inquire about the current state of an option:

:set <option>?

Search Options

There are two options that I recomend you turn on for searching.

First, set search to ignore the case of characters.

:set ignorecase, or :set ic

Second, turn on “smartcase”. If you type in a search pattern that is all lowercase then smartcase will show both lower and uppercase matches. However, if you type a single uppercase character then smartcase will become case sensitive.

:set smartcase

Smartcase gives you the best of both worlds. You don’t have to type uppercase characters when casually searching, but if you need to find a specific constant or class name, which typically has an uppercase character, you can weed out all the lowercase matches by typing with the actual case.

Unfortunately, both of these settings default to off. You can put them in your vimrc file so that you don’t have to type them every time you start Vim. We’ll cover vimrc’s in a later chapter.

Search with *

* will search for the word under the cursor. You can still use n and N to cycle through the results.

Yank and Put

Vim’s yank and put are like copy and paste.

Basic Yank

y<motion> will yank that specified text.

yy will yank the entire line (much like dd)

Examples:

yw yank word

y$ yank to end of line

2yy yank the next 2 lines

yt. yank till .

yfg yank to next occurrence of g

Basic Put

p paste the last yank after the cursor

P paste the last yank before the cursor

Pasting with Registers

Vim keeps track of all the things you have recently deleted in the “register”. Delete a few things, they type :reg to see the register. You will see output like the following:

--- Registers ---
""   the most recent deleted OR yanked text
"0   the most recent yanked text
"1   the second most recent deleted text
"2   the third most recent deleted text
...

The first register, the " register, is called the unnamed register. It contains your most recent delete or yank. If you yank something, then delete something else then this register will be overwritten by the delete.

This can create problems because you could yank something, intending to paste it elsewhere, then delete some text along the way, type p expecting to paste what you yanked, and – whoops – instead, you see what you deleted.

The solution to this is the 0 register. The 0 register will contain your last yank and it won’t be overwritten by any deletions.

To put from the 0 register, type "0p .

Now that’s a lot of characters and the 0 key is all the way in the upper right of the keyboard. That’s the kind of thing that deserves a custom mapping. We can make on like so:

:noremap gp "0p

This will make gp always put from the 0 register. I’ll be covering mappings in a later chapter, just know that if you feel like something is annoying in Vim you can usually make a mapping that fixes it.

Pasting From Insert Mode

Ctrl-r " will paste from the unnamed register while in Insert Mode

Crtl-r 0 will paste from the 0 register while in Insert Mode

There are three types of selections you can make in Vim: visual, visual line, and visual block. Selections are a core feature that you’ll probably come to love.

Visual Selection

Press v to activate visual selection mode, then use motions to expand the selected area.

Once you are in a visual selection you can perform operations on the selected text.

d or x to delete the selected text

c to change the selected text

y to yank the selected text

You could perform any of these actions without doing a selection, but doing the selection allows you to see exactly what text you are about to modify.

You can press o while in a visual selection to move the cursor to the other side of the selection box. This allows you to expand the selection in the other direction.

Visual Line

Press Shift-v to active visual line selection. You can use motions to expand the area of the selection.

You can then use the same commands as a visual selection to modify the text. Visual line is great when you need to to move, delete or yank multiple lines.

Remember that if you need to delete or yank a paragraph (paragraph means all the lines are touching) then dap and yap can be faster than doing a visual line selection.

Visual Block

Press Ctrl-v to activate visual block selection. Visual block is unique because you can select characters across columns.

Use visual-block mode to fixup similar looking text on multiple lines.

Consider this text:

htis is a typo

htis is a typo

htis is a typo

htis is a typo

You could use visual block to highlight the “ht” in the first line, then hit 3j, type c, then th, then . This would fix the typo on all of the lines.

The standard selection commands all work with visual block.

You also press I to insert new text. At first you will only see your new text on the first line. Hit escape to exit Insert Mode, then you will see the new text inserted on every line.

Substitute Across a Selection

Once you’ve made a visual selection of any kind you can use the substitute command to make a substitution across the selected text. Here’s how:

  1. Make a visual selection

  2. Press :. You will see <,'> appear in the command line.

  3. Type s/old/new/g and hit enter to make your substitution.

Saving

To save your changes to a file type :w and hit enter. The w stands for write.

Quitting

To quit out of a file, type :q.

If you’ve made changes without saving then Vim will give you the error: “No write since last change.”

If you want to ignore your changes and not write the file type :q! to get out of the file.

If you want to save your changes and quit, type :w, then :q. This can be abbreviated into :wq or :x.

Opening a File and Splits

:e <file> will open the file in your current window.

:sp <file>, will open the file in a horizontal split.

:vs <file>, will open the file in a vertical split.

You can open as many splits as you want.

To switch from one split to another type Ctrl-w <direction>. Direction can be h, j, k, or l.

To move the arrangement of a split, type Ctrl-w <direction>.

Tabs

Tabs are visible across the top of the screen.

:tabe <file> will open a file in a new tab.

gt will take you to the next tab.

gT will take you to the previous tab.

Opening a Directory

:e <path/to/directory> will open a directory

:e . will open the current directory

While in the directory view use j and k to move up and down file names, and enter to open the file or directory under the cursor.

Renaming a File

Vim has trouble doing this by itself. It has a :saveas command, but this won’t remove the previously named file.

Tim Pope wrote plugin called Eunuch which will handle renaming with the :Rename command. I will cover plugins in a later chapter.

You should never have to repeat yourself while using Vim.

Here are a few ways to save keystrokes.

Dot Operator

. will repeat your last command.

The last command will be everything that happened from when you last entered Insert Mode to when you exited it. The . command will also remember how you got into Insert Mode.

Say you want to remove the last character of every line. You could do:

A<backspace><escape>

Then hit j to go to the next line, and hit .. It will remove the last character of the line regardless of where you start on the line because you used A.

The dot operator can also be played across a visual selection by making a selection, then typing :norm .. The norm stands for normal mode, which is the mode you want the command to be executed in.

Macros

Macros are a neat and often underused feature of Vim. A macro is a recording of your keystrokes that can be replayed. Here’s how to use them:

  1. Press qq to start recording
  2. Press q again to stop recording
  3. Type :@q to play your macro on your current line

Macros can also be played across a visual selection with :norm @q.

One trick with macros is to make 0 the first key you record. This will place your cursor at the beginning of the line, helping standardize the way the macro will be played. This is important because your macro will always use the current cursor location as it’s starting point, so you often need to press 0 or ^ to first to consistently get the correct result.

Custom Mappings

Vim allows you to map any keystroke to any other keystroke. For example:

:map x :echo 'hi'<cr>

If you type that then hit x you will see hi printed on the command line. We don’t want to keep this mapping, so let’s get rid of it.

:unmap x

When mapping commands you should almost always prefix the mapping with nore, which stands for non-recursive. This means that the mapping will look to the true vim commands for the sequence instead of looking at any other vim mappings. This prevents any unwanted recursion or unexpected consequences from mapping commands. A typical mapping will look like this:

:noremap <keystroke to map> <keystroke to use>

If you try :noremap x p, you’ll see that x will will do a put. However, if you enter Insert Mode then type x you will see x, not p. That’s because mappings default to Normal Mode only. If you want to make a mapping specifically for Insert Mode, you would have to do this:

:inoremap <keystroke to map> <keystroke to use>

The same goes for visual mode:

:vnoremap <keystroke to map> <keystroke to use>

In summary we have:

:noremap

:inoremap

:vnoremap

And corresponding unmap commands:

:unmap

:iunmap

:vunmap

Note that modifier keys have their own representations:

<cr> for enter

<s> for shift

<c> for control

<esc> for escape

<leader> for \

To make a mapping that requires a modifier to be held down at the same time as another key, use a dash. For example, to map Ctrl-l to Ctrl-l + w you would do this:

:noremap <c-l> <c-w>l

Map Something to Nothing

If you are want to change your habits in Vim, one of the best things you can do is map the key you don’t want to use to <NOP>. This stands for “no operation”, and it will make the key do nothing.

Let’s say you want to try to use Ctrl-c intead of escape. This mapping will help you greatly:

:noremap <esc> <NOP>

Vimrc

Vim will automatically look for and load a .vimrc file in your home directory when it starts. Your vimrc file is a great place to put your personal settings and mappings.

Officially, vimrc files are written in what’s called Vimscript. But you don’t need to know any real Vimscript to make a useful vimrc. Just take any ex commands, like :set ic, and place them in the file without the colon.

An example vimrc file might look like this:

" ~/.vimrc
set number
set ignorecase
set smartcase

Here are some things I keep in my vimrc that I use all the time:

" \s is much faster than :w enter
nnoremap <leader>s :w<cr>
inoremap <leader>s <esc>:w<cr>

" same thing goes for \q
noremap <leader>q :q<cr>

" who has time to press w each time they want to change splits?
noremap <c-l> <c-w>l
noremap <c-h> <c-w>h
noremap <c-j> <c-w>j
noremap <c-k> <c-w>k

" this is much faster than typing :set paste, then :set nopaste
set pastetoggle=<leader>z

I turned my vimrc into a plugin called vim-quickdraw. You can check it out at https://github.com/vicramon/vim-quickdraw.

If you end up creating a bunch of personal mappings and settings then I suggest that you put your vimrc into a plugin that’s under version control. That way it wil be portable, sharable, and harder to lose.

You have to like the look of your terminal if you’re going to be in it all day. Vim comes with quite a few color schemes. To see them:

  1. Type :colo
  2. Hit tab. You will see a list of available color schemes.
  3. Type the name of the color scheme you want to try, then hit enter.

I am a color scheme fanatic, but I eventually settled on two color schemes that I like the most.

Solarized

Solarized is a low contrast color scheme that’s really easy on your eyes. It’s one of the most popular color schemes for Vim, and for good reason. It has a blue-green background that might seem odd at first, but becomes really pleasant once you spend some time with it.

here: https://github.com/altercation/vim-colors-solarized

Molokai

Molokai has a dark background and vibrant colors. It’s my second favorite after Solarized.

https://github.com/tomasr/molokai

Installing Color Schemes

To install a new color scheme just grab the .vim file that represents it and save it to ~/.vim/colors/.

Others

Some other popular color schemes are Railscasts, Badwolf, Vividchalk, Codeschool, and Pyte.

Here’s an overview of some of the most popular Vim plugins.

Pathogen

Pathogen is a plugin manager for Vim. It automatically sources all of the files that come with a plugin.

Once you have Pathogen installed, simply put your plugins in ~/.vim/bundle to have them sourced.

https://github.com/tpope/vim-pathogen

SuperTab

SuperTab is a great plugin for text completion. Vim comes with text completion built in, but SuperTab is much more intuitive – you simply press tab to autocomplete.

https://github.com/ervandew/supertab

Vim Surround

Vim Surround provides mappings to easily add, modify, or delete characters that surround words like (, [, ', and ". This comes in handy all the time when writing code.

https://github.com/tpope/vim-surround

Eunuch

Eunuch.vim provides useful ex commands for Vim like :Remove and :Move.

https://github.com/tpope/vim-eunuch

Rails Vim

If you’re writing Rails apps with Vim then Rails Vim is indispensable. It provides ex commands to help you quickly open the right file from anywhere within your app, among many other features.

https://github.com/tpope/vim-rails

Vim Airline

Vim Airline makes your status line more useful. For example it changes colors depending on what mode you are in. It’s also highly configurable.

https://github.com/bling/vim-airline

Tmux

Tmux isn’t a Vim plugin, but it needs mentioning because it works so well with Vim.

Tmux is a terminal multiplexer, meaning that it allows you to have multiple terminal sessions running in one terminal window. It provides keystroke mappings to open, close, and cycle through terminal windows. I highly recommend checking it out if you want to improve your virtual workspace.

Tmux, like Vim, is highly configurable. Between Tmux and Vim, you may never need to use your mouse again while coding.

http://tmux.sourceforge.net

There are many resources out there to help you learn and master Vim. Here are some of my favorites:

The book Practical Vim, by Drew Neil is truly great. I think it’s required reading if you really want to improve your Vim-fu. Drew also does screencasts at http://www.vimcasts.org.

If you want to learn more about Vimscript check out Learn Vimscript the Hard Way, by Steve Losh. It’s a great resource for anyone that wants to write Vim plugins.

I wrote a flashcard-style learning program for Vim called Vim Genius. You can play it for free at http://www.vimgenius.com.

http://vim.wikia.com has quite a bit of information. You will surely come across this site if you do any Googling about Vim.

Here is a great image of a keyboard overlaid with all the Vim commands and their actions: http://www.viemu.com/vi-vim-cheat-sheet.gif

And of course there’s always StackOverflow, and your old buddy :help.

Congratulations on making it to the end of this tutorial. You will surely be a better Vimmer if you took the time to play with all of the commands.

Please tweet your feedback to @vicramon or post suggestions on the GitHub repo.

Happy Vimming!