Intro

In this lab, we will be working with the versatile open-source editor, ViM. This program, which is available for all major operating systems is one of the most powerful editors around, and is specifically designed to make editing much faster and more efficient. Unfortunately, to achieve this status, ViM has a bit of a learning curve, especially up front. Once you can master the major concepts, however, it should be very easy to edit more productively, and to discover how to become even more proficient over time. To paraphrase the program's creator, Bram Moolenaar, ViM is designed so that any dull, repetitive task could be automated with the least amount of effort.


Exercise 1: Insert Mode

Unlike Emacs, gedit, notepad, etc., ViM was designed with the idea of "modes" of editing. This means that the same strokes may result in different outcomes based on the mode that you are currently in. This may seem confusing, but it should make more sense soon. Let's get started.

$ vim
We start in "command mode." This is the default mode for the text editor and the mode in which most of ViM's features are implemented. No matter what action we are performing, we can always press Escape to finish or cancel the current operation and return to command mode. This mode allows you to manipulate text very quickly, but does not provide for means to create new text. For that we should enter "insert mode." To do so, press 'i':
i
First, notice that, in the lower left-hand corner, you should see "-- INSERT --", which gives you an indication of your current mode. Insert mode is very similar to the default interface in Emacs or the only interfaces in Notepad, gedit, etc. Each stroke that you type will be written to the screen. Try writing the following (with typos):
The ccow jumpedd ovverr thhe mmmoon[Return]
There are a some words fun that do not do not belong paper in this sentence. [Return]
sOMEBODY typed the end of THIS LINE twice. end of this line twice. [Return]
Spike Excellent Joy Fyre
Now press escape to return to command mode. Notice first that the cursor appears to move back one character when entering command mode from insert mode. This is because when we are inserting, the cursor is placed at the position of the next character that will be written, while in command mode, we want to operate on the characters already written, so we cannot operate on a space where no character exists.

ModeCommandOutcome
Any<Escape>Enter Command mode
CommandiEnter Insert mode


Exercise 2: Moving around

In both insert and command mode, movement keys include those that one would generally expect. The arrow keys move the cursor on their associated direction, Home jumps to the beginning of the line the cursor is currently on, End, jumps to the end of the current line, Page Up and Down are aptly named, and so forth. In command mode, however, we have additional means of moving around our text; these are very important as almost all actions in ViM can be used with a particular movement. First, arrow your way to the upper-left corner of the document (we'll set up the mouse soon enough). Now press
w
Notice that your cursor jumped to the second word, "ccow." This is because the 'w' key moves you forward one word. This may seem pointless, but let us now combine it with insert mode. Type
cw
You have entered the "change" command and given it a direction. The "change" command deletes everything that was in the location you specified (here a 'word') and places you into insert mode. Type "cow" to modify this phrase, and then escape from insert mode. Please return your cursor to the beginning of the first line in command mode. It's nice to move forwards or backwards (with the 'b' rather than 'w' key) by a word at a time, but that's not very efficient. ViM solves this problem by allowing almost all movement keys the option of a given scaler that tells the program to execute that command x number of times. For example, try
3w
Your cursor should have moved to "ovverr". This makes perfect sense as we jumped to "cow" (1w), "jumpedd" (2w), and finally "ovverr" (3w). In fact, we can combine the scaler notation with almost all commands. Try moving to the beginning of "jumpedd" with the command by typping 8 followed by the left-arrow key.

Of course, we are not limited to movement only by characters, lines, and words. Move your cursor to somewhere in the middle of the second line and press
)
What do you think this command means? Try it again. Do the results surprise you? Continue pressing ')' until you reach the end of the document and then try '(' until you reach the top. Can you guess what the '(' and ')' commands mean? These move the cursor a "sentence" forwards or backwards, where a sentence is defined as ending with '.', '?', or '!' followed by an end-of-line, space, or tab. Though we don't have any paragraphs to work with the '{' and '}' commands work analogously for paragraphs, where a "paragraph" is defined as the text between empty lines (i.e. blank line, text, text, text, blank line). ViM was designed with these somewhat unnatural (for now) movement commands, so we will be seeing them in combination with many other commands below. How would we combine the "change" command with the paragraph motion? From the third line, how could we move to the end of the document using one command that involves ')'? <Hint> Two strokes, beginning with a number<\Hint>

ModeCommandOutcome
Any<Arrow Keys> Move the cursor in the direction pointed
by the arrow key
Any<Page Up/Down> Move the cursor one page up or down
Any<Home/End> Move the cursor to start or end of a line
CommandwMove forward one word
CommandbMove back one word
Command)Move forward one sentence
Command(Move back one sentence
Command}Move forward one paragraph
Command{Move back one paragraph
Commandx[movement] Move movement x times
Ex. 15} moves us 15 paragraphs forward
Commandc[movement] "Change" - Deletes everything within the next
movement away and enters insert mode
Ex. c3w deletes the next 3 words and
enters insert mode


Exercise 3: Simple Editing

We begin with the "delete" command. As with most commands, this takes a movement parameter. Please maneuver your cursor to the word "a" on the second line of our example text. We delete this word by typing
dw
That is, delete word. Next, please navigate to the word "fun" and delete it using only 'w' and "dw". Now, delete the word "paper" using only two commands, one to move to the word and a second to delete it. Are you getting the hang of moving by words?

