Vim is a command line text editor.
“command line” means you use it inside your terminal.
“text editor” means it allows you to write and edit text files (primarily code files for our purposes).
It does not have the standard graphical interface one might associate with other text editors like Sublime Text, Atom or Visual Studio Code. Important to note that it is NOT an integrated development environment (IDE) like Xcode, Visual Studio or IntelliJ (Atom & Visual Studio Code blur the line here by including some features often associated with IDEs). By default Vim does not come with features like code completion, refactoring, build tools or a debugger out of the box. These features can be added through plugins (though we won’t get into how today).
One could come up with many reasons to use it but here are two things Vim provides that I find particularly compelling.
First, portability. Vim (or its predecessor Vi) are installed on nearly every computer you will ever work on. This doesn’t matter as much on your own laptop where you can install any text editor or IDE you’d like. On a remote server though, you can’t use these graphical application (and may not even have permission to install other applications you might want to use). Emacs has a similar level of portability (though not quite the same ubiquity).
Second, a language for editing. All text editors aside from Vim (at least as far as I am aware) directly insert characters when you hit letters or numbers on your keyboard and use keyboard shortcuts, e.g. Ctrl-c
, to manipulate text or take special actions. In contrast, Vim has modes, one of which allows you to directly enter characters while another (the default mode) takes your typing as actions to manipulate text. This may seem confusing or odd, I promise we’ll discuss it more in a little bit. As a sign of the popularity of this editing philosophy there are numerous plugins for IDEs, text editors and even web browsers that add Vim keybindings to transplant the paradigm.
Here are some other people’s longer form thoughts (obviously a biased representation, definitely recommend reading other people’s thoughts on why they use Emacs or competing editors if you’re considering switching to Vim full time):
Comes preinstalled with a non-current version. Recommend installing separately to ensure up to date versions. The easiest way to install is brew install vim
if you use Homebrew.
Preinstalled on most flavors. Can be installed through your package manager if not. sudo apt install vim
for Ubuntu & Debian bistros, sudo yum install vim
on Fedora & CentOS, and sudo pacman -S vim
on Arch.
If you are already using the Windows Subsystem for Linux (WSL) you can install Vim in that environment following the steps of the Linux heading above for whichever distro you’re using. If you don’t have WSL setup then ssh
into one of the lab machines using your CS credentials (not the same as your NetID credentials) to follow along there (they all have vim
preinstalled).
Officially, vim has 6 modes, we’ll focus on four of them for this tutorial (and honestly the last two are optional in my opinion, personally I rarely use them). Those four are insert
, normal
, visual
, and command-line
. We’ll discuss visual
mode a little bit later.
When you open Vim it starts in normal
mode. In this mode each key is a shortcut for some action and they can be combined to allow more complex actions. To enter insert
mode hit i
. Until you leave insert
mode, any key you hit will be inserted into the document like a normal text editor. Hit esc
or Ctrl-C
(Note: Ctrl-
is sometimes written C-
) to leave insert
mode and go back to normal
mode.
Type :
in normal
mode to activate the Vim command line. Here you can enter commands to take a range of actions, from simple to complex.
vim <filename>
- to launch Vim & open the specified file:e <filename>
- to open a file from Vim (this is using thecommand-line
mode mentioned in the previous section)
- If in
insert
mode, switch tonormal
mode by hittingesc
- Type
:
to activecommand-line
mode - Type one of the below sequences then hit
enter
. Example::wq<enter>
saves and quits the current file.w
(short forwrite
) to save the fileq
(short forquit
) to close the filewq
orx
to simultaneously save and exitq!
to exit without saving
There are many ways to enter insert
mode from normal
mode, here are a few:
i
-> enterinsert
mode before cursorI
entersinsert
mode at the start of the line
a
-> enterinsert
mode after cursorA
entersinsert
mode at the end of the line
o
-> create new line below current line, enterinsert
mode on new lineO
does the same, but inserts the new line above the cursor
Vim provides many ways of navigating a file. This allows someone with the right commands to jump just about anywhere with a single line. Today we’ll just look at the basics that will get you 90% of the way there.
Note: C-<key>
is shorthand for Ctrl+<key>
. You can hold down the keys to repeat the actions.
normal
orinsert
mode - arrow keys to move by character/line innormal
orinsert
modenormal
mode onlyh
,j
,k
, andl
to move left, down, up, and right, respectivelye
to move to the end of the current “word”,w
to move to the beginning of the next "word"$
to move to the end of the line,0
to move to the start of the line:<number>
to jump to a particular line. This is particularly helpful if you get an error compiling/running something that tells you the line it happened on - you can jump straight there./<pattern>
to search for all instances of the pattern. Usen
to jump to the next instance, andN
to jump to the previous instance. This will highlight all instances; use:noh
to get rid of that highlighting when you're done jumping. This is really helpful if you're looking for a particular variable/function name.
zz
center file around cursorC-d
andC-u
to jump the screen down and up respectively, by half the height of the screen, without moving the cursorC-e
andC-y
move the screen down and up respectively, by one line at a time, without moving the cursor
backspace
to delete text while ininsert
modedd
to delete the current line while innormal
modecc
to “cut” the current line (delete and enterinsert
mode) while innormal
mode
In normal
mode:
u
to undo the last operation (e.g.,ddu
deletes the current line, and then immediately undoes the delete)C-r
to redo (or undo an undo) (e.g.,ddu<C-r>
deletes the current line, undoes the delete, then redoes it)
In normal
mode hit y<motion>
to copy (yank) the current line. Hit p
(again in normal
mode) to paste the yanked
line after the cursor (in the case of whole lines this will paste on the next line). Hit P
to paste before the cursor (or the line above in the case of whole lines). Important to note that dd
and cc
both yank the current line as well, overwriting the copy buffer.
In normal
mode hit >>
to indent the current line once and <<
to unindent the current line once. This works regardless of your cursor’s location on the line.
Mentioned briefly earlier, visual mode is an editing mode that lets you visually select text. Hit v
to enter Visual Mode, or V
to enter Visual-Line Mode. As you move around in Visual Mode text will be highlighted, and then you can apply a key command to it.
For example, if you highlight some text/lines and hit d
, that selection will be deleted.
Vim find-and-replace is a command-line action. In general, it looks like: :%s/<find>/<replace>/<modifiers>
In this line, %s
is the command "find-and-replace on all lines", <find>
is the pattern you want to find, <replace>
is the text you want to replace it with, and <modifiers>
are keys that tweak the behavior of the find-and-replace.
Common modifiers include:
g
for "global" or "replace all instances within a line". Otherwise, it will only replace the first instance per line.c
, for "confirm" or "ask for confirmation before replacing an instance". When it prompts, usey
as "yes",n
as "no", andq
as "quit/stop replacing".
If you want to replace just on one line, or only in a visually selected block of text, leave off the %
at the beginning - :s/<find>/<replace>/<modifiers>
.
For example, to replace all instances of the text "hello" with the text "world" without asking for confirmation, the command would look like :%s/hello/world/g
.
This right here is the magic of Vim. This is why people refer to Vim as a language for editing text, not just a text editor.
Mastering most text editors involve memorizing various key combinations to perform complex actions. Vim has some of that, but for most of the core editing actions it focuses on composability which dramatically increases the range of actions you can keep in your head without a photographic memory.
First let’s briefly discuss each of operators
, motions
, and text objects
. All these explanations apply in normal
mode.
- Operators (think
d
ory
) are keys which perform an action liked
eleting ory
anking (copying)- A few operators to start with:
d
- deletey
- yankc
- cut (delete and enterinsert
mode)>
or<
- indent
- Operators can be hit twice to operate on the current line. E.g.,
dd
deletes the current line,<<
to unindent the current line.
- A few operators to start with:
- Motions (think
w
,j
or$
) are keys which move the cursor. For example byw
ord, down one line (j
), or to the end of the line ($
).- A few motions to start with:
e
- end of current wordw
- start of next wordh
,j
,k
, andl
- left, down, up, and right, respectively$
- end of line
- A few motions to start with:
- Text objects are keys which represent constructs like words (
iw
), sentences (as
), or inside quotes (i"
)- The default text objects (I say default because plugins can add more) of Vim generally fall in two categories, inner (
i<key>
) or a (a<key>
), as in “a sentence”. The distinction here usually has to do with whether or not the object includes surrounding white space and the surrounding character. E.g.,is
represents a sentence through the period (inclusive), whileas
represents a sentence through the space following the period (inclusive). Another example,i”
represents all characters within a pair of quotes, exclusive of the quotes themselves.a"
represents all characters and the quotes themselves. Try these out on some example text to get a better sense. - A few text objects to start with (all of these must be combined with
i
ora
forinner
ora
, e.g.,iw
for inner word, surrounding whitespace exclusive, andaw
fora word
, surrounding whitespace inclusive.w
- words
- sentencep
- paragraph(
or)
(and other similar characters -<
,{
,[
, etc.) - within or around innermost containing parens (or other character). E.g., if your cursor is within nested sets of parens it operates on the innermost set."
,'
- within or around innermost double or single quotes
- The default text objects (I say default because plugins can add more) of Vim generally fall in two categories, inner (
Okay now that we’ve got that groundwork let’s talk composition. Generally, this composability comes in the form <optional-number><operator><text-object-or-motion>
. Ignoring the <optional-number>
for the moment, this means we can write di"
to delete all characters between a pair of quotes, y$
to yank all characters from our cursor to the end of the line, ci(
(or ci)
) to delete all characters from, and any other combination you can think of.
Okay now finally, let’s add in that <optional-number>
. This allows you to repeat an <operator>
and <text-object-or-motion>
combination multiple times. For example, we know that dd
deletes a line. 2dd
deletes two lines, starting at the current. Equivalently, dj
deletes the motion of the current line and the line below, indicated by j
(which means “down"). dk
deletes the current line and the one above. 2dk
deletes the current line and two above. For a text object example,daw
deletes the current word. 2daw
deletes the current word and the next. Important to note here that i
text objects (like iw
) cannot be repeated multiple times.
Note: the optional number can also come between the <operator>
and <text-object-or-motion>
, e.g. <operator><optional-number><text-object-or-motion>
.
There are more motions and text objects than I can list here. As you feel comfortable using the ones I did list look into adding more and more to increase your capabilities. There is, however, one additional set of motions I find super useful that I want to briefly mention:
-
f<key>
- move cursor to the next instance of<key>
in the line- E.g. if I have the following line (with
^
indicating my cursor):
The quick brown fox jumps over the lazy dog ^
and I hit
fl
my cursor will move to thel
inlazy
:The quick brown fox jumps over the lazy dog ^
- Just like other motions this can be composed with operators, had I hit
dfl
instead offl
in the example above I would have deleted all characters between my cursor (at thei
inquick
) and thel
inlazy
, inclusive, meaning I would have been left withThe quazy dog
. F<key>
performs the same motion but backwards
- E.g. if I have the following line (with
-
t<key>
- the same asf<key>
except the cursor moves to the character before the next instance of<key>
T<key>
performs the same motion but backwards
-
See this Stack Overflow post if this explanation of
t
andf
doesn’t do it for you
- Composition
- Focus on motions
- Focus on text objects (though there is overlap)
One awesome feature of text editors is the ability to edit the same or multiple files at the same time, side-by-side. Vim has great support for these, called splits!
- Enter
:vsp <optional filename>
to open av
erticalsp
lit. By default, it opens another view into the same file - you can give a filename to open a different file in the split. - Enter
:sp <optional filename>
to open a horizontalsp
lit - Use
C-w <direction>
to move the cursor between splits.<direction>
can be either anhjkl
key or an arrow key - anything you'd normally use to move the cursor.
Note: :q
and :w
operate on a split-by-split basis. To make them apply to all open splits, use :qa
(short for :quitall
) or :wa
(short for writeall
), or all together as :wqa
. E.g., to write and close all open splits simultaneously, use :wqa
.
Here’s a guide on using splits for additional information - Vim Splits - Move Faster and More Naturally.
As you start to use Vim more you might want to define your own custom commands, or remap keys, or use a particular set of non-default settings. To create these and maintain them between Vim sessions you use a configuration file called a .vimrc
(pronounced vim-are-see
).
Vim looks for a .vimrc
file in your home directory (~
). This file consists of a set of commands that Vim runs each time you launch it.
Here’s an example .vimrc
with some simple defaults you might find useful (I’ve tried to comment each setting, if you only like some of the settings feel free to cherry pick just those). Additionally, here’s my full personal .vimrc
(split into multiple files) which I also try to keep well commented.
Finally, here are a few external references for more examples:
- Example vimrc | Vim Wiki
- My .vimrc | Chris Yeh
- A Good Vimrc- opinionated take on
.vimrc
s, definitely agree with the one rule listed at the top of the article
If you want to use Vim for heavier editing, you'll want to look into plugins. Plugins extend the built-in functionality of Vim, and let you do some really cool stuff. This includes bringing in functionality for specific domains, for example smart autocompletion for a particular language.
It’s possible to install plugins manually (see the resources below for an article on doing so) but I highly recommend using a plugin manager. A few options are Vim-Plug, Vundle, and Pathogen. Setting up any plugin manager relies on using a .vimrc
. If you're interested in learning more here’s some resources:
- A StackOverflow discussion on the differences between various plugin managers
- How to install Vim plugins without a plugin manager
- 10 essential Vim plugins for 2018 - the author says essential, not sure about that but there’s some cool ones here
- Vim Awesome - a searchable listing of vim plugins
This guide only scratches the surface of Vim’s features. Here’s a random grab bag of a few other features you may want to look into on your own:
- macros - record multiple keystrokes then repeat them to perform arbitrarily complex actions
.
- innormal
mode hit.
to repeat the last action taken (e.g., hitdd
to delete a line, then move your cursor to another line and hit.
to delete that line)- folds - hide and show code for easier readability
- marks - set marks to easily jump between locations in a document
:!
- type!
incommand-line
mode then any shell command to execute that command in the folder Vim was launched from (e.g.:!ls
to list the the files in the current folder)- registers - yank and paste to multiple buffers, including the system buffer (to copy and paste between Vim and other programs)
If you’d like to learn more, here are a few resources! Also please feel free to reach out and contact me with any questions you might have (or any errors you might find) - nsnshelly
at gmail
.
- Interactive tutorials
- Interactive Vim tutorial
vimtutor
- enter at the command line like you would to launchvim
- Books
Thanks to Sasha Weiss for his excellent tutorial given last year that I borrowed from in writing this guide.