The Vim logo, licensed under the VIM LICENSE

vi cheat sheet

Notes published the
8 - 10 minutes to read, 1913 words

Target audience

These notes are for those who want or need to begin to use a vi-based editor and have zero experience with it.

It is also for those who need to use a vi editor right now and do not have enough time to learn how to use it properly.

Note 📝
This is a cheat sheet; it is not accurate, or complete, and omits a lot of details. But it should be good enough for a quick start.

Why?

Why should you want to learn to use a vi-compatible editor?

vi is ubiquitous

vi is part of the POSIX standard and is normally available on all GNU/Linux and BSD systems. It can be found on most servers, but also on embedded devices (busybox provides, for example, a vi editor), and there are ports for Windows, DOS, OS/2, Amiga, Android and other systems.

Speed up working from the command line

When working from the command line, I find it often distracting having to use a graphical program for editing files. Opening a program in a separate window, eventually resize it, using different keybindings for copy-pasting…​ It’s a lot of unnecessary context-switching.

This is not an argument in favor of vi editors but for any command-line editor.

It is fast and efficient

Unlike Emacs, which stands for "Eight Megs And Constantly Swapping" 🗄️, vi is efficient. /s

Jokes apart, compared to other editors, vim does not use many resources 🗄️. When dealing with big files, or on a busy system, this can make the difference between being able to edit a given file or not.

Which vi should I use?

Seems like a dumb question, but there are multiple vi implementations, even for a specific platform.

While it should not make any difference, I suggest learning vi with nvim.

Neovim features are generally compatible with other vi editors, and it has the advantage of having better defaults.

For example it

  • enables filetype detection

  • syntax highlighting

  • automatic indentation

  • navigation with arrow keys(!)

and other settings that one would expect on most modern editors.

Other vi editors tend to have a more minimalistic approach, and configuring a vi editor is not always as easy as it seems.⁠[1])

Even if it is trivial to change those settings, if one does not know that those can be enabled, they are not changed. Those good defaults are important, especially when someone is learning how to use vi.

If Neovim is not an option, vim is probably the currently most used vi editor. Compared to Neovim, it provides also a graphical Vim editor (gvim), which I enjoyed using on Windows systems.

The first and most important concept to understand when beginning to work with vi

vi has different modes.

When the editor is started, vi is in normal mode.

In this mode, it is possible to execute commands, like deleting one or multiple lines, searching patterns, executing external programs, replacing text, jumping to a specific position, closing the document, and so on.

The most important thing to know is that it is not possible to insert text directly from the normal mode.

When in insert mode, one can type content directly as one would do with a normal editor.

Note that even if it is called insert mode, it is possible to edit text, thus also removing and replacing content, not only adding it.

The easiest way to change from "normal mode" to "insert mode", is with i (mnemonic for insert). For changing from "insert mode" to "normal mode", use Esc

nvim adds -- INSERT -- at the bottom, to make it easier to realize in which mode one is. If in doubt, press Esc to be sure to be in normal mode.

Note: Pressing Esc only once might not be enough, as there are other modes that one could activate accidentally

Toggle between command and insert(/edit) mode

  • Esc and i, as already described

  • a works like i, but appends; it is for inserting text at the end of the cursor

  • A for apending at the end of the line

  • I for inserting at the beginning of the line

A and I work like their lowercase counterpart, but on a line basis, and not a character basis.

Saving file and closing the editor

Once we know how to open the editor and insert text, it would be nice to be able to save the changes (or dismiss them) and close the editor, which seems to be one of the most asked questions about vim

Both operations are done in "normal mode". It is possible to define keybindings, like Ctrl+S that can be used from insert mode too but realized only later that this was possible.

Use

  • :w to write changes (thus save them)

  • :q/:quit to quit the editor, it triggers an error if there are unsaved changes

  • :q!/:quit! or ZQ to quit the editor, unsaved changes are discarded

  • :cq to quit the editor with error code 1 (very useful when scripting), unsaved changes are discarded

  • :x/:exit, ZZ or :wq to exit, ie write and quit,

Notice that some commands have both a short and long form. The short form is usually a mnemonic for the word that describes the action one wants to execute.

I got accustomed to using :x but while opening and closing a lot of files, realized how easier it is to type ZZ. Otherwise, I tend to use :cq if want to dismiss changes.

