Choosing a text editor is intensely personal; it’s all about preference. This post isn’t meant to persuade you that vim is better than other text editors. Instead, view this post as a practical guide for getting started with vim if you decide that you want to give it a try.
As background, I’ve tried a lot of text editors. In college, I used emacs for my CS courses. And later, I switched to TextMate and then Sublime v2 and v3 during the long TextMate v2 release cycle. With friends trying to convince me to try VS Code, I decided to give vim another try instead. The goal of this post is help you to start feeling productive using vim. I’m not a vim expert, but understanding the commands described below has helped me understand why people get so excited about vim.
I started by completing the vim adventures game, which piqued
my interested. I was surprised by how much faster I could move by avoiding the
arrows on my keyboard. The game does a great job of making the process of
learning a new way of thinking about text fun and engaging. Next I read through
vimtutor
and this high level tutorial on how to get
started with vim, both of which helped me see how to do most of the things I
took for granted when using emacs. But even with these resources, it was hard
to internalize such a different way of interacting with text. I wish someone
would have shown me this cheatsheet and this poster
earlier. Both were valuable resources that helped me to avoid the temptation of
going back to one of the other text editors that I’m more familiar with.
It’s true that the vim docs are surprisingly detailed and clear when you type
:help
, but I was looking for a more structured approach to my learning than
people just telling me to RTFM. So, that’s what I’ve tried to put
together here. This is far from comprehensive, but it should be enough to help
you feel comfortable with the basics and help you understand what makes vim
different from other text editors.
Let’s get started. I’d recommend starting by using macvim, so you can still use the mouse and other operating system shortcuts. As you get more comfortable, I’d recommend transitioning to using vim directly in the terminal so that your experience is the same when you’re using vim on your local machine and when using it over ssh, but don’t feel a need to rush that.
For this tutorial, I’ll use the following notation:
<C-w>
is equivalent to pressing control
and w
at the same time.diw
is equivalent to typing d
then i
then w
.<ESC>
is equivalent to pressing escape
.In vim there are 4 main modes that I use:
<ESC>
.v
- typical text selectionV
- select one line at a time<C-v>
- select one column at a time:
.$ vim FILE
to open a file from the commandline.:e FILE
. This will open the file
if it exists and if it doesn’t, it will create a file with that name.:w
. This will write the changes to disk.:q!
or ZQ
. If this is the
last file that you have open in vim, it will also close vim.:x
, :wq
, or ZZ
.:edit
Now that you have a basic understanding of how to open and close vim, I’ll explain how to get started in four parts. First, we’ll go over basic navigation, then we’ll go over how to arrange your workspace, how to manipulate text, and finally how to install plugins.
This is the end of Part 0 on concepts and notation.
To get started, you need to know how to move the cursor in normal mode. This is
well covered in the vim adventures and in :h navigation
.
h
= LEFT one characterj
= DOWN one linek
= UP one linel
= RIGHT one characterw
= beginning of the next wordW
= beginning of the next WORDb
= beginning of the previous wordB
= beginning of the previous WORDe
= end of the wordE
= end of the WORD0
= beginning of the line^
= first non-whitespace character on the line$
= end of the line:N
or NG
= go to line number Ngg
= go to line 1G
= go to the last line of the filefx
= move the cursor forward until it finds x
tx
= move the cursor forward up to the character before x
Fx
= move the cursor backward until it finds x
Tx
= move the cursor backward up to the character before x
/PATTERN
= forward search for a regex pattern?PATTERN
= backward search for a regex patternn
= move the cursor to the next search resultN
= move the cursor to the previous search result:noh
to remove the highlighted search results<C-d>
= scroll up a half screen. You can remember this because “d” is for
“down”.<C-u>
= scroll down a half screen. You can remember this because “u” is for
“up”.<C-e>
= scroll down by one line.<C-y>
= scroll up by one line.zz
= position the line that the cursor is on in middle of the screen.zt
= position the line that the cursor is on at the top of the screen. You
can remember this because “t” is for “top”.zb
= position the line that the cursor is on at the bottom of the screen.
You can remember this because “b” is for “bottom”.H
= position the cursor on the top most visible line on the screen. You can
remember this because “H” is for “high”.M
= position the cursor on the middle visible line on the screen. You can
remember this because “M” is for “middle”.L
= position the cursor on the bottom most visible line on the screen. You
can remember this because “L” is for “low”.i
= switch to insert mode before the cursorI
= switch to insert mode before the beginning of the linea
= switch to insert mode after the cursorA
= switch to insert mode after the end of the lineo
= insert a line below the cursor and enter insert modeO
= insert a line above the cursor and enter insert modeThis is the end of Part 1 on basic navigation.
To make the most of normal mode in vim, you need to compose operators
and
motions
. In general, motions
are what we discussed above, but there are a
couple more useful ones that I’ll share once we’ve covered the common
operators
.
[operator] [count] [motion]
Before learning about operators
, let’s look at who we can use this with the
motions
we already know. If I type 3j
, vim will interpret this as jjj
, in
other words moving down three lines. Similarly, if I type 5w
, vim will move
forward 5 words. And to move forward to the second “x”, I would type 2fx
. At
this point, I had my first “aha!” moment. Even with just this amount of
knowledge under my belt, I was able to move around text files much faster than
before.
Operators can be thought of as verbs in language that describes how you
want to edit text. For more information go to :h operator
.
d
= delete, which is also a version of cutting texty
= yank, which is a more powerful version of copying textc
= change, which deletes the text from the motion and puts you into insert
mode.Now that you know about operators, you can combine them to uncover the power of
normal mode. For example, to delete 3 words, you would type d3w
. But, if
you’re combining operators with motions, there are two more types of motions
at your disposal.
iw
= inner word, so diw
would delete the word that the cursor is on.aw
= a word, which includes the surrounding whitespace, so daw
would
delete the word that the cursor is on and the surrounding whitespace.This type of motion can be used with words, brackets, parenthesis, quotes,
etc… So you could type ci"
to change the text between two "
marks,
assuming that the cursor in the text between the quotes, or yi(
to yank the
text inside a pair of parentheses. Once I started to get comfortable with this,
I started to understand why people get obsessive about learning vim.
At this point in my learning, I could quickly move around a document, but I couldn’t move text around. Vim has a more advanced version of copy and paste in that you can have many registers that can store text. In other words, you’re not constrained to a single clipboard like you are in a typical text editor. But, to get you started here’s how you can accomplish the familiar version of copy and paste.
yy
or Y
= yank the current line, which is like a powerful version of
“copy”dd
= delete / cut the current linep
= paste afterP
= paste beforey
to copy
or d
to delete / cut.r
= will replace the character that the cursor is on with the next
character that’s pressed and then return to normal mode. This is particularly
useful when fixing typos.x
= delete the current character while staying in normal modeC
= will delete the rest of the line and put you into insert modeD
= will delete the rest of the line and keep you in normal modes
= will delete the current character and place you into insert modeS
= will delete the current line and place you into insert mode<C-n>
and <C-p>
in insert mode will provide a dropdown of autocomplete
options. <C-n>
moves you to the next selection and <C-p>
moves you to the
previous selection. Without further configuration the dropdown is based on
the words that are already present in the file that is being edited.gd
= highlights all instances of the word under the cursor. You can move
between them by pressing n
and p
. This is particularly helpful when
looking for function definitions.gf
= follows the path that the cursor is on. When looking at a series of
include statements, this allows you to quickly open the relevant dependency.This is the end of Part 2 on making changes.
A buffer is the in-memory text of a file.
A window is a viewport on a buffer.
A tab page is a collection of windows.
As described in the vim docs :h window
, these are the three main concepts
that need to be understood to arrange your workspace.
Vim allows you to open multiple files at a time, each being put into its own buffer. Before I understood how to work with buffers, I would quit vim each time I needed to work on a different file, which was highly inefficient. Even though I could move around files faster than I had been able to before, the benefits didn’t seem worth it.
:e FILE
= open a file into a new buffer - we discussed this command before:ls
= list all of the open buffers:bn
= switches to the next buffer:3b
= switch to buffer number 3:sp
= split the current window horizontally:vs
= split the current window vertically<C-w>
+ direction hjkl
= to move to the next pane<C-w> =
= make the windows equally high and wide<C-w> o
= close all other windows except for the current one on the pageYou can use tabs like in other text editors (e.g. Sublime). To learn more about
how to reorder tabs, check out :h tabmove
.
:tabnew FILE
= create a new tab by opening the following file:tabc
= close the current tabgt
= go to the next tabgT
= go to the previous tabThis is the end of Part 3 on arranging your workspace.
gU
followed by a motion = will capitalize every letter in that motion. For
example, gU$
would capitalize every letter until the end of the line.gu
followed by a motion = will make every letter in that motion lower case.~
= will change the case of the current letter.<<
and >>
= will shift the current line by a shiftwidth while in normal
mode.<C-t>
and <C-d>
= will shift the current line by a shiftwidth while in
insert mode.Like the kill ring in emacs, vim allows users to hold
multiple strings of text in registers to be used later. There are registers
for every character on the keyboard, but a couple of them have special
properties. For more info, read :h registers
, but the basics are:
"xyy
= to copy the current line into the x
register"xp
= to paste from the x
register:reg
= to see the contents of each of the registers<C-r>
+ k
= to paste the contents of a register k
while in insert modeMacros allow you to program an arbitrary sequence of keystrokes that you can repeat whenever you’d like, allowing you to repeat complicated text manipulations on multiple lines of text in quick succession. Since macros are just recorded keystrokes, you can make revisions to the macro and then store it back into the same register.
qk
+ arbitrary keystrokes + q
= record a macro in register k
@k
= play back the macro stored in register k
For me, macros are one of the key features that sets vim apart. Because they’re so quick and easy to write, I use them regularly, allowing me to accurately refactor code and make what would otherwise be tedious changes without mistakes.
.
= repeat the previous command. This includes commands that are of the
“operator count motion” variety or a macro. This is what allows you to make
lots of changes in quick succession. To learn more about this, go to :h
single-repeat
.This is a great way to avoid having to type long words and to automatically
correct common misspellings in vim. To learn more about this read :h
abbreviations
.
:ab hh hello
= expand “hh” into “hello” when typing in insert mode:una hh
= remove the “hh” as an abbreviation:abc
= clear all abbreviations:ab
= list all of the current abbreviations<C-v>
before typing an abbreviation in insert mode and vim will
ignore the abbreviation expansion, allowing you to type “hh” without it
expanding to “hello”Marks allow you to quickly move the cursor back to a specified location. Lower
case letters are used for marks that are local to a particular file, while
capitalized letters are used for global marks. For more information go to :h
mark-motions
.
mk
= locally set the mark k
to the current location in the current filemK
= globally set the mark K
to the current location in the current file,
making it easy to switch back and forth between files`k
= go to mark k
'k
= go to the first non-whitespace character on the line containing the
mark k
One of the harder parts of transitioning to vim has been getting used to the
fact that there isn’t a built-in command for commenting multiple lines of text
like CMD+/
l in TextMate or Sublime. Here’s how I
comment out multiple lines of code in a language like Ruby.
#
).<C-v>
to switch into visual modeI
to switch into insert mode#
<ESC>
to return to normal modeTo uncomment multiple lines of code I use a similar process:
<C-v>
to switch into visual modex
to delete the selected characters and return to normal modeThis works well for many languages, but is a pain when trying to comment code in languages like HTML/XML that require opening and closing tags. There are vim plugins to make this process easier, but this is the best solution I’ve found for plain vim.
It was a pleasant surprise for me to learn that I can use shell commands to edit text in vim. For example, if I want to sort an unordered list into alphabetical order, I can do the following:
V
and
then move the cursor until the desired lines are highlighted!
followed by the shell command to execute a shell command with the
selected lines as an input. In this example, I would type ! sort
When editing markdown files, it’s nice to be able to check that there aren’t any spelling errors. To do this, you can use the following:
:set spell
= to highlight words that are spelled incorrectly:set nospell
= disable spellcheck]s
= move to the next misspelled word[s
= move to the previous misspelled wordz=
= when on top of a misspelled word, this shows the possible correctionszg
= to add the word under the cursor to the dictionary. You can remember
this because “g” stands for “good”.zw
= to remove a word from the dictionary. You can remember this because
“w” stands for “wrong”.To learn more about spell check in vim, read :h spell
.
<C-d>
while in commandline mode to show the possible autocomplete
commandsThis is the end of Part 4 on manipulating text.
For those who are unfamiliar, you specify your vim customizations in a file
called .vimrc
that you put in your home directory. While I’m still far from
an expert on how to customize vim, I have made some modifications that have
eased my transition process and saved me from unnecessary keystrokes. For
convenience, I keep my vimrc on github, so it’s the same on every
computer and server I use. Instead of just copying mine, I’d recommend building
your own from scratch. The process will help you to solidify your understanding
of how vim works.
There are three main things that I do in my vimrc.
set hlsearch
to highlight all of the search
results.inoremap <C-e> <esc>$a
to add some of my emacs
muscle memory to insert mode.Be patient as you build your vimrc; it’s a highly iterative process that’ll never really be finished. I’d recommend asking others what they’ve put in theirs and searching through github for sample vimrc files. It’s a great way to learn.
Once you’ve established certain settings like your textwidth
, you can make
use of commands like gq
, which reformats your text to fit within a specified
number of columns. I used to grumble about how tedious it is to make text fit
within the 79 character limit to comply with the team styleguide, but with this
command, it’s just a matter of a few keystrokes.
This is the end of Part 5 on my vimrc.
Like with other text editors, vim has a vibrant community of plugins. These range from easier methods of file navigations (e.g. NERDTree, and Ctrl-p) to colorschemes to syntax highlighting. As with building your vimrc, I’d recommend adding them slowly, instead of adding them all at once. To manage the process of installing, updating, and removing plugins, I’d recommend that you use a plugin manager. I happened to settle on Vundle, but there are others (e.g. Pathogen, Plug, and NeoBundle) that I’m sure work just as well. Each allows you to define the plugins you want to use in your vimrc file.
As with many things on the internet, there’s basically a plugin for anything you can imagine. Before you spend too long customizing your vimrc, check that a plugin doesn’t already exist. I often add a new plugin when I’m starting to work on a programming project in a new programming language so I can pick up syntax highlighting. For example, after installing typescript-vim and tsuquyomi, getting started with typescript was pretty painless.
This is the end of Part 6 on installing plugins.
I hope that this post has helped you understand how to think about vim and given you an overview of the things you’ll need to learn to start feeling productive using it. Be patient; the learning curve is pretty steep. While I still have a long way to go, I feel like the effort has been worth it. If you have suggestions for things I can clarify or things that I should add, please get in touch. Happy hacking.