Next, return the cursor to the first letter of the first "do" word in the line. Though we won't take this route, how could we fix this typo using a scaler version of "cw"? Instead, we will perform a similar operation and delete all four words with the command
4dw
<Aside> 4dw literally means (delete word) four times; and equivalent statement would be d4w delete (4 words). In ViM, there are several different methods of performing the same operation; you will learn which method feels right for you.</Aside> Wait! We have made a mistake! What can we do? Of course, ViM has a solution, the Undo command ('u'). Please revert the text to include two "do not"s with the Undo command.

This line still is not correct, however, so let's fix it by deleting the two words "do not". How could we do that with one command? This version looks a little better, but I'm not sure. Try undo-ing again. Actually, the version with only one "do not" looks correct, so let's redo our undo with the Redo command (Ctrl-r). Whew. Much better.

Let's move our cursor to the beginning of the "sOMEBODY" line. Type the 'End' key, followed by the 'Home' key to return to the start of the line we've been working on. 'End' and 'Home' were not standard when Vi (a predecessor to ViM) was created, so an alternative (and much more widely used) version of the end-of-line command is the '$' key, while the start-of-line command is '0'. Try it now. As '$' is a motion, we can combine it with the delete and change commands. Try deleting everything after the first period.

Our next objective is to learn some single character commands. We begin with deletion of one character with a single stroke (d-<right arrow> has too many key strokes, after all). Move your cursor to the second d in "jumpedd" on the first line. Type
x
This should delete the single character. Fix "ovverr" through the same method. The 'x' command is also a form of movement, so we can use it to delete several character at a time if needed. For example, try to delete two ms from "mmmoon" with the
2x
command. Try to get rid of the os as well. How can we undo this mistake?

We can also modify the case for a given character with the '~' (tilda) command. Move your cursor to "sOMEBODY" and press
~
Notice that tilda not only inverts the case, but also moves the cursor forward, hence we can keep pressing tilda until "sOMEBODY" is fixed. Please move the cursor to "THIS LINE" using only word movement. How could we fix the case of "THIS LINE" using only one command (two key strokes)? <Hint> Both 'x' and '~' operate immediately on exactly one character. Think of the 2x example and test what the '~' command does to a space</Hint>

ModeCommandOutcome
Commandd[movement] Delete movement and add them to the
buffer (described in section 5)
Ex. d4) deletes 4 sentences
Commandxd[movement] Equivalent to dxmovement
Commandu Undo previous changes
(i.e. move back through undo history)
Command<Ctrl>-r Redo previously undone changes
(i.e. move forward through undo history)
Command0Equivalent to <Home>
Command$Equivalent to <End>
Commandxx Delete x characters and add them to
the buffer (described in section 5)
Ex. 5x deletes 5 characters
Commandx~ Changes the case of the next x letters,
non-letters (whitespace, numbers, etc.)
Ex. 15~ reverses the case of the next
15 letters


Exercise 4: Revisiting Insert Mode

Now that we've covered some more command mechanics, I'd like to mention a few more means of editing text. The 'i' command is only the most basic method of entering insert mode; as we've already seen, using the 'c'hange command to replace whole words is much more efficient when editing rather than producing documents. A related command is the replace command, which comes in two formats. Move your cursor to the word "Fyre" on the fourth line. We could fix this misspelling by trying cw to change the word, but a more efficient method requires that we place the cursor over the y and type
ri
We should parse this comand into two strokes, 'r', which enters temporary replace mode and 'i', the letter that will replace the character at the cursor position. It's important to note that there is no immediate feedback when initially pressing 'r'; this is because the 'r' command is specifically designed to be used for one-character changes. A more substantive mode is the "Replace" mode (the 'R' command), which overwrites the character at the current cursor position. If you are familiar with MS-Word, this will resemble turning off insertion editing when pressing the Insert key. Let's test this mode:
R
Notice the "-- REPLACE --" notification. You can still manuever around as you can in Insert or Command modes, so please move to the first character in the word "Joy" and type "Ice". Simple, eh? Press escape to exit Replace mode. We can move around more quickly in command mode, so let's move to the word "Spike" in one key stroke. How can we do that again? Now, enter Replace mose to edit the word "Spike" and replace it with "Toast". Now try to replace the word "Ice" with "Huge". Do the results surprise you? We can also enter Replace mode from within Insert mode by pressing the "Insert" key. For example, enter insert mode ('i') and then press the "Insert" key, noticing that the "-- INSERT --" has become "-- REPLACE --" in the lower left corner.

We now quickly discuss two other methods of inserting text which you will find useful while editing code. Neither is especially complex, but both save quite a bit of time after a long coding session. Let's begin by moving to the word "The" on the first line. Try the command,
A
You will see that we've entered insert mode and placed the cursor at the end of the line. The command we entered stands for Append, which is extremely useful for syntactical mistakes. For example, let's add a period at the end of the line. Next, try to add some more words at the end of the fourth line. Notice that this command can be called anywhere on the line you wish to edit.

Next we learn the "open" command, which is a bit misleading as it allows us to "open" a line rather than a file. After placing the cursor anywhere on the third line, type the command
o
As you can see, we create a new line below the line the cursor was originally on and enter insert mode. A related command, 'O' performs the same operation by opening a line above the cursor's line. As you become more familiar with ViM, you will come to understand the relations between lower-case commands and their upper-case siblings. For now let's just exit insert mode and undo any lines we opened. Do you remember the command to undo?

ModeCommandOutcome
Commandr[key] Replace the character under the cursor with [key]
CommandREnter Replace mode
Command<Insert>Enter Insert mode
Insert<Insert>Enter Replace mode
CommandA Append - Move cursor to end of current line and
enter Insert mode
Commando Open - Create a new line under the current line,
move the cursor to it, and enter Insert mode
CommandO Open - Create a new line above the current line,
move the cursor to it, and enter Insert mode


