* The UNIX operating system, which emerged in the 1970s, included an extensive kit of software tools. One of the best-known was the "vi" text editor -- meaning "visual editor", pronounced "vee-eye" and not "vye" -- written by Bill Joy, which was unusually capable by the standards of the time, if not necessarily all that easy to learn. A competing editor named "EMACS" emerged that featured greater functionality, making vi look somewhat stodgy, but the 1990s, Bram Moolenar created an updated version of vi, which he named "vim" for "vi improved", originally for the Atari ST PC, but which has since been ported to a range of platforms, including MS Windows and Linux.
While the original vi, as mentioned, was not all that user-friendly, Moolenaar's vim did much to bring it up to date, and in terms of capability there's not that much to choose between vim and EMACS. Vim's price is right as well, since it's free for download by anyone who wants it. This document provides a quick introduction to vim. The discussion is based on vim for MS Windows, but it works much the same on other platforms.
* The original vi editor was preceded by a more primitive editor named "ex". Ex was a "line editor": although it sounds incredibly primitive, effectively only one line of text was directly available for editing at a time, though ex had commands that could modify all of a text file. Vi was more like typical modern text editors, such as the Windows "Notepad", in that is was a "screen" editor, where a user works on a text file an entire screen at a time.
However, vi differed from Notepad in that vi featured two different operational modes: "command" mode and "insert" mode. Vi behaved differently in each mode, and actions taken in one mode had entirely different effects in another -- which could be confusing to a beginner:
Vim, as its "vi improved" name suggests, is just vi with a number of refinements; anybody who is familiar with vi should have little trouble with vim, though there are some tweaky differences in syntax. Once the little differences have been understood, the traditional vi user can then move on to the enhancements offered by vim, the most obvious being that, unlike traditional vi, vim has a proper mouse-driven user interface, with a set of pull-down menus, plus mouse cutting and pasting.
It should be noted that the mouse user interface is actually associated with a vim variant named "gvim", but since gvim is what's normally used, that distinction will not be heavily made here. Incidentally, this document was defined relative to vim version 7.3, and some features mentioned here may not be available in earlier versions.
BACK_TO_TOP* After downloading and installing vim from the internet, the first thing to do is run it. Under Windows, there will be an entry for vim in the programs menu or a set of shortcuts on the Windows desktop; in either case, select "GVIM" to run the editor. The result is an editor window with scrollbars, a set of pull-down menus, and a toolbar.
Having run vim, the next thing to do is load a file to edit, say "report.txt". This can be done with the command:
:e report.txt
Note the format of the ":e" (edit) command, specifically that it's preceded by a colon. That is not true of all vim commands; commands preceded by a colon were inherited from the old ex editor, and as is easily observed in following examples, work slightly differently than vim commands without the colon. In any case, if the file "report.txt" doesn't exist, it will be created.
Alternatively, if GVIM has been set up as the default editor for .txt files under Windows, just clicking on the icon for "report.txt" in Windows Explorer with a mouse will bring up the editor with the file automatically loaded. In any case, when the file is loaded, the name of the file is at the top of the vim display; while the bottom line of the vim display gives the current line number, the position of the cursor in the line, and the location of the current line as a percentage of the length of the text file in lines. To get the actually length of the file in lines of text, just press "Ctrl-g".
* One of the nice improved features of vim relative to vi is the ability to edit several files simultaneously. In early versions of vim, multiple files could be loaded in a "split screen" format; for example, to load a second text file "shoplist.txt" in a split screen, we could use the command:
:sp shoplist.txt
-- or just use the pulldown menu entry for "File > Split-Open". The split screen has its uses, but it's also cluttered, and later versions came up with a "tabbed" feature -- like that used in a web browser to bring up multiple web pages at the same time, shifting between them by clicking on the appropriate tab with a mouse. To load "shoplist.txt" in a tab, use the command:
:tabnew shoplist.txt
-- or use "File > Open Tab". Each file name is listed on its appropriate tab. To jump from one tab to another, use "Ctrl-Page Up" or "Ctrl-Page Down". To get rid of a file that's been loaded, just select the appropriate sub-window or tab and enter:
:q
-- or use the mouse pull-down menu on the tab and select "close tab". Vim will provide a warning if the file has been changed and not been saved.
* Anyway, text files loaded into vim each end up in their own "work buffer" for editing. We can execute commands to move around in the work buffer and then modify the text stored in it. By default, vim understands the scroll bars and the PC cursor keys, but it also has traditional vi commands for moving around:
cursor key vi command function ____________________ _______________ ________________________________ up-arrow key k or - move up the screen a line down-arrow key j or + move down the screen a line right-arrow key l or space move one character to the right left-arrow key h or backspace move one character to the left Ctrl-right-arrow key W move one word to the right Ctrl-left-arrow key B move one word to the left Home 0 move to beginning of line End $ move to end of line Crtl-Home 1G move to start of text file Ctrl-End G move to end of text file` Page Up Ctrl-b move back one screen Page Down Ctrl-f move forward one screen ____________________ _______________ ________________________________
Some folks tend to prefer to use "k j l h" over the arrow keys since they don't have to shift a hand to the numeric keypad while editing, but then again if a user is comfortable by habit with using the arrow keys, that's something of a wash. Note that:
As suggested by the "G" command, commands can typically be preceded by a repeat count. For example, "3+" will jump forward three lines through the text, while "10-" will jump ten lines back.
* Once the cursor has been move to the proper place in the text, text can then be inserted into the text buffer.
i insert text before cursor ("Insert" key works the same)
I insert text at beginning of line
a insert text after cursor
A insert text at end of line
o make a new empty line after the current line & insert text into it
O make a new empty line before the current line & insert text into it
Vim displays the flag "INSERT" at the bottom of the page when in insert mode. While in insert mode, all keypresses will be entered as text; none will be interpreted as commands until we press "Esc" to return to command mode.
Suppose that we want to modify existing text, instead of add new text. Deleting old text is easy:
x delete character at cursor position ("Delete" key works the same)
dd delete current line
D delete from cursor position to end of line
dW delete a word (ignoring punctuation)
dw delete a word
Again, all these commands can be preceded with a repeat count: for example, "3dd" deletes three lines. It is just as simple to change text:
r replace current character with a new character ~ change letter from uppercase to lowercase and the reverse cw change a word cW change a word (ignoring punctuation) R overwrite current text
The "r" and "~" commands don't enable insert mode; the others do. To get out of insert mode, press the "Esc" key to return to command mode.
If some problem comes up that garbles text on the display, just press "Ctrl-l"; the screen will be erased and the text rewritten. To enter non-printing characters like "Esc" into text, enter "Ctrl-q" followed by the non-printing character. Traditionally, vi used "Ctrl-v" to embed nonprinting characters, but that leads to a problem under Windows, discussed below.
Incidentally, one of the other nice features of vim relative to vi is that vim does interactive spell-checking, highlighting misspelled or questionable words. Text files written with vi had to be checked by a separate spell checking program.
* Searching for a particular text string is also easy. Simply enter "/" while in "command" mode and follow it with the target string. For example, to search for the string "cat", enter:
/cat
-- and then press the "Enter" key. Vi will then jump to the first instance of the string "cat" following the cursor position, or give an error message if it can't find it. We can search backwards by using "?" instead of "/". If we search for a string and find it, we can repeat the same search by pressing the "n" key, or repeat the search in the reverse direction with the "N" key.
* Vim provides a large number of options that can be set by the user. To get a list of options and their current values, just enter the command:
:set
The "set" command can also be used to set option. Suppose we want lines of text to "wrap" automatically to a new line when we reach the right margin. We set the "wrapmargin" option as follows:
:set wm=1
This sets the "wrapmargin" to one column from the right margin. It's just as easy to disable word wrapping:
:set wm=0
We can also set up "autoindentation" -- that is, when we press the "Enter" key after typing in text, the cursor returns to a point exactly under the first character in the previous line, allowing us to type neatly indented text. Autoindent is set with:
:set ai
-- and disabled with:
:set noai
* Vim provides two particularly useful commands:
* In any case, now that we have modified "report.txt", we need to save it. Enter:
:w!
This overwrites the old "report.txt". If we don't specify the "!", vim will refuse to overwrite the old file. We can then exit vim with:
:q
We can do both by entering:
ZZ
-- or:
:wq!
To leave vi without storing the changed file, use the command:
:q!
If we are editing multiple files using tabbed editing, these commands apply only to the current tab, saving the file in the tab and then, on exit, closing the tab. To deal with all the tabs, add an "a" for "all" to the commands:
:wqa :qa!
This basic set of commands allows us to perform sophisticated text editing, but it is only scratching the surface. Vim has so many commands that few know them all. It is recommended to practice with this simple command set before proceeding further.
BACK_TO_TOP* So far we have learned how to move around in vim, and how to use a repeat count to multiply various operations. There's more we can do to move around. We can move the cursor to the next instance of some specified character on a line with the command:
f<char>
Similarly, we can move the cursor backwards to the last previous instance of a specified character on a line with:
F<char>
We can move the cursor to the character before the next instance of some specified character on a line with the command:
t<char>
We can move the cursor to the character after the last previous instance of a specified character on a line with:
T<char>
We can perform any of these four commands again by entering a ";". We can perform them again, but in the reverse direction, by entering a ",". We can move to a specified column with:
<column number>|
If we don't specify a column number, "|" moves the cursor to the beginning of the line.
Vim also has commands for moving by sentences or paragraphs at a time:
( Move to beginning of most previous sentence.
) Move to beginning of next sentence.
{ Move to beginning of most previous paragraph.
} Move to beginning of next paragraph.
As noted, we can go to any line with:
<line number>G
-- with "G" without a number jumping to the the work buffer.
* One particularly useful feature of vim is that it allows us to "mark" text during an editing session, with the command:
m<char>
-- where "<ch>" is any single character in the range "a-z". We will automatically jump to the marker every time we perform:
'<char>
For example, if we enter the command:
mx
-- at some point in the editing session, and later enter:
'x
-- the cursor automatically jumps back to the point in the text where we left the mark "x". This is just like leaving "bookmarks" in important pages of a book. Note that we jump back to the line where left the mark; if we use a backquote, "`", we jump back to the specific word that was marked.
Another useful command, particularly for writing computer programs, is "%". Computer programs often have blocks of code marked by "( )", "[ ]", or "{ }", often with nesting; the "%" causes the cursor to jump from the right parenthesis or bracket to the matching left parenthesis or bracket.
BACK_TO_TOP* We have already learned to insert text with commands like "i" and "o", replace it with "r", and delete it with "d". The "d" command is very flexible:
d0 delete to beginning of line
dw delete word
dW delete blank-delimited word
d3w delete three following words
dB delete to beginning of blank-delimited word
dd delete the current line
5dd delete the next five lines
d$ delete to end of line ("D" does the same thing)
d) delete to end of sentence
d( delete to beginning of sentence
2d) delete next two sentences
d} delete to end of paragraph
d{ delete to beginning of paragraph
The "c" (change) command allows changing text, and is also very flexible, with similar options to "d":
cw change to end of word
c3w change to end of third word
cW change to end of blank-delimited word
cb change to beginning of word
c$ change to end of line ("C" does the same thing)
....
Text can be indented using the ">>" command and unindented using the "<<". Perform these commands and the text is moved by a number of characters, a "shiftwidth", in the appropriate direction, with the shiftwidth defined as a set option. Both commands may be preceded with a count to move multiple lines one shiftwidth.
Similarly, the "<" and ">" commands can be used with other commands to shift lines. For example:
</RAM
-- shifts the first line it finds containing the string "RAM" to the left.
The "J" (join) command joins two lines together. It can be preceded with a count to join multiple lines. Breaking a line is easy -- just insert an "Enter" into it.
BACK_TO_TOP* Searches, as mentioned, can be performed with "/<string>" (search forward) and "?<string>" (search backward), with "n" repeating the last search in original search direction and "N" repeating the search in the reverse direction. If we need to include a "/" or "?" in the search string, precede it with a "\".
Some characters have special meanings in a search string:
^ matches beginning of a line $ matches end of a line . matches any character * matches zero or more repeated instances of the preceding character \> matches the end of a word \< matches the beginning of a word
Square brackets -- "[]" -- surrounding several characters match any single character located between the brackets. Placing a "^" as the first character in the square brackets matches any characters but the ones in the brackets. A range on characters can be designated by linking the ends of the range with a "-"; "[a-z]" designates any character from "a" to "z", while "[0-9]" designates any digit from 0 through 9. For example:
/and matches: "sand" "standard" "and" "slander" /\<and\> matches: "and" (and nothing else!) /^The matches: any line starting with: "The" /^[0-9][0-9]) matches: any line starting with: "00" ... "99" /11* matches: "1" "11" "111" "1111" ... /.* matches: any string of zero or more characters.
* An "s" (substitute) command does both a search and a replace. It has the form:
:[address]s/<search string>/<replace string>[/g]
If we don't specify an address, substitute only searches the current line. If we specify a line number, substitute searches that line. If the address is two line numbers separated by a comma, substitute searches between and through those lines. In addition, a "." indicates the current line, a "$" represents the last line, and a "%" represents the entire work buffer. Vi permits address arithmetic using plus and minus signs. Some examples:
5 line 5 77,100 lines 77 through 100 inclusive 1,. first line through current line .,$ current line through last line 1,$ all the text % all the text .,+10 the current line and ten lines following -10,+10 ten lines before the current line and ten lines following
The search string has the same form as in the search command. There are several special characters used in the replace string:
& use the search string as the replacement string \u& use the search string, with first letter capitalized \U& use the search string, with everything capitalized \l& use the search string, with first letter lower-case \L& use the search string, with everything lower-case
The substitute command normally will only change the first occurrence of the search string found. If we add "/g", substitute will replace all occurrences of the search string within the address range. The substitute command also has an "i" option to specify that case be ignored, and a "c" option that permits checking before making a change -- it lists the line, with the search string highlighted, and prompts to request if the change should be made or not. For example:
* Yet another one of the significantly nice features of vim relative to the old vi is that it supports text cutting and pasting with multiple applications using the mouse. We can select text in another application with the mouse, copy it with "Ctrl-c" or cut it out with "Ctrl-x", and then paste the text into vim with "Ctrl-v". Of course, we can copy or cut text from vim and paste it into another application, or a text file in a separate vim tab or another vim being run on the PC, in the same way. We can also select text without a mouse, just by holding down the "Shift" key and then using cursor movement keys such as "Page Up" and "Page Down".
The Windows cut and paste facility stores its text in the system Clipboard. Vim has its own separate set of "buffers" or "registers" that can be used for copies, cuts, and pastes. There is a general-purpose (GP) buffer that stores text that has been deleted, allowing the "u" command to retrieve text. We can also use the "y" (yank) command to store text in the GP buffer without deleting it from the text, and use the "p" (put) command to put the yanked text back someplace else in the text. The "y" command has much the same syntax as the "d" command and can be used with the same options. The "p" command inserts deleted or yanked text from the GP buffer after the current character; the associated "P" command inserts the text before the current character. The "p" commands don't delete the text from the buffer, so the same text can be pasted into the text as many times as desired. Incidentally, text cut or copied into the GP buffer from one text file can be pasted into another text file in a separate tab.
Given two different cut and paste mechanisms, it's easy to confuse them -- that is, trying to use "p" to paste text copied with "Ctrl-c", or use "Ctrl-v" to paste text copied with "y". The Clipboard and the GP buffer are not the same thing. Incidentally, vim also has its own block-selecting scheme. Just move to a block to be selected, press "Ctrl-q" -- vim displays "INSERT BLOCK" -- and use the appropriate movement commands or softkeys to select the text. Then perform a copy or paste using an ex-style command.
* Although it's not something that's used very much, there are 26 named buffers, each one named by letters of the alphabet; each named buffer can store its own text, to be recalled as needed. Vim uses a named buffer if we precede a delete, yank, or put command with a quotation mark and a buffer name; for example:
"kyy
-- yanks into buffer "k";
"kdd
-- deletes into buffer k, and;
"kP
-- puts from buffer k. We can use a named buffer two ways. If we give the buffer name as a lowercase letter, vim clears the buffer before it deletes or yanks text into the buffer. If we give the name as an uppercase letter, vim appends the newly deleted or yanked text to the end of the buffer.
BACK_TO_TOP* The ":w", ":q", ":wq" or "ZZ" commands have already been discussed; there is more to vim's file-handling capabilities than that. The ":e" (edit) command, mentioned in the introduction, brings a file into vim for editing. For example:
:e helpfile.txt
-- brings file "helpfile.txt" into the work buffer for editing. If there is already text in the work buffer that we have not saved when we enter the ":e" command, the ":e" command will fail, and we'll get an error message. If we want to overwrite our existing text, we must use the ":e!" command instead.
The ":r" (read) command allows us to paste another file into our current text following the current line. For example, if we are editing file "letter.txt", and want to insert file "table.txt" following line 20, we would move the cursor to line 20 and enter:
:r table
If ":r" is invoked without specifying a filename, it reads a copy of the current text file from disk into the text.
The ":w" (write) command is very flexible; it allows us to save chunks of a file, not just the whole thing. It has the syntax:
:[<address>]w[!] [<filename>]
The <address> is as specified for the substitute command earlier. The "!" allows us to overwrite an existing file. If we wish to append the text we are writing to an existing file, we should enter the command:
:[<address>]w>> filename
One warning: if we use the "w!" command without specifying a filename, it automatically saves the file in the default filename -- which is, under normal conditions, the name the file was invoked with. This default file is represented in vim as "%". If we want to save the text file in a new text file with the same name, but an added extension -- say, ".tmp" -- we can write it as:
:w %.tmp
We can also change the default file name, which is useful if we want to modify one file into an entirely different one, and don't want to risk wiping out the old file with a "ZZ" or ":w!" command. This is done with the "f" (file) command:
:f <new_filename>
The "new_filename" established by this command now becomes the name given by the "%" symbol. The old filename is now represented by another symbol, "#".
* Having described various commands that can be used with an address range, it's useful to provide a few examples here, showing how to perform deletes, copies, moves, and writing to a file:
* Some of the parameters that can be set by the ":set" command in vim have been mentioned. There's actually a large set of them, with a list of them and their values provided with:
:set all
A few examples follow:
These parameters can be set as defaults by storing them in the "_vimrc" configuration file, which is found in the vim installation directory. It is recommended that anyone tinkering with _vimrc should make a backup copy of the original file and keep it in a safe place, in case something goes wrong with the changes. In any case, all the ":set" commands can be placed in the _vimrc file so vim will always use those settings.
BACK_TO_TOP* Vim allows a user abbreviations with the ":ab" command. For example:
:ab BT biotechnology
Every time we type "BT", the words "biotechnology" will be inserted. The abbreviation will not be expanded if it is part of another word. We can eliminate abbreviations with the ":una" command, as follows:
:una BT
This is a handy feature when writing a document that repeatedly used hard-to-spell words. Vim also has a "word completion" feature that wasn't in vi: just type the first few characters of the word, then press "Ctrl-n", and it will complete the word. If there are multiple choices, vim provides a menu of them -- just scroll up or down the menu with the arrow keys, then use the right-arrow key to select.
* Vim allows us to set up command "macros", in which a single short user-defined command can be exchanged for a long string of commands. Macros are created with the "map" command:
:map d d4w
This causes four words to be deleted every time the "d" key is pressed. We can use the ":unmap" command to delete macros as follows:
:unmap d
The "map" command is particularly useful for assigning function-key mappings in _vimrc. For example, to map function key 4 so it saves part of the current text from the current line to the end to a temporary file, use:
map <F4> :.,$w! temp.txtBACK_TO_TOP
* We can "fire up" a command shell from within vim with the command:
:sh
Under Windows, this brings up a COMMAND.COM window, hanging up text editing until we exit COMMAND.COM. We can change the command shell using ":set shell=". It is also possible to execute a system command from vim using:
:<address range>!<shell command>
Vim provides shortcuts for this:
!!<shell command> -- Use current line. !}<shell command> -- Use current paragraph. !3}<shell command> -- Use current & next two paragraphs.
For example, suppose we want to take a directory listing and embed it into a document. We can insert a blank line in the appropriate place in the text, and then execute:
!!dir /b
Windows lists the current directory into the text. In the same way, we can insert the date into the text with:
!!date /t
-- and the time with:
!!time /t
More significantly, we can "filter" text with system commands. Suppose we have a list of names:
Jack Fred Ahmed William Joe Thomas Art Harry Paul Oscar
-- and we want to sort them in alphabetic order. We can use the "sort" system command, simply moving the cursor to the first number in the list and then executing:
!}sort
This gives:
Ahmed Art Fred Harry Jack Joe Oscar Paul Thomas William
How useful this feature is depends on how knowledgeable a vim user is about system commands, and how big a set of system commands and utilities is available on the PC -- adding a set of UNIX-type tools to a PC provides a good deal of capability. An adept user could actually write programs to implement custom commands, though that's a subject beyond the scope of this primer.
* Another subject beyond the scope of this document is vim's "macro programming" capability. Vim has its own programming language, useful for providing specialized extensions of the editor's capabilities. The lack of macro programming capability was one of the limitations of vi relative to the EMACS editor, but vim adopted much the same concepts from EMACS, bringing the two editors up to rough parity in that regard. In any case, vim macro programming is a complicated subject and cannot be reasonably discussed here.
BACK_TO_TOP* The list below provides a short vim command reference:
___________________________________________________________________
FILE MANAGEMENT:
:e <filename> edit text, use "e!" to overwrite
:tabnew <filename> load file into new tab
:w [<filename>] write text, use "e!" to overwrite
:q quit, use "q!" to overwrite
:qa quit all tabs, use "qa!" to overwrite
:wq write and quit, "ZZ" does same
:r read file into text
:f <filename> change default filename
CURSOR MOVEMENT:
h j k l cursor movement
w W jump forward by word
b B jump back by word
0 start of line
$ end of line
Ctrl-f jump ahead one screen
Ctrl-b jump back one screen
<column number>| jump to column
<line number>G jump to line ("G" give end of text)
( ) jump forward / back by sentence
{ } jump forward / back by paragraph
TEXT INSERTION & MODIFICATION:
i insert before character
I insert at beginning of line
a insert after character
A insert at end of line
o insert above current line
O insert after current line
x delete character
D delete to end of line
dd delete line
dw dW delete word
yy yank line
y} yank paragraph
"<a-z>yy yank line into named buffer
p paste
"<a-z>p paste from named buffer
~ toggle uppercase / lowercase
r replace character
R overwrite text
cw cW change word
C change to end of line
J join lines
>> indent text
<< dedent text
SEARCH AND REPLACE:
f F find character in string
t T find preceding / trailing character in string
/<search string> find string in forward direction
?<search string> find string in reverse direction
n repeat search
N reverse repeat search
% find matching parenthesis or bracket
^ match start of line
$ match end of line
. match any character
* match repetitions of preceding character
\> match start of word
\< match end of word
[<character/digit list>] match selections from list
s/<old>/<new>/[gic] search & replace text
& use old as new
\u& use old as new, capitalize
\U& use old as new, all-caps
\l& use old as new, first character lower-case
\L& use old as new, all characters lower-case
NOTES:
jump back to earlier text with "''"
mark text with "m[a-z]", jump back with "'[a-z]"
use "Ctrl-q" to embed nonprinting characters in text
use "Ctrl-q" to select block
use "Ctrl-n" for word completion
create abbreviations with ":ab", macros with ":map"
use ":sh" to get a shell, use "!!" to run system commands
___________________________________________________________________
* I originally wrote this document as a short vi tutorial back in the late 1980s. I later created a website; I didn't see the need to add a vi document to it, vi being clearly behind the times -- but when I finally got into vim I realized it had a future, and besides I wanted to refine my vim skills. I retrieved the old vi document out of my archives and quickly rewrote it for release to the website.
I ended up spending more time on the update than I expected, since I hadn't given vim's special features much consideration before I started on the update, and found out there's more to them than I thought. Vim is a rich environment, in fact there's no way to do more than scratch the surface in a one-chapter document. However, this primer provides a useful starting point.
Having mentioned the rivalry between vi/vim and EMACS in the introduction, the question arises as to where I stand in the long-ongoing "editor war" AKA "World War VI" between the two. The answer is that I'm agnostic, since I know almost nothing about EMACS and can't say anything either good or bad about it. I'm entirely dedicated to using vi/vim, but it's not out of any belief that it's inherently better, it's just what I grew up with, I'm comfortable with it, it does everything I could want, and there's no obvious reason to go through the learning curve of using something else. If I'd started out with EMACS, I would have ended up being just as dedicated to it.
* Revision history:
v1.0.0 / 01 may 11BACK_TO_TOP