A Reference for the VI Text Editor (aka VIM)

If you’ve done any programming at all on the command line (in Linux or OS X, or using Cygwin on Windows), you have probably heard of VI and the other powerhouse command-line editor, eMacs, and the epic battle between them long, long ago in a galaxy far, far away… The goal of this article is to give you a functional overview of the VI text editor and give you a useful reference of its commands. I spent a lot of time putting these notes together, so I hope they’re helpful.

Right off the bat, some purists will snipe me for saying “vi” when I really mean “vim” — the latter being the IMproved version. But pretty much everyone uses vim and they call it vi… most of the time when you type “vi” on the command line, it opens up vim anyway.

Open a file with vi just like with other editors: vi [filename] . If the file doesn’t exist, it will be created. And then you will have entered the realm…

There are 2 Modes: Insert and Command

The insert mode is the “normal” typing mode that you would normally think of when using a word processor. The command mode is when you are typing in commands to operate on the text (in lieu of menus, you’ve got to type in all commands). vi starts in command mode, but if you’ve gone to the edit mode, pressing Esc gets you back into command mode. Entering Insert mode is actually a command. Enter insert mode by pressing i (preceded by the Esc key if necessary): Esc to enter command mode. i to enter Insert mode.

How to Type Commands in Command Mode

The command mode commands are normally in this format: (Optional arguments are given in the brackets)

[count] command [where]

Count is the number of times to run the command (e.g. delete 7 lines), and where is the destination of the action, e.g. save this file as xxx.txt.

I’ve grouped the commands here loosely into groups, some of them corresponding to traditional menu names.

Modes

i – enter insert mode (you can also type ‘a’)

Esc – enter command mode

File (the colon commands, mostly)

:n create a new file (not common).

:e [filename] – Edit (open) a file.

:w – save. :w [filename] acts as “Save As”.

:wq – save and quit. Also ZZ (in caps).

:w [filename] – save as filename.

:set xxx – sets option xxx. See Preferences section below.

:q – quit.

:q! – quit without any prompts (i.e. quit without saving).

Edit

u – undo the last change (or redo it).

U – undo the changes to the current line.

ctrl r – Redo. This redoes whatever you undid.

. – Repeat last command.

x – deletes the character under the cursor (Del).

X – deletes the character before the cursor (Backspace).

d – delete (i.e. cut). Usage is dw, d$, d^, dd. to delete a word, delete till the end of the line delete to the beg. of the line, repeat delete, respectively.

y – yank (i.e. copy).

– clipboard. See “Multiple Buffers” below.

p – paste.

r – replace the character under the cursor (specify count).

/ – Find (searches from the current position towards the end)

? – Find (searches from the current position towards the beginning).

:s[regular expression] – Substitute (find and replace). See below.

View

:set nu – show line numbers (:set nu! to remove)