At least on my keyboards, :cq is easier to type than :q!, and in case I’ve invoked the editor inside a more complex command, like

command1 && nvim file.txt && command2

or

set -o errexit
command1
nvim file.txt
command2

then command2 will not get executed. The most common use case I have is aborting git commits when writing the commit message.

Text Navigating

Once it is clear how to edit files and save my changes, the next step is how to navigate a document.

The "official" way of navigating between text is getting into normal mode, and using h (for left), j (for down), k (for up), and l (for right).

Especially when learning how to use a vi editor, it seems to make more sense to use the arrow keys, unless

  • one is already accustomed to those keybindings

  • one does not use nvim and does not want to change any settings

In nvim it is possible to navigate from the insert and normal mode directly with

  • arrows (, , and )

  • Ctrl followed by an arrow key

  • Home, End

  • PgUp🠕 and PgDn🠗

like in most graphical editors

Note that pressing the right arrow at the end of the line (or the left arrow at the beginning of the line) won’t change the position to another line (but it can surely be configured to work differently)

Once one is proficient enough, it will become more natural to use the normal mode more often and other keys for navigating.

From normal mode, it is possible to navigate with the following keys:

  • $ moves to the end of the line (note that $ is also used in regular expressions with the same meaning)

  • 0 moves to the beginning of the line

  • gg moves to the first line of the document

  • G moves to the last line of the document

  • nG, or ngg goes to line n

All the following commands can be prefixed by a number to repeat the movement multiple times.

  • h (for left), j (for down), k (for up), and l (for right)

  • b moves to begin of word

  • w moves to next word

  • e moves to the end of the current word

  • B, W, and E works like their lowercase counterpart, but use only spaces as separators

  • f followed by a character for finding the given character, for example, fa for moving to the character a

  • F followed by a character for finding backward the given character, for example, fa for moving to the character a

In case you are asking yourself how a word is defined:

A word consists of a sequence of letters, digits, and underscores, or a sequence of other non-blank characters, separated with white space (spaces, tabs, <EOL>). […​] An empty line is also considered to be a word.

vi --cmd ":h word"

For example, 5l moves the cursor to five characters on the right instead of one.

Those commands not only move the cursor but also change to insert mode

  • A brings to the end of the line and changes to insert mode

  • I brings to the end of the line and changes to insert mode

  • O inserts a new line before the current and changes to insert mode

  • o inserts a new line after the current and changes to insert mode

Search and replace

From normal mode

  • /regex for searching forward, n to move to the next match

  • ?regex for searching backward, n to move to the next match

  • :s/search/replace/g will search and replace the next match on the whole line (otherwise remove g)

  • :%s/search/replace/g will search and replace in the entire file

  • :8,10 s/search/replace/g

  • prefix search with \v and use | as separator for multiple searches: /\vword1|word2|word3, or just use the \| separator: /word1\|word2\|word3

Cut, copy and paste

Cut

Deleting means cutting, and is done with d.

It can be combined with other commands, for example

  • dw delete until next word

  • de delete until end of word

  • dW and dE works like their lowercase counterpart, but use only spaces as separators

  • d$ delete until the end of the line

And dd for deleting current line (line ending included, contrary to 0d$)

Paste

There are two commands:

  • p for pasting after current position

  • P for pasting before current position

Copy

One could delete and immediately paste once. For example, for copying the text until the end of a word, one could use deP (but notice one needs to use dep if the word is the last on the line).

A better alternative would be to use the appropriate command: y for yanking.

If you are wondering what yanking has to do with copying, you are not alone 🗄️.

Just like d, it can be combined with other commands:

  • yw to yank until next word

  • ye to yank until end of word

  • yW and dE works like their lowercase counterpart, but use only spaces as separators

  • y$ to yank until the end of the line

Last but not least

The documentation: :h opens the help page

For example :h d opens the help page for the delete command and :h / opens the help page for search commands.


1. I’m still trying to enable specific vi configurations (as there are environments where I do not have the luxury to use nvim…​ even if I should try to change that) that works from a normal GNU/Linux setup, PowerShell, cmd.exe, Cygwin, WSL, Cygwin executed from PowerShell prompt, git-bash executed from Cygwin bash, …​ It is frustrating because different terminals have different capabilities…​ and detecting the environment and finding the corresponding setting is not always trivial

Do you want to share your opinion? Or is there an error, some parts that are not clear enough?

You can contact me anytime.