Exercise 5: Line-Based Editing

This is all fine and dandy, but, even in notepad we can select, copy, delete, etc. multiple lines at once; how can we perform these operations in ViM? We'll discuss selecting several lines at a time later, but we now discuss how to delete a line. Please move your cursor to the fourth line and type
dd
Just like that the line is gone. Notice the similarity between "dw" and "dd"; in general, if a command required a movement (such as 'd', 'c', and soon 'y'), we can perform the operation on an entire line by repeating that command. After moving to the first line, please delete all three lines in one command. See the table below if you forget how.

Ah! All our precious work is gone! We could retype it...
...
...
...
or, I could tell you that "delete" operations ('d') are actually more equivalent to "cut" operations than their name would appear. To "paste" what we just cut, try
p
Perhaps unexpectedly, the lines previously deleted are placed on the second line rather than the first. Try alternative version of paste, 'P'. How are these commands different? If you are unsure, try deleting one line and pasting it near the middle of the document first with 'p' and then 'P'.

A command that is releted to "delete" is "yank" the equivalent of "copy". Yank ('y') operates identically to 'd', except the words, lines, etc. that you copy are not deleted. Try rearanging the three lines with combinations of
yy
and 'p'. It might be useful to note that the paste, yank, and delete operations work with any movement (we can paste words, letters (after deleting with 'x', for example), lines, etc.). Please delete any duplicate lines and rearrange the words within one of the lines using only delete, yank, and paste.