zc – folds Closed a section of code, delineated by {{{ # code here }}} #

zo – folds Open a section of code, delineated by {{{ # code here }}} #

Format

> – indent highlighted text (like tab)

< – shift tab.

Insert

O – open the line above the line the cursor is on.

o – open the line below the line the cursor is on.

R – enters Replace (overwrite) mode until Esc is pressed to exit.

Navigation

h – move the cursor left

j – move cursor down

k – move the cursor up.

l – move the cursor right.

control F – move forward one screen (i.e. page down)

control B – move back one screen.

H – home window line (top of visible)

L – last window line.

]] – next section/function

[[ – previous section/function

0 – Move to start of line (zero)

$ – move to end of line.

shift g – move to end of document.

gg – move to start of document

ctrl g – returns the current line number.

123 shift g – go to line 123.

Tools

% – when the cursor is on a (,),[,],{, or } this will locate its matching pair.

Window

:split – split screen horizontally

:vsplit – split screen vertically.

ctrl w [up/down/left/right] – jump to new portion of split screen.

ctrl z – move vi to background (recess to the Terminal)

fg – brings the process back to the ForeGround (type this in the shell after you’ve done a “ctrl z”).

Help

:h – help

crtl ] – follow a link in the help file.

:q – closes the help file (it’s actually a separate text file), so you quit it.

Search Commands (Find)

These commands let you search the current file looking for a given string. When you press the ‘/’ or ‘?’ key, the cursor will move to the bottom of the screen, where you will enter the string you wish to search for. Pressing the [RETURN] key will signal the end of the string, and cause the search to take place.

To include a ‘/’ or ‘?’ as part of the search string, you must “escape” any of these characters with the backslash character (\).

==> /search string[RETURN]

This command will let you search forward through the file looking for the string. The search will wrap around to the start of the file.

==> ?search string[RETURN]

This command will let you search backward through the file looking for the string. The search will wrap around to the end of the file.

Press n (n) to move to the next result. Press shift n (N) to move back to the previous.

Mnemonics:

The ‘/’ is a forward slash, and is used to search forward. The ‘?’ is the shifted ‘/’ key, and you can think of the act of shifting as reversing the command direction.

To repeat the search, press ‘/’ or ‘?’ depending on whether you want to search forward or backward for the next occurrence. When the cursor moves to the bottom of the screen, press [RETURN] without entering anything. Vi will use the last search string entered as its target.

Substitute (Find and Replace)

To substitute new for the first old on a line type :s/old/new

To substitute new for all ‘old’s on a line type :s/old/new/g

To substitute phrases between two line #’s type :#,#s/old/new/g

To substitute all occurrences in the file type :%s/old/new/g

To ask for confirmation each time add ‘c’ :%s/old/new/gc

Multiple Buffers ” : Frequently Used Text

Most users just use the general buffer, but you can cut and paste text from/to multiple buffers. There are 36, specified by all letters (a-z) and all digits (0-9). The buffer is specified using the command (the mnemonic here might be to QUOTE something). For example, the command: “mdd uses the buffer m, and the last two characters stand for delete current line. Similarly, text can be pasted in with the p or P command. “mp pastes the contents of buffer m after the current cursor position. For any of the commands used in the next two sections, these buffers can be specified for temporary storage of words or paragraphs.

These buffers remain in memory after vi has closed (for a while, at least… I’m not banking on these buffers being 100% persistent). So you can use them to store frequently used bits of text. For example, you may want to use:

“i to contain the block code for an if statement.

“h to contain basic html tags.

Copy, Cut, and Pasting

(i.e. Yanking, Deleting, and Pasting)

The command commonly used command for cutting is d. This command deletes text from the file. The command is preceded by an optional count and followed by a movement specification. If you double the command by typing dd, it deletes the current line. Here are some combinations of these:

d^ cuts (deletes) from current cursor position to the beginning of the line.

d$ cuts (deletes) from current cursor position to the end of the line.

dw deletes from current cursor position to the end of the word.

3dd deletes three lines from current cursor position downwards.

There is also the y command which operates similarly to the d command which take text from the file without deleting the text.

The commands to paste are p and P. They only differ in the position relative to the cursor where they paste. p pastes the specified or general buffer after the cursor position, while P pastes before the cursor position. Specifying count before the paste command pastes text the specified number of times.

Keep in mind that the targeting of the pasting actions isn’t where you’d expect from working with traditional word processors.

Execute External Commands

Type :! followed by an external command.

:! perl -d % launches the current (perl) script in debugging mode (very useful!).
:! php -l % if you’re editing a php file, this checks syntax.

Highlighting Text

v – enters visual mode so you can highlight a visual block. You can highlight entire lines AND columns. Very cool.

To highlight several lines: ctrl v, then hold shift and use the arrow keys and the Home and End keys as you would do normally in commercial word processor (or the j,k,l… equivalents). E.g., pressing d after highlighting a block would delete it (cut it).

Shift g moves to the end of the document.

Alternatively, with most terminals you can use the mouse to highlight a block of text, then move the cursor to where you would like to paste it. A right-click will paste the text. However, this method is a bit awkward because of the keyboard/mouse/keyboard interaction.

Setting Preferences using :set (Pimping Your Ride)

You can set a number of preferences in vi including text and highlight color. Many of these options can be set using :set. Notice than anything you can set, you can unset by using the same command followed by ! – the exclamation point is the universal program code for NOT.

:set ic – ignore case (for searches)

:set hls– sets highlighting for a search

:set is – include search

:set nohlsearch – remove highlighting (or use :set hls!)

:set ai – sets autoindent

:set nu – adds line numbers. (:set nu! to remove)

Edit your ~/.vimrc file to add preferences to this file to make them permanent. E.g. I have the following in my ~/.vimrc file:

highlight Comment ctermfg=lightblue
highlight Search ctermfg=0 ctermbg=3*
set tabstop=4

Other Useful Functions

To push a vi window (or any window, really, to the background) press ctrl z. To bring it back, press fg (for ForeGround). There is fg1, fg2, fg3, etc.

Conclusion

Well, there’s my reference for you fine folks. I may grow some more hair on my chest if I ever do the counterpart for eMacs… but I’m not holding my breath. As of Sunday, this article represents the knowledge gleaned from 2 years spent editing scripts on the command-line. In parting, I’ll share one little tidbit of wisdom: don’t worry too much about the navigation shortcuts: although some shells don’t support the standard arrow keys and Page-Up/Page-Down key bindings, most of them do. Whew!

Please feel free to add corrections or additions to the comments!

3 thoughts on “A Reference for the VI Text Editor (aka VIM)

  1. Here’s a handy regular expression. Say you want to find and replace all instances of Oracle timestamps to MySQL timestamps?

    to_timestamp(’11-NOV-09 12.40.47.000000000 PM’,’DD-MON-RR HH.MI.SS.FF AM’)

    Should become
    NOW()

    A simple find an replace won’t cut it because there could be ANY date and time in the target string, and normal greedy matching will replace more than you want. Instead use non-greedy matching:
    :%s/to_timestamp(.\{-})/NOW()/g

Comments are closed.