It's important that we stop here to note that the buffer that ViM copies and pastes from is *not* the operating system's buffer. Hence, you cannot copy text from this webdocument and paste it into ViM with the 'p' command (this is a bit misleading, as it is possible since ViM has several dozen buffers, including one that has access to the system buffer, but for simplicity, let's assume it does not). If we need to copy information from another program, a simple solution is to enter insert mode and use the terminal's paste operation (or middle-click).

ModeCommandOutcome
Commandxdd Delete x lines and place them in the buffer
Similar to "cut"
Ex. 5dd deletes the next 5 lines
Commandxcc Delete x lines and enter Insert mode
Ex. 2cc deletes the next 2 lines and enters
Insert mode
Commandp Place whatever is in the buffer ("clipboard")
after the cursor. If the buffer contains a line or
more, place the contents of the buffer on the line
following the current line.
CommandP Place whatever is in the buffer ("clipboard")
before the cursor. If the buffer contains a line or
more, place the contents of the buffer on the line
above the current line.
Commandy[movement] Yank movement (add it to the buffer)
Similar to "copy"
Ex. y4w yanks 4 words
Commandxyy Yanks x (places them in the buffer)
Similar to "copy"
Ex. 5yy yanks the next 5 lines


Exercise 6: Execute Mode and Files

We now reach the last major mode of ViM, the "execute" mode. This mode is accessed from command mode by pressing the colon (':'). Notice that a colon also appears at the bottom left of the screen, indicating that you've entered execute mode. You can easily cancel the execute mode by pressing the Escape key to return to command mode. One of the most basic commands involves jumping to a particular line and is of the form ":x", where x is a line number. Try moving to the first line with the command
:1
Simple enough? This is just one of many ways to jump around your text documents (see "marking", for example), but it happens to be one of the most easy to remember. In any event, this is quite useful when debugging for jumping to the exact line that caused a problem.

We next learn some file-manipulation commands, beginning with saving a file. In ViM, the command is called "write", and is performed via
:w filename
or ":write filename". filename is not always required, especially if we call vim to open a specific document (see below) or we've written to the file once already. For example, add a new line with some useful information on it, then use ":w".

Now that we can write, we should learn how to open files, but before we can do that, we must learn how to close the document we are currently editing. To close an editing session (I use this termenology because, as we shall see in a moment, ViM may be editing several different files at once), we use the quit command,
:q
or ":quit". Let's exit ViM and return to bash. Try listing the contents of the current directory to make sure vim wrote where you thought it did. Next, we discuss several methods of opening a document with ViM, the most obvious being from the command line. If we envoke vim with a filename as an arguement, ViM will start immediately editing that document.
$ vim filename
This is not the most efficient method, as it requires us to exit ViM itself. Exit ViM and then open it again without any arguments. The command, "edit",
:e filename
or ":edit filename" is the standard method of opening a file within ViM. While opening your file, try using tab-completion. ViM's tab-completion is very similar to bash's with one major difference. Can you spot it? <Hint> try tab completion in a directory with many files in it</Hint>. ViM's command mode also offers a history similar to that of bash; press ':' to get into command mode and then press the up or down arrows to move through the history of your commands.

Try editing your file and then quiting ViM without saving. Being a forgiving text editor, ViM doesn't want you to lose your work, so it will question your actions if you try to exit without saving. As the helpful error message points out, you can tell ViM that you *really* want to quit (or any other command), regardless of consequences, by adding the '!' at the end of the command. For example, you should now type
:q!
to quit without saving your work.

Another useful method of editing two files at once uses the split command. First, use ViM to create a second, nonsensical file (alternatively, you can use another text file that is ready). Use the edit command to edit our original document (which you saved not too long ago). Now use the "split" command to open a second editing session within ViM:
:split filename
where filename is the name of the new text document. Now we have two seperate documents. Try to split again, this time with the original document as the parameter. Your screen should be split into three equal editing sessions that are ontop of each other. Try editing the file that is now opened twice. How does the other instance of the editing session respond?

You may or may not have noticed that you can only move your cursor in the editing session that you last opened. How can we navigate between the sessions? One method is to use the mouse, but that won't be an option until later. Another method is to hold ctrl and press 'w' (for "window") twice.

As mentioned before, the quit command closes a particular editing session. Please close all sessions but the main document that we have been editing. What's the result of calling split with no parameters? How could this be useful? As a quick experiment, try splitting a file with itself, editing the file, and then quiting ViM without saving by closing each session one-at-a-time. Why do you think ViM allows you to close all except the last session that is editing a particular file without any errors or warnings? As a side note, you can save all sessions that are split or exit all such sessions with the "all" system, i.e. ":qa" for quit all window and ":wa" for write all windows to their respective files.

<Aside>A very efficient command for saving and closing a file is the concatenation of "write" and "quite", i.e. ":wq" </Aside>

Now that we understand how to open, close, and navigate windows, let's discuss quite possibly the most important command in ViM, "help". ViM has an internal help system that rquires users to call
:help topic
where topic can range from a keystroke (e.g. ":help i"), to a command (e.g. ":help :q"), to a concept (e.g. ":help window"). This help system certainly contains the resources your need to succeed with ViM, but is presented rather tersely and with difficult searchability (hence, I'm writing this lab). When you get a chance, try calling ":help" alone, as it serves as a very good introduction to ViM's concepts.

ModeCommandOutcome
Execute:xJump to line x
Execute:w [filename] Write ("save") curent editing session to
filename. If no filename is specified,
write to the document associated with this
session (the last file written to, opened from, etc.)
Execute:q Quit the current editing session.
ViM will not quit if you have not saved.
Execute:wq [filename] Write ("save") curent editing session to
filename and then quit. If no
filename is specified, write to the
document associated with this session (the
last file written to, opened from, etc.)
Execute:e [filename] Edit - Open filename using the current
editing window. This closes the current file.
Execute:[command]! [arguments] Force - Perform the command regardless
of any rammifications
Ex. :q! Quits the session whether or not the
file has been saved.
Execute:[command]a [arguments] All - Perform the command to all open
windows
Execute:split [filename] Opens a new editing session in a new "window"
to edit filename. If filename is
blank, open the current document.
Command<Ctrl>-w <Ctrl>-w Move cursor to next window (vertically)
Execute:help [keystroke] Shows help for given keystroke in new
window. If no topic is given, show
generic help screen.
Execute:help :[command] Shows help for given command in new
window. If no topic is given, show
generic help screen.
Execute:help [topic] Shows help for given topic in new
window. If no topic is given, show
generic help screen.


Exercise 7: Searching and Substituting

Searching and substitution are essential to any application that works with large quantities of editable text. Of course, ViM provides facilities for these operations and even extends the standard assortment with an understanding of regular expressions. This certainly is not the time to discuss this important term, but I can't pass too many opportunities to glorify ViM. But back to searching. Please open a new file with the following contents
Peter Piper picked a peck of peckled pippers.
Did Peter Piper pick a peck of peckled pippers?
If Peter Piper picked a peck of peckled pippers,
where's the peck of peckled pippers Peter Piper picked?
Remember that to copy text from another source and paste it into ViM we copy the text, enter insert mode, and then use the terminal to paste. Please move the cursor to the upper left-hand corner of the document. We will now search for "pick" using the forwards search command:
/pick
ViM's cursor has moved to the first instance of "pick", which is in the first line as "picked". We'd like to look at the next match, so type
n
Now ViM has moved us to the next match, which happens to be in the second line. Try to use the next-match command ('n') a few more times, noting what happens when there are no more entries in the document. An alternative to the next-match command is the previous-match command, ('N'). Similarly an alternative to forwards search ('/') is the backwards search, '?'. Do 'n' and 'N' operate how you expect them to when backwards searching? In certain cases, it may be exceedingly useful to search for the word that is currently under the cursor. For example, if we wanted to search for all instances of "of" we could move to the "of" in the first line and type
*


Next, try searching for "pIcK". Why do you think ViM responds the way it does? Personally, I prefer my searches to be case insensitive. To tell ViM to ignore case when searching, use the following command, which will be explained further in the next exercise:
:set ignorecase
Try searching for "pIcK" again. If you prefer searching with case sensitivity, we can go back to the default setting by typing
:set noignorecase
Ignorecase is a boolean option. We will discuss options in more detail in the next section.

ViM also has a built-in search-and-replace command, but the syntax is rather clanky. Read ":help :s" for more information, but the gist of this command are noted in the table at the end of this section. To fix all of the "peckled"s to "pickled"s, then, we would type
:%s/peckled/pickled/g
Even I find these commands very hard to remember, but luckily there is a (in my oppinion) a simpler way. Use the '/' command to search for "pipper". Once you hit your first match, use the change-word command to convert the "pipper" into a "pepper". Now next-match to the next "pipper" and press
.
While in command mode, the '.' character is used to repeat the last editing command ("delete 20 lines", "paste twice", etc.), and as the last command change-worded the word to "pepper", '.' will do the same. Use this group of commands to fix the rest of the document, and if you are interested in ViM's methods of repeating tasks, please refer to :help repeating.

ModeCommandOutcome
Command/[searchTerm] Searches forward for regular expressions that
match searchTerm and places cursor on
the next match
Command?[searchTerm] Searches backward for regular expressions that
match searchTerm and places cursor on
the next match
Command* Searches forward for the word that is currently
under the cursor
Commandn Place cursor on next match for the most recent
search
CommandN Place cursor on previous match for the most
recent search
Execute:set ignorecase In all searches/regular expressions, be case
insensitive
Execute:set noignorecase In all searches/regular expressions, be case
sensitive (Default)
Execute:s/oldWord/newWord/g Replace all oldWords with the newWord
on this line
Execute :%s/oldWord/newWord/g Replace all oldWords with the newWord
in this file
Execute :%s/oldWord/newWord/gc Replace all oldWords with the newWord
in this file, asking for confirmation on each entry


Exercise 8: The .vimrc File

As you learned with your introduction to Emacs, many Unix programs read from a configuration file at startup. ViM's startip file is stored in the home directory as ".vimrc". Let's open that file to edit it.
:e! ~/.vimrc
The syntax of the .vimrc file is identical to what you would enter in execute mode, save that we can skip the colon if we want to. For example, let's open the .vimrc file every time we run vim. To be perfectly explicit, I stress that we must press the insert key:
i:e ~/.vimrc or
ie ~/.vimrc
Now quit ViM and open it again with no parameters. ViM will give you an odd message from the command line (this command is not quite what the .vimrc is for); you can continue the program by pressing [Enter]. Notice that opening ViM with no parameters jumps to the .vimrc file. Close ViM. What happens when we open ViM with another text file (such as the typo'd file we started with) as a parameter?

Let's fix our .vimrc file to something a bit more useful. Before we list any of the following useful options, it's important to note that you can search the help manuals for a particular option with the ":help 'option'" systax, where option is the name of the option we'd like more information on. Please select any of the options below to enter into your .vimrc, placing each entry on a separate line. Boolean options can be set and unset while running ViM with the following syntax
:set option
:set nooption
Arguments that require parameters can be set with
:set option=[Value]


ignorecase - "set ignorecase" alerts ViM that all searches should be case insensitive. Note that, if you do not want to ignore case while searching you do not need to put "set noignorecase" as the default behaviour of ViM is to be case sensitive.

mouse - "set mouse=a" tells ViM that you want to make use of the mouse in all modes. ViM can use the mouse in a terminal if you are running Linux, BSD, or Windows. Unfortunately, the Mac terminal does not support the mouse very well, so to use the mouse on a Mac, you will need to use gViM. As we've alluded before, the mouse can be used to select large chunks of continguous information (see visual mode below) and can be used to switch between editing sessions. When working with split sessions, you can also adjust the size of each session by dragging the appropriate divider.

wrap margin - "set wrapmargin=x" or "set wm=x" where x is a small number (I use 4) tells ViM to automatically wrap your text while typing. If this parameter is not set, your text will likely appear to span several lines, but not include actual newline characters (therefore in any other editor or printing, the characters will be botched). A very simple test for a multi-line-in-ViM entry is whether, when arrowing through the document, the cursor appears to skip over lines. The numeric parameter tells ViM how many characters from the end of the window it should start wrapping words.

background - "set background=dark" or "set background=light" informs ViM that the terminal it is being run in has a dark or light background. This is useful for syntax and other types of highlighting, as it makes the highlighting much easier to read.

backspace - "set backspace=2" is an odd but useful command that alerts ViM that the user should be able to backspace through autoindentation (see the next section), through newline characters, and past the beginning of an insert-mode session. This command makes ViM feel a bit more comfortable as it will feel more like a standard editor.

whichwrap - "set whichwrap=b,s,<,>,[,]" or "set ww=b,s,<,>,[,]" informs ViM that it should wrap movements that involve the left and right arrow keys. Like the backspace option, this is set largely to make ViM a bit more friendly. For more information, look at ":help 'ww'".

autoindent - "set autoindent" will be very useful when programming, but arrises in all sort of editing situations. More or less, this setting makes ViM copy the indentation of the current line when opening a new line, either explicitly ('o') or by word-wrapping or pressing "[Enter]" while in Insert mode. ViM should have this by default, but I think it's important to mention anyway.

ModeCommandOutcome
Execute:set option Set the boolean option, option to true
Ex. :set ignorecase
Execute:set nooption Set the boolean option, option to false
Ex. :set noignorecase
Execute:set option=[Value] Set the option, option, to [Value]
Ex. :set wm=5
Execute:set ignorecase Ignores case while searching
Execute:set mouse=[Value] Allows the mouse to be an input in Value
is "a", or nothing if Value is ""
Ex. :set mouse=a
Execute:set wm=[Value] Set the word margin (the character position
from the right at which point ViM wraps
words) to Value
Ex. :set wm=5
Execute:set bg=[Value] Tell ViM the terminal's background color
so that it may highlight appropriately
Ex. :set bg=dark
Execute:set bs=[Value] Tell ViM how to deal with backspaces.
Value can be either a comma separated
list or a numeric value (see help pages)
Ex. :set backspace=2
Execute:set ww=[Value] Informs ViM which characters wrap around a
newline. See the help pages for specifics
Ex. :set ww=b,s,<,>,[,]
Execute:set autoindent If this option is set, whenever you press
[Enter] or open a new line, the indentation
of the previous line is used for the new line

Exercise 9: Programming with ViM

Though ViM was designed to be a multifunctional text editor, it is probably most useful as a coding tool. As such, it implements several useful features, such as autoindent, code folding, and code highlighting. Many of these are options that somewhat alter the way ViM is acting; they may be placed in your .vimrc if you want them to always be set, or can be set in any particular editing session. Let's look first at the options and then at the key commands.

Nice indentation - The default indentation for most text editors (including ViM) is a tab character. While that is very simple, it has the tremendous problem that when it is printed, a tab is expanded into eight spaces. That's quite ridiculous if you have code that has deep indentation. Here's a rather spiffy solution for this problem, using ViM that I strongly suggest you place in your .vimrc.
:set softtabstop=2
:set shiftwidth=2
:set noexpandtab
The ":set softtabstop=2" or ":set sts=2" tells ViM that when you press the tab key, it should insert 2 spaces. To any editing or viewing tools (including the printer), the tabs your insert are replaced with two space characters. However, while editing, ViM will treat both spaces as if they were one single tab character, allowing you to delete them in one stroke. ":set shiftwidth=2" or ":set sw=2" informs ViM that whever it performs any automatic indentation, such as the ">>" operation (see below), it should use only 2 spaces. Finally ":set noexpandtab" (which may not be required as it is the default) tells ViM that tabs should not be expanded into spaces while editing. If ":set expandtab" were used, ViM would not treat your tab-presses as single characters, but would expand them into spaces. All of these commands prevent you from adding the tab character if you need to (i.e. in a Makefile). If you ever need to enter an actual tab character, you need to specifically tell ViM this. While in Insert mode, press Ctrl-v and then press Tab to enter a tab character.

Syntax highlighting - Let's get a hands-on demonstration with this example. Please open one of the .c files you have been working on. Now, in ViM type
:syntax on
Isn't that pretty? ViM looks at the file extention to try to guess which type of syntax highlighting it should use, so if you open an html document, its highlighting will be different than a c header. You can also explicitly set the syntax highlighting system by using ":set syntax=java" (or some other file format). See ":help 'syntax'" for more information.

Numbered Lines - It's often useful to have quick access to line numbers, especially when debugging. For this feature, there is an option,
:set number
which will number every line. Note that the numberings require characters on the left, and your terminal will not resize itself. Luckily, if you've set wm to 4 or 5, you shouldn't have any wrapped lines. If this becomes a problem, you may be interested in the 'numberwidth' option (see help pages). How could we turn this option off?

Automatic Indentation - Though I don't use these parameters, you might find ":set smartindent" and ":set cindent" to be useful operations. The first tells ViM to indent after any lines that end with '{' or after certain keywords (such as for, while, etc.). It also matches the indent for a closing brace with its corresponding open brace. 'cindent' takes this formatting a step further, but is a bit more specific to c and c-like languages, especially dealing with their particular formating conventions and keywords.

As you likely have realized from your earlier experience, Unix facilities tend to favor several small, efficient programs rather than one large program. As such, ViM uses the standard gnu tools such as gcc, make, gdb, etc. To run these tools from within ViM, you can use the command-bang syntax (I don't know the real name of this sequence, but "command-bang" is a nice pnuemonic). Try the command
:!ls
Next, try the command-bang ls with some flags, such as "-l". Using command-bang tells ViM to execute the command in a new shell, which allows us to have access to the entire operating system from within ViM. For example, we could run firefox with
:!firefox &
As you will likely be using ViM to code, you will probably want to call your program and your compiler. For example, it's common to use the following
:!gcc progName.c -g -Wall -o progName
Which compiles the program at progName.c and outputs the resulting program to progName. You can then execute your program with
:!./progName
And, if you wanted to be really slick and you watch for compile errors, you could even try
:!gcc progName.c -g -Wall -o progName; ./progName
which performs all of these operations in a single step. As ViM provides a history, we can just type ":!" and up-arrow until we reach the command. It may be useful also to note that within execute mode, the '%' symbol represents the current file. Hence we could write the compile instruction as
:!gcc % -g -Wall -o progName


Warning: You will accidentally overwrite your .c file if you use "-o progName.c". Though you should be as careful as possible, ViM saves a "swap" file as you are working (of the form ".fileName.swp" so that if ViM closes unexpected, you can recover the changes you made. This swap file method also alerts you if the file you are working on has been overwritten, and allows you to return to the version of the file that you've been working on, which you can then save. I strongly suggest you don't rely soley on this mechanism, however, as the swap files are not intended for this use, and disappear after you end a ViM session.

Now we move on to in-program commands that are quite useful while editing. We begin with quick indentation, which you should remember from the Emacs lab. In the open c file, place your cursor anywhere on a line that is within a code block (i.e. within braces). Type
>>
Notice that the indent is equal to two spaces (or however much the shiftwidth option is set to). We can revert by using the reverse ("<<"). This is all quite nice, but often enough we'll need to indent many lines as functions tend to be multi-line entities. How do you think we could indent 5 lines using "<<"? How about 5000 (which will likely indent the rest of the file)? As shifting is a movement operation, we can perform it several times exactly how we did with other commands, i.e.
x>>
where x is the number of lines to indent.

Next, we note a very useful movement command, the match-paren command. Move to the opening bracket for a code block within your file. Please press
%
What just happened? It may not be immediately obvious if you are using syntax highlighting (because syntax highlighting also highlights the matching parenthesis), but try moving the cursor up or down to see where you are. Move back to the closing paren and press '%' again. How could we combine this with delete or copy?

Though '%' is pretty useful for moving through multi-functioned files, I find it most useful in conjunction with code-folding, a feature that condenses ("folds") multple lines of a text document into one so that you can stop worrying about their inner details. Move to the opening bracket for a function and type
zf%
Let's parse this command. The 'z' alerts ViM that it will be working with one of a series of fold-related (mostly) commands. See ":help z" for more information. The 'f' tells ViM that it should create a fold that includes all text passed over with the next movement command. Using '%' as a movement command folds the entire function and it moves the cursor to the opening brace's corresponding closing brace. Move your cursor to the fold, which is indicated by a "+--" at the beginning of the line and special highlighting. Now we open the fold with
zo
i.e. "fold-open". What do you think the corresponding "close" command would be? Yep, "zc" will close the fold. Try this command anywhere within the function to see how ViM responds. These folds will continue to exist only for your editing session, so if you split a file, you may use a different set of folds for each editing session. Folding is a very complex (though useful) feature. Please read ":help folding" for more specifics.

ModeCommandOutcome
Execute:set sts=[Value] Tabs will be treated as Value spaces
Ex. :set sts=4
Execute:set sw=[Value] Shifts (">>") will be treated as
Value spaces
Ex. :set sw=4
Execute:set expandtab Expands each tab press into as 'sts' spaces
Ex. :set noexpandtab
Execute:syntax [on/off] Turns syntax highlighting on or off
Ex. :syntax on
Execute:set syntax=[Value] Tells ViM which syntax to highlight
Ex. :set syntax=php
Execute:set number Turns line numbering on
Execute:set smartindent Tells ViM to use "smart indenting" which
includes indenting after certain characters
(like '{'). See help page for more
Execute:set cindent Tells ViM to use "c indenting" which includes
the indentation in 'smartindent' as well as
after certain c keywords and structures. See
the help page for more
Cmd-Bang:![Command] Execute the external Command
Ex. :!ls -a lists all files in the current directory
Cmd-Bang:!gcc progName.c -g -Wall Uses the external gcc to compile progName.c
Ex. :!gcc calc1.c -g -Wall
Cmd-Bang:!./progName Runs the file, progName, which is in the
current directory
Ex. :!./a.out runs the output of gcc
Cmd-Bang% Used as a placeholder for the current file's name
Ex. :!echo % prints the file name
Commandx>> Shift the next x lines 'sw' characters right
Commandx<< Shift the next x lines 'sw' characters left
Command% Move to the matching paren/brace
Commandzf[Movement] Make a new fold of the next Movement lines
Ex. zf} creates a fold of the next paragraph
Commandzc Closes the fold that the cursor is in
Commandzo Opens the fold that the cursor is on
Insert<Ctrl-v>[Key] Insert the leteral Key character
Ex. <Ctrl-v><Tab> inserts a tab character


A List of Some Other Useful Features

The following is a list of spiffy features and a short explaination. Please look at Further Sources for more information.

Further Sources

Many of the examples were borrowed and modified from the examples given in vimtutor, a program that is installed with vim that provides a (somewhat outdated) tutorial on how to use ViM. For more information, run vimtutor from the terminal.

Of course, a wonderful place to read more information about ViM is ViM's website, which includes links to the online documentation (including help files), information on how to join the mailing lists (and as questions, and a wide variety of ViM Scripts.

Bram Moolenaar (creator of ViM) gave a Google TechTalk titled 7 Habits for Effective Text Editing, which is really quite awesome. It describes an array of useful features within ViM and discusses a bit of the editor's philosophy.

Two of the most useful ViM resources are right on this campus! I'd like to thank Dr. Rebelsky and Dr. Davis for their help on this project and mention that they are huge resources of ViM knowlege. If you want to know how to do something and you aren't sure how to search for the proper solution, odds are one of these fine folks will be able to point you in the right direction.

Table of Discussed Commands

ModeCommandOutcome
Any<Escape>Enter Command mode
CommandiEnter Insert mode
ModeCommandOutcome
Any<Arrow Keys> Move the cursor in the direction pointed by the arrow key
Any<Page Up/Down> Move the cursor one page up or down
Any<Home/End> Move the cursor to start or end of a line
CommandwMove forward one word
CommandbMove back one word
Command)Move forward one sentence
Command(Move back one sentence
Command}Move forward one paragraph
Command{Move back one paragraph
Commandx[movement] Move movement x times
Ex. 15} moves us 15 paragraphs forward
Commandc[movement] "Change" - Deletes everything within the next movement away and enters insert mode
Ex. c3w deletes the next 3 words and enters insert mode
ModeCommandOutcome
Commandd[movement] Delete movement and add them to the buffer (described in section 5)
Ex. d4) deletes 4 sentences
Commandxd[movement] Equivalent to dxmovement
Commandu Undo previous changes (i.e. move back through undo history)
Command<Ctrl>-r Redo previously undone changes (i.e. move forward through undo history)
Command0Equivalent to <Home>
Command$Equivalent to <End>
Commandxx Delete x characters and add them to the buffer (described in section 5)
Ex. 5x deletes 5 characters
Commandx~ Changes the case of the next x letters, non-letters (whitespace, numbers, etc.)
Ex. 15~ reverses the case of the next 15 letters
ModeCommandOutcome
Commandr[key] Replace the character under the cursor with [key]
CommandREnter Replace mode
Command<Insert>Enter Insert mode
Insert<Insert>Enter Replace mode
CommandA Append - Move cursor to end of current line and enter Insert mode
Commando Open - Create a new line under the current line, move the cursor to it, and enter Insert mode
CommandO Open - Create a new line above the current line, move the cursor to it, and enter Insert mode
ModeCommandOutcome
Commandxdd Delete x lines and place them in the buffer Similar to "cut"
Ex. 5dd deletes the next 5 lines
Commandxcc Delete x lines and enter Insert mode
Ex. 2cc deletes the next 2 lines and enters Insert mode
Commandp Place whatever is in the buffer ("clipboard") after the cursor. If the buffer contains a line or more, place the contents of the buffer on the line following the current line.
CommandP Place whatever is in the buffer ("clipboard") before the cursor. If the buffer contains a line or more, place the contents of the buffer on the line above the current line.
Commandy[movement] Yank movement (add it to the buffer) Similar to "copy"
Ex. y4w yanks 4 words
Commandxyy Yanks x (places them in the buffer) Similar to "copy"
Ex. 5yy yanks the next 5 lines
ModeCommandOutcome
Execute:xJump to line x
Execute:w [filename] Write ("save") curent editing session to filename. If no filename is specified, write to the document associated with this session (the last file written to, opened from, etc.)
Execute:q Quit the current editing session. ViM will not quit if you have not saved.
Execute:wq [filename] Write ("save") curent editing session to filename and then quit. If no filename is specified, write to the document associated with this session (the last file written to, opened from, etc.)
Execute:e [filename] Edit - Open filename using the current editing window. This closes the current file.
Execute:[command]! [arguments] Force - Perform the command regardless of any rammifications
Ex. :q! Quits the session whether or not the file has been saved.
Execute:[command]a [arguments] All - Perform the command to all open windows
Execute:split [filename] Opens a new editing session in a new "window" to edit filename. If filename is blank, open the current document.
Command<Ctrl>-w <Ctrl>-w Move cursor to next window (vertically)
Execute:help [keystroke] Shows help for given keystroke in new window. If no topic is given, show generic help screen.
Execute:help :[command] Shows help for given command in new window. If no topic is given, show generic help screen.
Execute:help [topic] Shows help for given topic in new window. If no topic is given, show generic help screen.
ModeCommandOutcome
Command/[searchTerm] Searches forward for regular expressions that match searchTerm and places cursor on the next match
Command?[searchTerm] Searches backward for regular expressions that match searchTerm and places cursor on the next match
Command* Searches forward for the word that is currently under the cursor
Commandn Place cursor on next match for the most recent search
CommandN Place cursor on previous match for the most recent search
Execute:set ignorecase In all searches/regular expressions, be case insensitive
Execute:set noignorecase In all searches/regular expressions, be case sensitive (Default)
Execute:s/oldWord/newWord/g Replace all oldWords with the newWord on this line
Execute :%s/oldWord/newWord/g Replace all oldWords with the newWord in this file
Execute :%s/oldWord/newWord/gc Replace all oldWords with the newWord in this file, asking for confirmation on each entry
ModeCommandOutcome
Execute:set option Set the boolean option, option to true
Ex. :set ignorecase
Execute:set nooption Set the boolean option, option to false
Ex. :set noignorecase
Execute:set option=[Value] Set the option, option, to [Value]
Ex. :set wm=5
Execute:set ignorecase Ignores case while searching
Execute:set mouse=[Value] Allows the mouse to be an input in Value is "a", or nothing if Value is ""
Ex. :set mouse=a
Execute:set wm=[Value] Set the word margin (the character position from the right at which point ViM wraps words) to Value
Ex. :set wm=5
Execute:set bg=[Value] Tell ViM the terminal's background color so that it may highlight appropriately
Ex. :set bg=dark
Execute:set bs=[Value] Tell ViM how to deal with backspaces. Value can be either a comma separated list or a numeric value (see help pages)
Ex. :set backspace=2
Execute:set ww=[Value] Informs ViM which characters wrap around a newline. See the help pages for specifics
Ex. :set ww=b,s,<,>,[,]
Execute:set autoindent If this option is set, whenever you press [Enter] or open a new line, the indentation
of the previous line is used for the new line
ModeCommandOutcome
Execute:set sts=[Value] Tabs will be treated as Value spaces
Ex. :set sts=4
Execute:set sw=[Value] Shifts (">>") will be treated as Value spaces
Ex. :set sw=4
Execute:set expandtab Expands each tab press into as 'sts' spaces
Ex. :set noexpandtab
Execute:syntax [on/off] Turns syntax highlighting on or off
Ex. :syntax on
Execute:set syntax=[Value] Tells ViM which syntax to highlight
Ex. :set syntax=php
Execute:set number Turns line numbering on
Execute:set smartindent Tells ViM to use "smart indenting" which includes indenting after certain characters (like '{'). See help page for more
Execute:set cindent Tells ViM to use "c indenting" which includes the indentation in 'smartindent' as well as after certain c keywords and structures. See the help page for more
Cmd-Bang:![Command] Execute the external Command
Ex. :!ls -a lists all files in the current directory
Cmd-Bang:!gcc progName.c -g -Wall Uses the external gcc to compile progName.c
Ex. :!gcc calc1.c -g -Wall
Cmd-Bang:!./progName Runs the file, progName, which is in the current directory
Ex. :!./a.out runs the output of gcc
Cmd-Bang% Used as a placeholder for the current file's name
Ex. :!echo % prints the file name
Commandx>> Shift the next x lines 'sw' characters right
Commandx<< Shift the next x lines 'sw' characters left
Command% Move to the matching paren/brace
Commandzf[Movement] Make a new fold of the next Movement lines
Ex. zf} creates a fold of the next paragraph
Commandzc Closes the fold that the cursor is in
Commandzo Opens the fold that the cursor is on
Insert<Ctrl-v>[Key] Insert the leteral Key character
Ex. <Ctrl-v><Tab> inserts a tab character


Written by C.M. Lubinski, January 2008, with help from Marge M. Coahran, Janet Davis, Samuel A. Rebelsky, Christine Gerpheide, Emily Jacobson, Nick Hecker, Tony Leguia, and Ian Young. This document is licensed under a Creative Commons Attribution-ShareALike 3.0 United States License