Troubleshooters.Com Presents

Linux Productivity Magazine

Volume 1 Issue 5, December 2002
VI and Vim

Copyright (C) 2002 by Steve Litt. All rights reserved. Materials from guest authors copyrighted by them and licensed for perpetual use to Linux Productivity Magazine. All rights reserved to the copyright holder, except for items specifically marked otherwise (certain free software source code, GNU/GPL, etc.). All material herein provided "As-Is". User assumes all risk and responsibility for any outcome.

See also Troubleshooting Techniques of the Successful Technologist
and Rapid Learning: Secret Weapon of the Successful Technologist
by Steve Litt

[ Troubleshooters.Com | Back Issues ]

In pursuit of the dubious goal of producing idiot-proof, zero-learning-curve programs, even programs intended for heavy-duty use such as editors--arguably the most important piece of software you'll use--have been turned into children's toys, effectively expert-proofed. -- Tom Christiansen
(discussing alternatives to VI in his article,  "Zenclavier: Extreme Keyboarding")


Editor's Desk

By Steve Litt
I hated VI the first time I used it. So to avoid using VI, I created a script to ftp a file from the HP9000 down to my Win98 box, edit it with a Windows editor, and ftp it back up. VI's arcane and non-intuitive keystrokes, plus its silly two mode construction were productivity killers.

A couple years later I started using Linux, and naturally chose a different editor -- the Wordstar like Joe. That might have continued forever if Dillon Jones hadn't bragged about Vim, the VI workalike common on Linux boxes.

Dillon was a fellow LUG member, and every chance he got he showed off a new script, function or trick in Vim. He had a script to convert Vim to an HTML authoring tool. With a few keystrokes he could convert a directory listing into a data file or a computer program. I decided to reinvestigate VI.

And fell in love. I've used all sorts of editors, but VI is by far the fastest and most powerful. And this fact is one of the world's best kept secrets. All too many people draw the conclusion I originally drew -- that VI was some silly kludge hacked together by 1970's spaghetti programmers.

It's an easy conclusion to draw. Who would guess to press "l" to go right. Shouldn't "l" go left? What in the world is the rationale for using "h" to go left? One would think "h" would mean "higher" or some such thing. "j" and "k" for down and up respectively is just plain weird. And how strange is the 2 mode system, where the insert mode is for typing, and the command mode is for editing, necessitating constant switching between them. Many VI implementations cannot even facilitate a mouse, nor can they highlight text with the Shift+Arrow hotkey, nor skip words with Ctrl+Arrow. As a modern software developer I've been trained to make my apps intuitive.

But anyone who has been around the block a few times knows there's a tradeoff between beginner's intuitiveness and master's productivity. VI has been optimized entirely for the touch typist. l, h, j and k are easily touch typing home position accessible. Cursor (arrow) keys are not. In the time you can move your hand from the keyboard to the mouse, a VI master can cut the current paragraph and move it above the preceding paragraph. (Keystrokes {d}{P). VI is built exclusively for speed. Well, almost exclusively.

VI is built for power too. By combining VI's range enabled global commands, range enabled search and replace commands, regular expressions, macros and scripts,  you can effect almost any conceivable transformation on a file. If  the transformation can be described in English, it can be done with VI. And in VI it usually can be done in 1/10 the time required to write a program to perform the same transformation.

Speed and power. Life can't get any better.

OH YES IT CAN! You can also have ubiquity. Every system with UNIX, a UNIX variant or a UNIX workalike operating system has VI installed. Once you're good at VI, you can walk into any UNIX installation and get to work, without the need to learn a new editor or install your favorite editor. And once you're really good at VI, it will probably become your favorite editor.

Speed, Power and Ubiquity. This issue of Linux Productivity Magazine details everything you need to know to achieve top notch speed and power with this ubiquitous editor. Also discussed is the ultra-powerful Vim superset of VI. Vim has a programming language all its own, including functions. Vim is so powerful that a professional grade outline processor, called VimOutliner, has been created using a few Perl scripts and some Vim scripts. One article of this magazine is devoted to VimOutliner.

So kick back, relax, and learn how to make VI, Vim and VimOutliner work their magic. And remember, if you use Open Source or free software, this is your magazine.
Steve Litt is the author of Samba Unleashed.   Steve can be reached at Steve Litt's email address.

The Accuracy of This Document

By Steve Litt
The biggest problem in writing this magazine is the fact that there are many different implementations of VI, and 98% of my VI use has been with the Vim implementation (HP9000 UNIX VI and Elvis make up the other 2%). So I'm sure some of the features I attribute to VI are really Vim specific.

I had a choice to make with my limited time. The magazine could describe a tiny subset of VI functionality and rigorously check various VI versions, or it could document a much larger functionality set while I tried my best to remember whether other VI implementations support the various features.

I chose the latter. First, Vim is probably the most used VI implementation. And second, most readers can forgive a few described features not available in their VI implementation in order to learn VI's powerhouse techniques.

So if your VI doesn't support a particular feature (the \| alternative in regular expressions, for instance), try to find another way to do it (macros, for instance).
Steve Litt is the author of " Troubleshooting Techniques of the Successful Technologist".  Steve can be reached at Steve Litt's email address .


By Steve Litt

GNU/Linux is comprised of the Linux kernel originally crafted by Linus Torvalds, plus many, many utilities, a large number of which were utilities from the original GNU project. "GNU/Linux" is probably the most accurate moniker one can give to the operating system. Please be aware that in all of Troubleshooters.Com, when I say "Linux" I really mean "GNU/Linux". I completely believe that without the GNU project, without the GNU Manifesto and the GNU/GPL license it spawned, the operating system the press calls "Linux" never would have happened.

I'm part of the press and there are times when it's easier to say "Linux" than explain to certain audiences that "GNU/Linux" is the same as what the press calls "Linux". So I abbreviate. Additionally, I abbreviate in the same way one might abbreviate the name of a multi-partner law firm. But make no mistake about it. In any article in Linux Productivity Magazine, in the whole of Troubleshooters.Com, and even in the technical books I write, when I say "Linux", I mean "GNU/Linux".

There are those who think FSF is making too big a deal of this. Nothing could be farther from the truth. The GNU General Public License is the only reason we can enjoy this wonderful alternative to proprietary operating systems, and competition from Free Software is the only reason proprietary operating systems aren't even more flaky than they are now. Last but not least, it's significant to note that in Infoworld's October 6, 2000 article entitled "E-business innovators", author Mark Leon named GNU's Richard Stallman as the innovator associated with GNU/Linux.

Steve Litt is the author of Rapid Learning: Secret Weapon of the Successful Technologist. He can be reached at Steve Litt's email address.


By Steve Litt
We all stand on the shoulders of those who came before us, and this Linux Productivity Magazine is a perfect example. Certainly Ken Thompson deserves thanks for creating UNIX, the original platform on which VI originated. Had Richard Stallman not created the GNU Manifesto and GNU GPL license, GNU/Linux wouldn't exist and I'd still be using PFE shareware on Windows. For the same reason, Linus Tovalds must be thanked.

Thanks to Bram Moolenaar for creating the Vim implementation of VI. Vim is standard on all Red Hat and Mandrake  systems, and probably many others. Vim is one of VI's greatest ambassadors, running on Linux, Windows, Mac, OS/2, UNIX, and even the Amiga. And Vim's feature set is so great that, frankly, I'm spoiled.

Thanks to the entire Open Source community for making such great software. And a big thankyou to my fellow VimOutliner developers, Noel Henson and Matej Cepl, for taking VimOutliner from an "army surplus" app to a full featured outline processor.
Steve Litt documented the Universal Troubleshooting Process. Steve can be reached at Steve Litt's email address.

VI Life Preserver

By Steve Litt
This article is designed for the person who has never before used VI. Specifically, the newbie using this article won't get caught in a situation where he can't get out of the program. And he'll be able to open and save files, maneuver around the file, and perform basic edits. The person familiar with this article can go to any VI equipped computer and edit files, although such editing won't be particularly efficient. Subsequent articles bestow efficiency.

Getting In and Out of VI

Getting into VI is easy. At the command prompt, just type vi and press Enter. Or, if you want to use VI to edit a specific file called myfile, at the command prompt type vi myfile and press the Enter key. Once in VI, the following commands are available to retrieve files, save files, get help and get out:

Gets you out of insert mode. Commands must be performed from command mode, not from insert mode. Pressing Esc while in command mode does nothing and is harmless. Be sure you're in command mode before trying the following commands. When in command mode the cursor is fat and covers one character. When in insert mode the cursor is skinny and is between two characters.
:q! Gets you out of VI no matter what. No files are saved.
Saves the file and quits VI.
Saves the file and keeps you in the VI editor.
Quits VI if the file is up to date. If there are unsaved changes you are kept in VI.
:e myfile
Places file myfile in the VI editor
Goes into help mode. You get out of help mode with the :q command.
:h myfeature
Goes into help mode and looks up any help on feature myfeature. If there's no help on myfeature, it errors out and doesn't go into help mode.

The preceding commands are all you need to get into VI, get back out, and edit a specific file.

Moving Through the File

Before you can do any real editing, you must be able to move through the file. The following is a small subset of the commands with which you can move through the file. Remember once again you must be in command mode to run these commands. You can move from insert mode to command mode with the Esc key.

l (lower case L)
Cursor one character right
Cursor one character left
Cursor one line down, staying in the current column. In other words, if you were on the 14th character of line 5 when you pressed j, the cursor would end up on the 14th character of line 6. If line 6 has less than 14 characters, the cursor will be on the last character in line 6.
Cursor up one line. The k command works the same as j only up instead of down.
Cursor one word right. This command wraps at the end of a line.
Cursor one word left. This command wraps at the beginning of a line.
Cursor to end of file
Cursor to start of file. On VI implementations without the gg command, use 1G
Cursor down 100 lines. Naturally, that number can be any number you choose. You can also precede k with a number to move up that many lines. This same technique can be used to move several characters (100l or 100h), or several words (100w or 100b).
Tells you your current line number, so you can estimate how far you need to jump or move.
Cursors to line 52 from anywhere in the file. Naturally, that number can be any desired destination line. Note that on some implementations you can do this as 52gg, which might be easier for some keyboarders.
Move down (forward) one screenful of lines.
Move up (backward) one screenful of lines.
Move down 1/2 screenful of lines.
Move up 1/2 screenful of lines.

The preceding is a list of basic, essential moves. There are many more. In Vim, use the :h motion.txt command to learn the rich variety of motion commands. And there are moves based on searches. The next section of this article covers basic searches.

Basic Searches

This section covers VERY basic searches. VI searches can be incredibly powerful and complex, because they incorporate regular expressions. This article does not cover search and replace, because in VI search and replace is extremely powerful, and is implemented differently from plain searches.
:set ic
Sets VI to ignore case in all searches and replaces. All subsequent searches are case insensitive.
:set noic
Sets VI to consider case in all searches and replaces. All subsequent searches are case sensitive.
Search for the next instance of Steve in the file. In other words, search down from the cursor.
Search for the previous instance of Steve in the file. In other words, search up from the cursor.
/web *master
Search for webmaster, web master, or web          master. This is a very basic regular expression that means "look for web, followed by zero or more spaces, followed by master. Such regular expressions also can be used with the ? to search backwards. The asterisk means "zero or more of the preceding character", and the preceding character in this case is a space.
Search down for the next occurrence of whatever you searched for last.
Search up for the next occurrence of whatever you searched for last.
Repeat the previous search, in the direction of the previous search.
Repeat the previous search, in the opposite direction of the previous search.

As an added benefit, many VI implementations including the Vim VI implementation give you a search history. Press the slash key (/) followed by the up arrow, and you'll see the history of all your searches, both forward and backward. If you want to search backwards for something in your history, press the question mark (?) and then the up arrow. If you go too far with the up arrow, you can return with the down arrow. If you're familiar with the command history provided by the bash shell, it's very similar.

This section has provided you with a minimal set of search commands with which you can maneuver the file.

Inserting Text

There are probably 20 commands to insert text, and the truly efficient VI user knows and regularly uses most of them. However, only a few are necessary. Strictly speaking, you could do everything with the i command (Insert before the current character). You could navigate to the character before which you want to insert, and the press i  key. Use of only the i key would preclude easily inserting at the end of a line. What you'd need to do is navigate to the end of the line, press the i key, insert the character previously at the end of the line, insert text you want to insert, return from insert mode, and then delete the extra end character. Ugh!

That's why VI has the insert after (a) command, which inserts after the current key. So you'd maneuver to the end of the line, press the a key, and type what you want at the end of the line.

Here is a summary of enough insert commands to make your life easy:

Return from insert mode to command mode.
Insert before the current character. Observe that this gives you no convenient way to insert at the end of the line.
Insert after the current character. Observe that this gives you no convenient way to insert at the beginning of the line.
Insert at the beginning of the line.
Insert at the end of the line. This is needed often and is a real time saver.
Open a brand new empty line below the current one, and position the cursor at the start of that line, in insert mode.
Open a brand new empty line above the current one, and position the cursor at the start of that line, in insert mode.

The preceding set of commands is by no means exhaustive, but it's enough to work with some efficiency in VI.

Deleting Text

VI gives you two ways to delete -- You Asked For It, You Got It (YAFIYGI) and What You See Is What You Get (WYSIWYG). Each has its benefits. In general, go YAFIYGI for small deletions, and WYSIWYG for large or complex ones. Obviously, WYSIWYG is safer, and YAFIYGI is often faster. I use both regularly. Remember also that almost all VI implementations have at least one level of undo, so it usually isn't the end of the world if you blow a delete.

You Asked For It, You Got It

Here are some of the most used YAFIYGI commands:

Undo the previous command. Very handy to correct a blown delete. Many VI implementations have multiple levels of undo. Some such implementations use a succession of u commands to do more undos, and Ctrl+R commands for redos in case you undo too far. Other implementations use u for the first undo, and Ctrl+R commands for subsequent undos. The latter, although bizarre, is the "true VI way". Your best bet is to be alert enough that you never need more than a single level of undo.

Note that if you save often, you can always revert to the last saved version.
Revert to the last saved version of the current file.
Delete the character under the cursor. The cursor comes to rest on the character following the deleted one, or if the deleted character was the final character on the line, the character before the deleted one.
Delete the character to the left of the cursor. The cursor stays on the current character.
dd Delete the current line so that the cursor is placed on the line following the one deleted.
D Delete current character and everything to the end of the current line.
Delete everything to the left of the cursor.
Delete the current line and everything below. (Careful!)
Delete the current line and everything above. (Careful!)

What You See Is What You Get

WYSIWYG deletes are safer because you can review what you'll do before you do it. Here are the commands to perform WYSIWYG deletion:

Begin highlighting lines of text. Use j, k, or other move commands discussed previously to extend the highlighting.
Delete the highlighted text


VI is an incredibly rich and powerful editor. There's no way to learn the whole thing at once. But by mastering how to start VI, how to quit it, how to load, save and quit files, and a few commands to move around, insert text and delete text, you'll be able to get into the game. By mastering the contents of this article, you'll be able to walk into any UNIX shop and use the editor without looking like a total newbie.

That being said, VI offers MUCH more. Its power is almost magical. Read on...
Steve Litt is the author of the Universal Troubleshooting Process courseware.   Steve can be reached at Steve Litt's email address.

Search and Replace: Substitute and Global Commands

By Steve Litt
This article reviews the mechanics of the search and replace commands: Substitute commands, Global commands, and combinations of the two. To keep it simple, this article contains no regular expressions, so naturally all its examples are academic rather than real-world. An article later in this magazine details regular expressions, which, when combined with the information in this article, gives you complete power over a file.

The simplest search and replace occurs on a single line. For instance, to replace the first instance of "Windows" with "Linux", use the following command:
The colon puts you in EX mode, which is what you use for search and replace, as well as global commands and many other commands.

In some VI implementations, the EX mode has a history feature similar to the bash shell. After pressing the colon character, you can use the up arrow to recall previous commands, and the down arrow to go back to later commands if you go too far back.

The s stands for "substitute", because that's what you're doing. The first forward slash signifies the beginning of the search expression. The second backslash signifies the end of the search expression and the beginning of the replace expression. The third backslash signifies the end of the replace expression.

In many VI implementations you don't need to use the slash character as the expression delimiter. You can use most non-alphanumeric characters (but not \, " or |). This is very handy when working with UNIX filenames, as in the following example:
Whatever character follows the :s is defined to be the delimiter character. If your implementation doesn't support this, you can represent slashes in search and replace expressions by escaping them with backslashes, as follows:
As you can see, the escaping method is much less readable, so if you can use alternative delimiter characters, it's a good idea.

Recalling the substitute command:
The preceding simple command replaces only the first instance on the line. Sometimes that's what you want, and sometimes it isn't. Often you want to replace all occurrences on the line. In that case, append the letter g (stands for Global) after the close of the replace expression, as follows:
Perhaps you're replacing ten or so instances, and you want to make sure you really want to replace each one. In most VI implementations you can use the letter c (stands for Confirm) at the end, in which case before each replacements you'll be asked yes or no:


So far we've discussed search and replace on a single line, which is pretty useless because on a single line it might be faster to search and replace manually. The real power comes when you search and replace over a range of lines. You declare the range before the s command. By far the most common range is "all lines in the file", which is represented by the percent sign, as follows:
Due to the percent sign before the s, the preceding replaces every instance of "Windows" with "Linux" throughout the entire file. Please remember, the g on the end means "every instance on the line", and the percent sign at the beginning means "every line in the file", so combined they mean "every occurrence on every line", which works out to "every occurrence in the file". Either the % and g can be used without the other, or they can both be used together.

You can use other ranges, as described in the following table:
Runs the substitution command on lines 4 through 7 inclusive.
:4;7s/Windows/Linux/ Runs the substitution command on line 4, and the 7 lines following it. Note the distinction between the semicolon version, which calculates the second value relative to the first.
:4s/Windows/Linux/ Runs the substitution command on line 4 only.
:4,$s/Windows/Linux/ Runs the substitution command on lines 4 through the file's last line, inclusive. In line ranges, the  $ character represents the last line in the file.
:4,.s/Windows/Linux/ Runs the substitution command on lines 4 through the line the cursor is on, inclusive. In line ranges, the . character represents the current line.
:.,2000s/Windows/Linux/ Runs the substitution command on the current line through line 2000 inclusive. This shows that the dot can be used as the beginning, or as the end of a range.
:.,.+3s/Windows/Linux/ Runs the substitution command on the current line through the line three below the current line inclusive. In other words, this line plus the next three. In general, you add and subtract from a range value by appending a plus and number, or a minus and number. Be careful not to go too far or too short by one -- it's easy to do.
.,+3 :.,+3s/Windows/Linux/ CAREFUL!!! This produces the identical result to the preceding example, even though we removed the dot in the range end expression. In a + or - expression, if what it's relative is not explicitly declared, it defaults to "current line". This can lead to confusion. Use the version with the dot.
:/My_Opinion/,$s/Windows/Linux/ Search forward for the next occurrence of My_Opinion, and run the substitution on that line through the end of file, inclusive. Note that the search will not find matches on the current line.

Searches in Ranges

The final example in the preceding table shows a search in a range. This makes VI incredibly powerful, and if done casually incredibly dangerous. But here let's discuss the power. A search can appear in either the range start expression, the range end expression, or both. The search can be forward or backward. The line found by the search can be added to or subtracted from.

If you have wrapscan set, searches in ranges can do some strange things. A forward search can fail to find the string by end of file, wrap back up, and find one above where you are. Likewise, a backward search can wrap around the top and find a match below you. These typically are not what you want.

To make your results more predictable, before running commands with searches in ranges, turn off wrapscan with the following command:
:set nowrapscan
Later, if you want to restore wrapscan so you can find a pattern anywhere in the file, restore it with this command:
:set wrapscan

Remembering to set nowrapscan, see the following examples:

:/My_Opinion/,$s/Windows/Linux/ Search forward
Search forward from the current line to the next line containing "My_Opinion", and from that line to the end of file substitute "Linux" for "Windows". The search WILL NOT match any "My_Opinion" on the current line, and instead will match the next downward occurrence of "My_Opinion".
:?My_Opinion?,$s/Windows/Linux/ Search backward
Search backward from the current line to the next line up containing "My_Opinion", and from that line to the end of file substitute "Linux" for "Windows". The search WILL NOT match any "My_Opinion" on the current line. The search WILL NOT match any "My_Opinion" on the current line, and instead will match the next upward occurrence of "My_Opinion".
:1+/My_Opinion/,$s/Windows/Linux/ Search forward from line 1
The previous searches started from the current line, which may or may not be what you want. If starting the command with a known state is important to you, use this command form to start from line 1. Note that this will not find a match on line 1, so if that's an issue you'll need to run an additional command to get the lines you missed.
See comment
If the first line contains "My_Opinion", the preceding command did not substitute on that line or any lines until the next occurrence of "My_Opinion". You probably want those lines substituted. This command does that. Starting at line 2, it goes backward (you did set nowrapscan to prevent search wrapping, didn't you?), and if it finds "My_Opinion" on line 1, it alters line 1 and every line until, and including, the line before the next "My_Opinion", which presumably was fixed by the preceding command.


Consider the preceding range substitution:
Can you glance at that command and tell what it does? Not unless you're a true VimMeister. Personally, I'm not that good.

The classic early 1980's post titled "Real Men Don't Use Pascal" discusses the wonders of "You asked for it, you got it" (YAFIYGI) editors like DEC's TECO, in which a single wrong character can destroy the file. The preceding command just might involve just a little too much "you asked for it, you got it" risk for someone on a tight deadline.

When you need to play it safe, many VI implementations have something called Visual Mode, in which you can highlight a certain range of lines, and run a simple substitution on that range. For instance, in the Vim implementation, you'd go to the first line you want to change, press Shift+V, then use motion commands, such as j or a search, to move to the end of the range. Once the desired range is highlighted, you simply press the colon key, and then type s/Windows/Linux/ to make the change in the highlighted area.

Generally speaking, when you're making range changes in realtime, if you have Visual Mode available, you'll use it to simplify ranges.

And of course, when you want to show off at your LUG, you use the YAFIYGI method. After all, real men use TECO when they can, and if TECO isn't available, they use VI recklessly.

Global Commands

Real men and quiche-eating Pascal programmers alike love VI's Global commands. The real man can destroy an entire file with this 8 character command:
Or he can hide his tracks from quiche-eating Pascal Programmers by combining it with an obfuscatory substitute command like this:
If you're a Pascal Programmer (or the modern equivalent, a Java Jockey) interested in knowing what the preceding command does, click here. To real men the preceding is intuitively obvious to the most casual observer.

Quiche eaters also love Global commands. When the boss expects the huge production produced by quiche-eating rapid development techniques, your editing needs to be lightning quick. Consider how often you need to pick out only lines containing "whatever" from a huge file. Edit a duplicate copy of the file with VI, and run the following command:
The preceding command deletes every line not containing "whatever". But what if you need only lines containing "whatever" and "whichever"? Watch this:
Try it. Create a data file with lines consisting of either "whatever", "whichever" or "whyever". Then, so you can be assured that all lines are copied in the order they're found, prepend line numbers to every line with the following command:
:%!cat -n
Global commands are also an excellent way to perform a substitution on only a certain class of lines. The following changes the word "judgment" to "ripoff" on any line containing "microsoft antitrust":
:g/microsoft antitrust/s/judgment/ripoff/
The cool thing about the preceding is the word "judgment" can appear anywhere in relation to the word "microsoft antitrust", and yet the deed will be done. Perhaps you want to make the change anywhere near the word "microsoft antitrust", where "anywhere near" is defined as the line, or anything within 2 lines before it or 2 lines after it. Watch this:
:g/microsoft antitrust/-2,+2s/judgment/ripoff/c
You notice the c (for confirm) at the end? Any time you do anything as adventurous as the preceding, you want to check your work. It would be terrible to write an article and inadvertently change "I used my best judgment" to "I used my best ripoff".

The Anatomy of a Global Command

The following are how a global command is built. The first runs the command on every line within the range that matches the pattern. The second runs the command on every line within the range that DOESN'T match the pattern:
If the range is not given (and it usually is not), the default range is every line in the file. The concept is simple enough. The command is run on every matching (or non-matching with the exclamation point form) line. Where it gets more complex is when the command gets complex.

Real Life Global Commands

Certainly the simplest command is the delete command:
The preceding deletes every line with a pound sign. The following deletes every line that DOES NOT contain the pound sign:
The global command is often used to move certain classes of lines to a second file:
The preceding command appends all lines that don't start with 2 tabs. In a tab-indented outline, that would be the top 2 levels. The carat at the start of the pattern is a wildcard representing start of line, as will be explained in the article on regular expressions.

Another common command used with the Global command is the substitute command. In this case the substitute command substitutes based on a criteria totally different from the criteria by which the line is chosen. Typically the pattern by which the line is chosen can occur anywhere on the line in relation to the substitute command, so you cannot include the selection criteria in a single substitute command. Even when the selection criteria is predictable, the global command often simplifies it. Which would you rather do:
The latter command uses groups to "remember" the match, and places that remembered text in the replace text in the form of \1. Even the somewhat convoluted second form is not completely accurate, because if there are multiple instances of the word "slave", VI's native long matching will cause it to only change the last instance of "slave" on each line. Long and short matching are explained in the article on regular expressions.


Substitute and Global commands offer immense power, but that fact is not obvious from this article. After all, most examples in this article simply looked for one string and replaced it with another. Ranges added some power, and so did the one-two punch of a Global command whose command upon match is a Substitute command.

But until you introduce Regular Expressions, the Global and Substitute commands are just parlor tricks of a second rate magician. Regular Expressions transmogrify these commands into wizardry. Read on...
Steve Litt is the author of " Troubleshooting Techniques of the Successful Technologist".  Steve can be reached at Steve Litt's email address .

Regular Expressions

By Steve Litt
VI is the most powerful editor I've seen. It absolutely dwarfs the WordPerfect editor I loved for so many years. The person truly adept at VI can accomplish file translations and conversions typically requiring a computer program. Indeed, I've written Vim scripts that convert a VimOutliner outline to an htmlslides presentation. Another script reads an issue of Troubleshooting Professional Magazine or Linux Productivity Magazine and creates a table of contents that can be pasted into the magazine. Yet another converts a tab-indented outline into a LyX document. Yet another formats data pasted from my sales database into mailing labels. These are very simple scripts -- not a one is more than 20 lines.

Better yet, VI can be used on the fly to do work usually requiring programming. I've taken data files and converted them to a program to produce them. I've added, deleted and reordered fields in fixed length and comma delimited data files.

Regular expressions are a fundamental component of this power. Simply put, regular expressions are searchable expressions that match a class of strings in the file. As a basic example, the following VI search command:
matches "webmaster", or "web master", or "web      master", because \s represents a single character of any whitespace, and an asterisk means "zero or more of the preceding character". Here are some other examples:

Find the next vowel.
Find the next non-vowel letter.
Replace all instances of "Windows" with "Linux".
Exchange the first two fields in each row of a file of comma delimited records.
:s/\<\(.\)\([^[:space:][:punct:]]*\)\>/\u\1\2/g Capitalizes the first letter of every word on a line (title case converter)

That's some pretty serious power for the person expert at creating regular expressions. Entire books have been written about regular expressions. However, this article will give you the 10% to do 90% of what you need to do in VI.

Character Sets

A character set is a wildcard. When compared to a character, there is a match if the character is one of those in the character set. There are several types of character sets, but the most basic is a list of matching characters inside of brackets. For example, [aeiou] matches any lower case vowel. The list could be a range like [0-9], which matches any decimal digit. The brackets can contain a combination. For instance, [0-9.] matches any decimal digit or a decimal point (within brackets a dot is NOT a wildcard).

If the characters inside of the brackets start with a carat (^), the character set matches anything except the characters inside the brackets. So [^a-zA-Z] matches any character except a letter in the alphabet. If you actually want to match a carat, simply make it not the first character, as in [@^#], which matches either an at sign, a carat, or a pound sign.


A character set matches only a single character. It cannot match a phrase. It is only when character sets are grouped with other character sets, other characters, and iterators, that they can match phrases.

Many character sets are so common that VI shortcuts are provided for them. Here are some character set shortcuts:

Shortcut Equivalent
What it matches
\d [0-9] digit
\D [^0-9] Any character except a digit
\s [ \t\n\r] whitespace
\S [^ \t\n\r] Any character that is not whitespace
\w [a-zA-Z0-9] "word char" : i.e. alphanumeric, not space or punctuation
\W [^a-zA-Z0-9] "word separator" : i.e. space or punctuation, also not EOL or BOL
Lowercase letter. In the search expression it matches any lower case letter. In the replace expression it lowercases the character or character representer following it.
In the search expression \L matches any character except except a lowercase letter. In the replace expression it makes everything that follows it, to the end of the replace expression, lower case. However, a later \U in the replace expression ends its effect.
Uppercase letter. In the search expression it matches any lower case letter. In the replace expression it capitalizes the character following it.
In the search expression \U matches any character except except an uppercase letter. In the replace expression it makes everything that follows it, to the end of the replace expression, upper case. However, a later \L in the replace expression ends its effect.

What do you do if you need to match a control character like  a newline, carriage return, escape character or tab? In the UNIX world you could construct the unprintable by pressing Ctrl+V followed by the control character (Ctrl+M for the carriage return character, for instance). But that's ugly. A much better solution is to use the following character representers:

Character Representer
What it represents
The Escape character (decimal 27)
The Tab character
The carriage return character (looks like ^M in VI)
The Backspace character
The end of line character
Any character

There are also special strings that represent positions in a line instead of characters:

:s/^/cp / ^ Means beginning of line. This example "replaces" the beginning of line with cp followed by a space, creating a copy command from a directory listing. Note that when you "replace" a positional representer, there's nothing to replace, so you simply put the replaced text in the position represented by the positional representer.
:s/$/ backupdir/ $ means end of line. This example puts a space followed by backupdir at the end of the line, finishing the copy command you started with the carat example.
:s/\<sed/awk/g \< means a the word's beginning boundary. It is neither the first character of the word, nor the whitespace or punctuation before it, but instead an imaginary position between the two, or in the case where the word is at the start of the line, it exactly overlays ^. This example finds every word starting with the string sed and replaces that string with awk. But, for instance, it would leave the word "based" unharmed, because the string sed is not at the beginning of the word.
:s/\<sed\>/awk/g \> means a the word's ending boundary. It is neither the last character of the word, nor the whitespace or punctuation after it, but instead an imaginary position between the two, or in the case where the word is at the end of the line, it exactly overlays $. This example finds every word sed and replaces that word with awk. But, for instance, it would leave the word "based" unharmed, and also the word "sediment", because the string sed is not at both the beginning and end of the search pattern.

Because many characters are used as character representers, character set shortcuts, and other constructs, they are not available in regular expressions unless they're escaped. Here's a partial list of characters that must be escaped:

A literal period
A literal backslash
A literal forward slash. Note that because of the forward slash's role in regular expressions, this escape pattern must be used even in the replace section of search and replace regular expressions.
A literal carat. Normally a carat represents "beginning of line".
A literal dollar sign. Normally a dollar sign represents "end of line".

The VI character set shortcuts discussed so far are handy, but in addition to those, many VI implementations recognize Posix character set shortcuts, as shown in the following table:

[[:alnum:]]   letters and digits
space and tab characters
control characters
decimal digits
printable characters excluding space
lowercase letters (all letters when 'ignorecase' is used)
printable characters including space
punctuation characters
whitespace characters
uppercase letters (all letters when 'ignorecase' is used)
hexadecimal digits
the <CR> character
the <Tab> character
the <Esc> character
the <BS> character

Remember, a character set is a wildcard against which you can match a single character. You cannot use it to match a string or phrase, unless you use enumerators...


Enumerators apply to a single character -- the character or character set that precedes them in the regular expression. An enumerator declares how many of the preceding character will match.

The most general form of an iterator is:
The first number (n), is the minimum number of the preceding character needed to create a match. For instance,
A\{2, 4} matches AA, AAA, or even AAAAAAAAA, but it does not match a single A not followed or preceded by an additional A.

So you might wonder what the second number is. The second number is how far you skip before trying to find another match. For instance, take a string with 13 A characters in a row, preceded and followed by a space.
/A\{2,4} the first time

/A\{2,4} the second time

/A\{2,4} the third time

/A\{2,4} the fourth time (no match, because only 1 A remains)

The first time it matches the first 4 letters. The second time it matches the second four. The third time it matches the third four. Now it gets interesting. It doesn't match the last A because there's only one left. If there had been 14 A's instead of 13, it would have matched the last 2. So the last number is the maximum match, and the number it skips ahead to begin trying for the next match.

Remember also that the character being enumerated can be a character set. For instance, the following finds strings of 2 to 100 instances of whitespace (presumably to convert them to nothing, thereby squeezing out repeated spaces)
That brings up a good point. You really wanted 2 to infinity, not 2 to 100. Another way of saying 2 to infinity is 2 or more, and the enumerator for that is \{2,}. That matches 2 or more consecutive A characters, and matches all of them, so that subsequent matches won't match any more of that consecutive run.

Perhaps you want to match exactly two of a character. The enumerator for that is \{2}.

There are shortcuts for the most common enumerators, namely, 0 or more, 1 or more, and 0 or 1:

Equivalent enumerator
0 or more
1 or more
0 or 1

The following matches a traditional 10 digit phone number:
The preceding is read as follows:

An opening paren, followed by exactly three digits, followed by a closing paren, followed by zero or one instance of either a whitespace character or a dash, followed by exactly three digits, followed by a dash, followed by exactly four digits.

Armed with character sets and enumerators, you can search and successfully find simple to moderately complex patterns. But some things, like locating phone numbers whether or not they have area codes, and parsing of delimited lines, require more. Read on...

Using Matched Text as Replacement Text

Something that comes up with surprising regularity is the need to switch 2 parts of every line. For instance, consider a comma delimited data file. What if you need to switch the first and second fields? Here's how you do it:
Your first reaction might be that the preceding is ugly. That's true, but compare it to writing a program or creating a macro like you need to do in so many other editors.

Here's a character by character explanation of the preceding command:

Substitute on every line

Begin search expression

Begin a group. The group is ended by \). Everything inside a search expression group is remembered such that it can be used within the replace text.

A character set that matches everything EXCEPT a comma. In a comma delimited file, this is how you implement short matching so the match ends on the first comma.

An enumerator indicating zero or more of the character or character set that preceded it. In this case, it means zero or more non-commas. Those zero or more non-commas correspond to the first field in the line.

Ends the first group.

Matches a comma, which is the field delimiter in a comma delimited file.

Begins the second group

Zero or more non-commas corresponding to the second field

Ends the second group

Matches the comma that separates the second field from the third field

Begins the third group

Zero or more characters of any type. This represents the rest of the line. Because the only fields you're modifying are the first and second, you can group the third, fourth, ... fields together into one group -- the third group.

Ends the third group

Ends the search expression and begins the replace expression

The text that was matched by the second group of the search expression, which, in fact, was the second field, which we are now putting first

Literal comma to separate the first and second fields in the replaced text.

Text matched by the first group in the search expression, which we are now putting second.

Literal comma to separate the new second field from the third

Text matched by the third group in the search expression, which in fact represented all fields after the first two

Ends the replace expression

Study the preceding information. Once you understand the preceding, you understand most of what it takes to use search information in the replace expression. Here's another example -- a titlecase converter:
You might use this in a VI based book outline in order to titlecase all headings for later use as parts, sections, subsections, etc. Let's quickly analyze:

Substitute on every line

Start search expression

Matches position at beginning of word (between the space or punctuation preceding the word and the first alphanumeric of the word

Group containing the first character of the word

Begin second group

Series (zero or more) characters that are neither whitespace nor punctuation. This makes up the remainder of the word. This is discussed further in the Short Matching section of this article.

End second group

Matches position at end of word (between the last alphanumeric of the word and the punctuation or space following the word)

Ends the search expression and begins the replace expression

Means the next character or metacharacter will be capitalized

The text that matched the first group of the search expression. In this case that means the first character of the word, which due to the \u before it in the replace expression, means it's capitalized.

The text that matched the second group of the search expression. In this case that means the remainder of the word.

Ends the replace expression

Means global, meaning that you don't quit on the first match. This is what enables this title case converter to work on every word of the line.

Once again, review the preceding, especially noting the use of \< and \> to delineate words, the use of
[^[:space:][:punct:]]* to represent the remainder of a word, and the use of \u to uppercase the next item in the replace expression.

The following table lists several pieces of syntax used when you use matched text in the replacement:
Delineates a group. Whatever matches the expression inside the \( and \) is remembered and available in the replace expression. In this example, any series of 5 characters matches the expression inside the \( and \).
Used inside the replace expression, this is replaced by the text matched by the first group in the search expression.
Used inside the replace expression, this is replaced by the text matched by the second group in the search expression. Likewise \3 is replaced by the text matched by the third group, \4 by the text matched by the 4th group, all the way up to \9.
Used in the search expression, this matches any upper case letter. Used in the replace expression, this uppercases the next single item in the replacement expression.
Used in the search expression, this matches any lower case letter. Used in the replace expression, this lowercases the next single item in the replacement expression.
Used in the search expression, this matches any character that IS NOT an upper case letter. Used in the replace expression, this uppercases the remainder of the replacement expression. However, a later \L in the replace expression will "turn off" the \U at the point of appearance of the \L.
Used in the search expression, this matches any character that IS NOT a lower case letter. Used in the replace expression, this lowercases the remainder of the replacement expression. However, a later \U in the replace expression will "turn off" the \L at the point of appearance of the \U.

Using matched text is one of VI's most powerful features. Many other word processors require you to write a macro in order to accomplish similar things. Of course you could write the same types of macros in VI, but once you get used to regular expressions it takes only 1/4 to 1/10 the time.

Short Matching

Consider the following sentence:

I will roll the wheel from the whalebelly to the well.

Let's say you want to find every string that begins with w and ends with ll, replacing it with XXX. You want the line changed to the following:

I XXX roll the wheel from the XXXy to the XXX.

How bout this:
The g on the end means global, meaning keep finding and replacing after finding the first one. Unfortunately, the preceding regex will instead produce the following:


What happened? Unless told otherwise, regular expressions match as much as possible. So it found the first w (the one in will), and the last ll (the one in well), and replaced them, and everything in between, with XXX. How would you make the matches as short as possible?  Some environments, such as Perl, have special modifiers enabling enumerators to match as short as possible. This isn't available in many VI  implementations.

What's needed is a way to limit the scope of the enumerator. Consider the following:
This is much closer, producing the following:

I XXX roll the wheel from the whalebelly to the XXX.

It found "will" and "well", but missed "whalebell". What happened is the first "l" in "whalebelly" reset the search, so that the search went back to searching for "w", moving all the way to the last word of the line.

If we can agree that we should match long on a per word basis (in other words, "wellwall" will be replaced by XXX and not XXXXXX), we can limit by word boundaries instead of the "l" character:
The preceding produces the desired:

I XXX roll the wheel from the XXXy to the XXX.

If you want full short matching ("wellwall" replaced by XXXXXX), you need to use advanced techniques involving groups.
Steve Litt is the author of Rapid Learning: Secret Weapon of the Successful Technologist . He can be reached at Steve Litt's email address.

Advanced Searches with Groups

By Steve Litt
I wouldn't blame you for skipping this article. It's brutal, and for 90% of your editing activities you won't need its power. Indeed, what you can do with groups in a regular expression would be difficult for a good programmer using C (unless he was using regular expressions).

Let's say you want to find a phone number. Look at all the ways phone numbers can be written:
These don't include putting 1- in front -- it can be done but I want to keep this example understandable. How can you write a single search expression to find all of these different methods?

The first thing to notice is that everything except the area code is simple:
As things get hairy, it's important to note that the last 8 characters are a "gimme".

If you notice, either you have an area code plus optional dash or space between it and the exchange, or you don't. So you make a group to hold the area code, its parens or lack thereof, and option dash or space. We already discussed groups in the Using Matched Text as Replacement Text section of this article, where we used it to capture text for later use in the replace expression. The more powerful use is to create incredibly versatile searches, such as detecting all these different phone number formats.

So anyway, we can start by dreaming of a group containing area code, optional parens, and an optional trailing separator, and prepending it onto the search for the exchange and 4 digit number:
Following in the footsteps of programmers since the dawn of time, let's simply forget about the last 7 digits and concentrate on the area code group.

One thing you know is the area code has it has parentheses or it doesn't. The other punctuation depends on whether it has parentheses. If it has parentheses you look for this:
/(\d\{3})[- ]\?
That's an opening paren, exactly three digits, a closing paren, and one or zero iterations of either a space or a dash. Obviously if there are zero iterations it matches a string where the paren buts up against the telephone exchange.

If there are no parens, it's even simpler because you must have a dash after the area code.
We'll use the \| operator to represent alternatives. In truth I don't know whether many VI implementations offer the \| operator, but I know that Vim does. By the way, in case you haven't noticed, Vim is my favorite VI implementation, though I like all VI's. Anyway, here's the first step in representing the area code:
/(\d\{3})[- ]\?\|\d\{3}-  
This matches area codes with or without parens. Remembering phone numbers can have one or zero area codes, together with the area code's parens and optional trailing dash or space, we put that in a group that can happen zero or one time, and append the regex for the last 7 digits of the phone number:
/\((\d\{3})[- ]\?\|\d\{3}-\)\?\d\{3}-\d\{4}
To make this clearer, let's color code it:
/\((\d\{3})[- ]\?\|\d\{3}-\)\?\d\{3}-\d\{4}

\( to \)
Group  consisting of all area code and trailing punctuation alternatives
Signifies 0 or 1 instances of the area code group.
Phone number without area code
Signifies that the element on its left and on its right are either/or alternatives
(\d\{3})[- ]\?
Structure (with options) of area code with parens
Structure of the area code without parens

Groups can be nested, and nested, and nested some more. In VI implementations that allow it, alternative groups can be specified with the \| operator (or possibly a different operator in a different VI implementation).

If your head doesn't hurt too badly, for extra credit try to make a substitute expression that converts all these phone number formats to a single format. I can't do it in a single step, but I can do it in a 2 step process. The first substitute finds all valid phone numbers and surrounds them with pho_ on one side and _ohp on the other. The second finds such surrounded strings and picks off the digits. This 2 stage approach frees the second replace from worrying about punctuation, or mixing detection and validation with substitution.

To do this, step 1 must surround the ENTIRE search expression with \( and \) to make it a single group, and place it in a substitute:

:%s/\(\((\d\{3})[- ]\?\|\d\{3}-\)\?\d\{3}-\d\{4}\)/pho_\1_ohp/
Step 2 formats all resulting strings that include area codes in a standard format:
You'll notice that all phone numbers that didn't include an area code were not converted. To convert them you need to run a second, much simpler substitute command.

I think you know where I'm going with this. If we can recognize all forms of phone numbers, and we can also remember matched text for use in the replace expression, then it's pretty obvious we can make a regular expression to "standardize" phone numbers. In this case we need to surround the digits of the phone number with slash parens. It's made more difficult because those slash parens are nested in a major group and are alternatives.


Regular expressions are huge. Master them and you can do in 5 minutes what others take hours to do. One of the most powerful regular expression techniques is the use of groups. By using groups, you can search for various alternatives, and for phrases that may or may not be there or may be repeated. Groups can be nested.
Steve Litt is the author of Rapid Learning: Secret Weapon of the Successful Technologist . He can be reached at Steve Litt's email address .

Registers, Cut and Paste

By Steve Litt
The most significant factor in a software developer's success is his or her design process. Next comes his or her debugging process, including use of tools such as debuggers. Obviously, a good memory or skillful use of reference material play an important part also.

And for those of us without total recall, cut and paste plays a vital role in our software development productivity. The ability to copy documentation and paste it into our code, to copy a function declaration to the code that uses the function, and many other cut and paste tasks speed our productivity immensely.

VI's cut and paste is richer than most other editors because of VI's vast array of registers. A register is simply a place to store text.

The simplest cut and paste operation is to delete a single line and paste it elsewhere. The line delete is accomplished by the dd key sequence, which deletes the current line and places it in the default register, the "" register. You can then move to another location, and press the p key, which pastes the contents of the "" register below the current line.

If you had wanted to copy the line instead of cut it, you could have used the yy keystroke sequence to "yank" the line into the "" register, and then moved and used the p keystroke to paste it below the current line.

By the way, if you want to paste above the current line instead of below it, you'd use the P keystroke instead of the p keystroke.

Anyway, the "" register always contains the text of your last deletion or yank, meaning it will quickly be be overwritten by the next delete or yank. To save a delete or yank, delete it or yank it into a specific register. For instance, to delete the current line and save it in the "b register, use the "bdd keystroke sequence. To yank (copy without delete) a line into register "c use the "cyy keystroke sequence. In general, you save any deletion or yank to a named register by preceding the delete or yank command with a doublequote and the register letter.

To paste from a specific register, prepend a doublequote and the register letter to the paste command. Thus "bp pastes the contents of the "b register after the current position, while "eP pastes the contents of the "e register before the current position.

To see a list of all the registers and their contents, use the :reg command.

The System Clipboard Register

Some VI implementations have a special register whose contents are those of the system clipboard. Vim is one such implementation, and in Vim that register is the "* register. So in Linux, if you want to paste part of a browser hosted help file into the file you're editing, highlight the material in the browser, switch to Vim and type the "*p keystroke sequence.

Likewise, to move a line from Vim to Mozilla Composer, press "*yy, switch to Mozilla Composer, press the middle mouse button, and watch the line appear in Mozilla Composer. A single line isn't particularly impressive, but with techniques discussed later in this article you can copy entire subroutines.

Various Delete and Yank Commands

Sometimes you want to delete only part of a line, instead of the complete line. To delete to the end of the current word, you'd use the dw keystroke sequence. To copy the remainder of the current word you'd use the yw keystroke sequence. When you delete or yank a line fragment, the p and P commands act differently, in that they paste before or after the current character instead of the current line.

In general, deletion commands have corresponding yank commands. The following table lists several such commands:

Text to copy or cut
Char or Line
Current line
Current plus next 2 lines
Current word
Current plus next 2 words
2dw or d2w
2yw or y2w
Current plus previous 2 words
Current char to end of line
D or d$
Preceding char to beginning of line
Character under cursor
Character before cursor
Remainder of paragraph
Earlier part of paragraph
Current char to start of searchtext
Preceding char to start of searchtext d?searchtext y?searchtext C
To end of sentence (not counting the period)

Notice in the preceding that many of the commands are composed by appending a motion command to the end of the  d or y. The motion command can be a built in one like w or }, or it can be a search. Either way, all the characters traversed in the motion are deleted or yanked.

WYSIWYG Cut and Paste

Many VI implementations, including Vim, allow visual mode highlighting, in which case simply pressing the d or y key will delete or yank the highlighted text. For instance, in Vim you can highlight line by line by pressing  the V key and then moving with motion commands such as j, k, } or a search. You can start  highlighting character by character with the v key.

And in Vim, you can start rectangular highlighting with the Ctrl+v keystroke combination. This extremely powerful capability allows you to switch fields around in a fixed length sequential record file. You can also build up such a file field by field by typing a field's contents on each line, and then rectangular cut and paste that onto the end of the preceding fields.

Rectangular delete is excellent for deleting the first several characters from several lines or all lines in the file, or for deleting past a certain column.


VI offers a wide variety of delete, cut, copy and paste techniques that are keyboard easy. The practitioner knowing the techniques listed in this article will be able to edit quickly. Your VI implementation will probably have many additional techniques not discussed in this article, giving you the opportunity to be even faster.

In VI the concepts of "cut" and "delete" are identical -- deleting text always sends it to the "" register, which could be thought of as "the VI clipboard". This concept is called "delete" in VI, and is implemented with various keystroke sequences starting with d. The concept of "copy" is called "yank" in VI, and is typically implemented with a various keystroke sequences starting with y.

Deletes and yanks can either be character by character or line by line. The distinction is important when pasting.

VI has two paste commands, p and P. The lower case paste command pastes after the current position, while the upper case version pastes before the current position. If the previously deleted or yanked material was line by line, the pasted material goes in new lines opened either after (p) or before (P) the current line. If the previously deleted or yanked material was character by character, the new material starts on the current line either after (p) or before (P) the character over which the cursor resides.
Steve Litt is the author of Rapid Learning: Secret Weapon of the Successful Technologist . He can be reached at Steve Litt's email address .

Maps and Abbreviations

By Steve Litt
You can map substantial commands to simple keystrokes using the :map command. For instance:
map ,,1 :set foldlevel=1<CR>
Note: if your VI implementation does not accept <CR> as a carriage return equivalent, just make the real thing with Ctrl+V followed by Ctrl+M.

After the preceding command, any time that within command mode you press the keystroke sequence ,,1 your foldlevel gets set to 1. But what if you want it to work within insert mode also? In that case you might do something like this:
:map! ,,1 <ESC>:set foldlevel=1<CR>a
Once again, if your implementation doesn't recognize the text "<ESC>" use Ctrl+V followed by the Esc key to place a literal Esc character.

The exclamation point after the word "map" indicates this mapping should be in insert mode, not in command mode. So the command first does the <Esc> command to get out of insert mode, then sets the foldlevel, and then runs the append command (a) to get back into insert mode. To the user it seems like ,,1 set the foldlevel from within insert mode.

An abbreviation is very similar to a map! command. It works from within insert mode only. Maps render instantly, but abbreviations do not render until another character is pressed. So for instance,
map! sl Steve Litt
after the preceding command, sl expands to Steve Litt as soon as the l is pressed. On the other hand,
abbr sl Steve Litt
after the preceding command, sl expands to Steve Litt only after the sl is followed by a space or punctuation. If it's followed, by, let's say, ant, the word "slant" is the result. Abbreviations are usually used to abbreviate common phrases, while map! commands are typically used to run commands.

Maps and abbreviations can greatly speed productivity. Maps are often used to provide a quick entry to macros and scripts...
Steve Litt documented the Universal Troubleshooting Process. Steve can be reached at Steve Litt's email address.

Macros and Scripts

By Steve Litt
A macro is a sequence of keystrokes to accomplish a task. A script is a sequence of commands to accomplish a task. In Scripts are usually EX mode commands (the kind of commands that start with a colon (:)), while macros are usually command mode commands such as dd, i, and typed in text.  Macros are stored in registers, while scripts are stored in files. Macros are run by typing @ and then the register letter, such as @b. Scripts are run by typing :source followed by the filename of the file containing the macro:
:source myscriptfile
Macros are recorded by pressing the q key followed by a letter representing the register in which to store the macro. The recording process is ended when a second q is pressed while in command mode. So, just like so many other editors, VI enables you to construct a macro interactively in real time, and then later play the macro back. Macros assume even more power when you include a multiple by prepending the number of times to do it. For instance, if you wanted to append the word "Done" to 10 lines, you could create the following macro in register b:
A Done^[j0
The preceding appends the word Done to the end of the line, types an Esc character to  get back into command mode, goes to the next line and then goes to the beginning of the line. So you've appended "Done" and then gone to the beginning of the next line. If you then the type 10@b keystroke sequence, the current line and the next 9 have the word "Done" appended to them. Better yet, if you type 1000@b and there are only 20 lines in the file, the current line and every succeeding line is appended, but at end of file the other 980 iterations are ignored.

Macros are the way editors without regular expressions do much of their magic, and in fact, VI can do the same type of magic with macros.

Let's review some distinctions between macros and scripts:

What it is
A series of command mode character commands
A series of EX mode colon commands
Where it's stored
In a register
In a file
How it's recorded
Interactively following the q command
Programatically by a text editor
How recording is stopped
A q command within command mode
How it's run
@ followed by the register letter
:source followed by the filename
How it's run multiple times
Precede the @ with a multiplier
How to append to it
Typing q followed by the upper case register letter appends to the existing register macro.
In a text editor.
How to edit it
  1. For example, assume register b contains the macro
  2. Open a blank line in VI
  3. "bP to insert the register b macro procedures on the line
  4. Edit the line as desired
  5. Move to the beginning of the line
  6. "bD to delete the line to register b
In a text editor.
Running one from the other
Include :source filename<CR> in the macro while in command mode
:normal @b
(see note)

The :normal @b syntax works only in Vim, and possibly a few other VI implementations. It doesn't work in the "standard" VI from the UNIX world.


At the dawn of computerized civilization, before the invention of the VI full screen editor, there was a line editor called EX. EX was incredibly powerful, but being a line editor with a command line, it was spectacularly unproductive. Then somebody built VI as a full-screen front end to EX. The authors of VI left several ways to access the underlying EX. Some of the more common ones are:
  1. You can run a single EX command by preceding it with the colon character
  2. You can put a series of EX commands in a script and run it with the :source command.
  3. You can go into EX mode by running VI with the -e option.
#3 is rarely used today and won't be discussed. #1 has been mentioned frequently so far in this magazine. #2 is the subject of this section.

The following is a very abbreviated list of EX commands you can use in scripts:
Quit VI
Quit even if there are unsaved changes
:e filename
Edit a different file
:e! filename
Edit a different file even if this one has unsaved changes
Edit the disk version of this file, even if there are unsaved changes in the memory version.  This is basically a revert command.
Go to the next buffer. For each file opened with an :e command there is a buffer, so you can switch from buffer to buffer, as long as the current one is saved. This command wraps, meaning once you pass the last buffer, you go back to the first one
Go to the previous buffer. For each file opened with an :e command there is a buffer, so you can switch from buffer to buffer, as long as the current one is saved. This command wraps, meaning once you pass the first buffer, you go back to the last (highest numbered) one
Go to buffer # 3. Obviously you can put any number in there to go to its corresponding buffer. If you put a number higher than the last buffer, you get an error message.
Go to the last (highest number) in the buffer list.
Delete the current buffer, so the file is no longer in memory (but it's still on disk). If the buffer deleted is #5, the former #6 becomes #5, and all higher numbered buffers are renumbered to be one less than their former values, so there are no "holes" in the list of buffers.
Lists all buffers -- by number, with filename
Search forward and goto the first matching line
Search backward and goto the first matching line
The substitute command. Can be used with ranges as discussed Ranges section of the Search and Replace: Substitute and Global Commands article.
The global command. Can be used with ranges as discussed Ranges section of the Search and Replace: Substitute and Global Commands article.
Sets a VI property
:let x = 1
Variable assignment
Delete line. Can be used with ranges as discussed Ranges section of the Search and Replace: Substitute and Global Commands article.
Paste the content from the last delete or yank. Can be used with an optional line number and an optional register. See :h :put for details.
Filters lines through an operating system command. Can be used with ranges as discussed Ranges section of the Search and Replace: Substitute and Global Commands article. The lines in the range are sent to the command, and are replaced by the output of the command. Common examples:
Sort the file
:%sort -n
Sort file numerically
:%sort -u
Sort unique -- delete dups
:cat -n
Prepend line numbers to each line

:r filename
Inserts the contents of filename below the current line.
Inserts the output of sysCmd below the current line. A few common examples:
Inserts network information
ls -l
Inserts a directory listing
galeon --help
Inserts Galeon's usage information

Saves the current file
:w filename
Saves the current file as filename. WARNING!!! The buffer you are editing is the old filename, not the new one. To edit the new filename, perform the :e! command immediately after :w filename.
:4,8w filename
Saves lines 4 through 8 of the current file to filename.
Appends lines 4 through 8 to filename.
:normal ddp
Example to the left switches the current line with the one below it. :normal runs a command mode Vim command from the EX prompt. This is not in VI, but it is in Vim and possibly other implementations.

Convenient Set Commands

:set textwidth=0
Turn off wordwrap during typing, but the gq command still changes line ends.
:set textwidth=99999
Turns off wordwrap during typing, and forces the gq command to concatenate all adjacent nonblank lines. If you previously composed an email with textwidth 65, and want to paste it into a WYSIWYG mail client like kmail, you'd use :set textwidth=99999 and then gq commands to crunch all adjacent nonblank lines into a single line so that kmail can wrap the line.
:set ai
:set noai
Set or unset autoindent. Autoindent causes new lines to start at the same column position as the line above them.
:set ic
:set noic
Set or unset ignorecase. When ignorecase is set, searches, substitutes and global commands match in a case insensitive manner. When it's unset, searches, substitutes and global commands are case sensitive in matching.
:set fileformat=unix
:set fileformat=dos
Puts the proper line endings on lines, according to operating system. DOS lines end with crlf, while UNIX lines end with lf.
:syntax off
:syntax on
Sets or unsets syntax specific editing (coloration, etc)
:set syntax=perl
Sets the syntax language. Perl, C, Java, HTML, and many more languages are supported.


In Vim, and probably some other VI implementations, your scripts can have functions. This provides power to accomplish almost any task, including turning VI into a different product (like an outliner). In Vim scripts, functions look something like this:

function MakeChars(count,char)
let i = 0
let chars=""
while i < a:count
let chars = chars . a:char
let i = i + 1
return chars

In the preceding, you see functions are delineated by their declaration, and by the word endfunction. Arguments are defined in the declaration, and the return statement is what you'd expect. Assignment is via the let statement, and you have loops and branching.

One thing not obvious is functions must not be defined multiple times, so function definitions and declarations must be surrounded by code to prevent multiple definition. It looks something like this:

if !exists("loaded_vimoutliner_functions")
let loaded_vimoutliner_functions=1

function MakeSpaces(count)
let spaces = MakeChars(a:count," ")
return spaces

function MakeDashes(count)
let dashes = MakeChars(a:count,"-")
return dashes


For more about functions, use the :h functions command to see info about built in functions, and the :h func command to see function definition syntax.
Steve Litt is the author of " Troubleshooting Techniques of the Successful Technologist".  Steve can be reached at Steve Litt's email address.

Programmers Helpers

By Steve Litt
Like most other editors, VI has features to help editing source code. This article lists the ones common to most VI implementations. The Vim article later in this magazine discusses some Vim extensions making source code editing even easier.

These programmers helpers are common to most VI implementations


You turn on autoindent with the :set ai command. You turn it off with the :set noai command. With autoindent on, every time you press Enter in insert mode, the cursor comes to rest below the beginning of the last line, making programming indentation much easier.

Various VI implementations have other indentation settings designed to "help" the programmer, and in my opinion most of them are best turned off. There are settings which convert spaces to equivalent tabs and tabs to equivalent spaces, which to me is incredibly confusing. Whether you indent using tabs or spaces, you want it consistent. I therefore suggest the following:
:set ai 
:set noexpandtab
:set nosmarttab
:set softtabstop=0
:set nosmartindent
:set nocindent
The preceding uses autoindent, but none of the other "helpful" options that can end up giving your lines arbitrary combinations of tabs and spaces. Also, it tells VI not to impose its own indentation rules, but rather to follow your rules and assist you by assuming a new line starts at the same position as the one above it.

When using autoindent you'll find some indenting commands handy:
Indent in command mode
Exdent in command mode
Indent in insert mode (when at start of line)
Indent in insert mode (from any point on the line)
Extent in insert mode (from any point on the line)

Bracket Matching

In an ideal world we'd all indent and document so well that matching beginning and ending brackets, braces and parens would be intuitively obvious to the most casual observer. In that ideal world, all maintenance programmers would retain the obvious matching, and even during development indentation would be perfect and brackets, braces and parens would never accidentally be omitted.

For those of us not living in the ideal world, there's bracket matching. In command mode, simply place the cursor on a square bracket, curly brace or paren, and press the percent key (%). The cursor will jump to the complementary square bracket, curly brace or paren. This is a 5 second test to see whether your source code is doing what you really think it is.

This is a great debugging technique to find the missing or extra brace that throws off everything else. Better yet, it's a quality control test. If, upon finishing a subroutine, you bracket match the beginning brace with the ending brace, you will have removed a large percentage of problems before testing your code.

Some VI implementations, such as Vim, have syntax highlighting, which makes a blown brace instantly visible. But bracket matching is the conclusive test.


"Now what were the arguments to that function again?" Sound familiar? Like most modern professional grade editors, VI has a facility such that when you encounter a subroutine usage, you can jump to other places where it's used, as well as where it's declared and where it's defined. This is done by tagging.

Here's the simplest way to implement tagging on a project. Find a directory with a programming project. C is ideal, C++ will probably work, as will Perl and some other languages. From within that directory, run the following command:
ctags *
That will create a new file called tags. If you were to look at the new file you'd notice it's a list of many of your project's variables, functions and classes, along with the files containing their definitions and some other information. Once that file is created, go into one of your source files (not a header file), find a function call, put the cursor over the function name, and press the Ctrl+] key. You'll be brought to the definition of the function. Press the Ctrl+T key and you'll be returned to where you came from. This works for function names, global variables, class names, and even #ifdef constants.

The preceding discussion is the simplest possible use of tagging. For real life projects I recommend you review information on the ctags program, keeping in mind there are other programs that construct tag files. Pick the best program and options for your needs.
Steve Litt is the author of the Universal Troubleshooting Process courseware.   Steve can be reached at Steve Litt's email address.


By Steve Litt
If you use Redhat or Mandrake, the vi command is symlinked to Vim. Vim is a VI implementation, or to be absolutely correct, a VI workalike, where VI is the editor originally packaged with UNIX. But given the fact that today there are so many VI variations, it's tough to talk of VI as if it's a distinct program or a standard.

I've used VI on an HP-9000, and I've used Tiny-Elvis (another VI implementation) on an old Debian version, and I can tell you that Vim is hugely more useful. Not that you can't use HP-9000 VI or Tiny-Elvis to edit source code and/or construct/edit huge data files -- you can. But Vim goes farther, by adding enough functionality that you can configure it as an html editor, or an outline processor, or pretty much anything your imagination can conceive.

Vim is a rather large VI implementation -- certainly more resource intensive than Tiny-Elvis, for instance. That being said, modern computers have more than enough RAM and processor power to easily run Vim. Here's a top command from my machine, which at the time was running Mozilla, Mozilla Composer, Galeon, UMENU, a couple shells and 4 graphical Vim sessions.

7365 slitt 16 0 37456 35M 13476 S 7.6 7.0 13:18 mozilla-bin
7367 slitt 9 0 37456 35M 13476 S 0.0 7.0 0:00 mozilla-bin
7368 slitt 9 0 37456 35M 13476 S 0.0 7.0 0:00 mozilla-bin
7369 slitt 9 0 37456 35M 13476 S 0.0 7.0 0:00 mozilla-bin
7371 slitt 9 0 37456 35M 13476 S 0.0 7.0 0:06 mozilla-bin
11042 slitt 9 0 37456 35M 13476 S 0.0 7.0 0:00 mozilla-bin
7554 slitt 9 0 21788 21M 14344 S 0.0 4.2 0:07 galeon-bin
7565 slitt 9 0 21788 21M 14344 S 0.0 4.2 0:00 galeon-bin
7566 slitt 9 0 21788 21M 14344 S 0.0 4.2 0:00 galeon-bin
7567 slitt 9 0 21788 21M 14344 S 0.0 4.2 0:00 galeon-bin
7568 slitt 9 0 21788 21M 14344 S 0.0 4.2 0:00 galeon-bin
7573 slitt 9 0 21788 21M 14344 S 0.0 4.2 0:00 galeon-bin
3456 root 18 0 96200 13M 3280 S 3.3 2.6 19:26 X
11033 slitt 9 0 7108 7108 4424 S 0.0 1.3 0:07 gvim
7912 slitt 9 0 6352 6352 4200 S 0.0 1.2 0:21 gvim
2697 sympa 9 0 9768 6200 1904 S 0.0 1.2 0:09

You can see that the Vim sessions consumed less memory than the browsers and X. So if you have enough memory to run a graphical browser, you have more than enough memory to run Vim, graphical or CLI.

Vim can be run on the command line, or it can be run as a graphical application with menus. The graphical version has complete mouse selection and is useful even to those knowing little VI. But of course, if you need to reach for the mouse, you're slowing yourself down.

Extra Features

Here are some of the extra features that Vim brings to the table:


Vim's commands go far beyond traditional EX mode. Vim scripts can actually contain functions, which can be called in a wide variety of circumstances. There's even an autocommand (au) which runs a command specified by you (typically a function) upon a specific event for a file with a specific pattern (such as *.html). This extra functionality enables Vim to be configured as a completely different type of app. Indeed, the VimOutliner project is primarily a configuration of Vim.


Vim has folding. Folding is a feature by which some lines of a file become invisible, replaced by a marker. This can be used, for instance, to view only the declarations of functions within a file. Within a hierarchy, it can be used to hide lower levels for a "big picture" view. The VimOutliner project uses folding to implement expand and collapse.

Graphical interface

Traditional VI is a CLI (Command Line Interface) application. Many VI implementations have GUI interfaces, and Vim is one. Vim's GUI interface facilitates easy cut and paste within Vim and with other GUI apps. The GUI interface sports a menu, making Vim more approachable for the newbie. And Vim's menus are configurable, enabling it to be used in specialized circumstances (such as VimOutliner).


Many VI implementations allow multiple windows, and Vim is one of them. Vim has a very rich set of windowing commands. Use the :h windows command to learn more about using multiple windows in Vim. One incredible extension is the :normal command. Look it up with the h: :normal command.

Extra Commands

Here's where Vim really shines. Whether the desired feature is regular expressions, or text selection, or a host of other needs, Vim has extra commands to make the desired task easy.

Learning Vim

Even if you're a VI expert, you're using only a subset of Vim's functionality. Like every other app, the best immersion learning technique is to take the tutorial. To take the Vim tutorial, get into Vim and run the :h tutor command. Go through the tutorial and follow the instructions.

Once armed with knowledge from the tutorial, use the extensive help facility. The most general way to use the help facility is the :h command, which presents the highest level of the help system, including a table of contents (you must scroll down to see it). This is the preferred way of searching the help system, as there's no real search mechanism.

The table of contents is actually multilevel, using tagging to move to new levels. When you see text between vertical bars (|), that text is a link (tag, actually). Press the Ctrl+] key combination to go to the new level, and use the Ctrl+T key combination to come back.

If you know the exact Vim designation for the subject you're looking for, you can go directly to it by appending the subject to the :h command. For instance, :h folding takes you directly to the help text on folding.


If you're looking up an EX command (one done at the colon prompt), don't forget to include the colon in the help command. For instance:
h: :d

h: d

Finally, if you need a true search facility, you can use grep. First you need to find out what directory contains your help text. Perform the :h command to bring up help.txt, and press the Ctrl+G key combination to see what directory it's in. Then, at the bash prompt, go to that directory, and run a grep command. For instance, if you want help on "matching", try this:
grep -i -C5 match * | less
Then you can search the retrieved information to discover which help file would help you, and within Vim access that help file with the :h filename command, where filename is the name of the help file.
Steve Litt is the author of the Universal Troubleshooting Process courseware.   Steve can be reached at Steve Litt's email address.


By Steve Litt
Much of our world is hierarchical. Object oriented computer programs have "isa" and "hasa" hierarchies. Structured computer programs have hierarchies of subroutines. Projects are hierarchies of tasks and subtasks. Todo lists are lists of projects, hence a hierarchy. Your shopping list is best kept as an outline, with stores being the top level. As food runs out, put it in the proper place on the outline. That way your shopping trip can be efficient at each store.

Grocery Store
Trail mix
Sugary cereal
4 lbs ground beef
1 chicken
Toilet paper
Laundry detergent
Vegetable Stand
Green peppers
Video tapes

The classic use of outlines is the structuring of a book or other large document. My outline for "Samba Unleashed" was over 2800 lines. Anyone writing a nonfiction book will most likely fail to finish if they don't start with an outline, and even if they finish, the book will be full of chapter interdependencies, forward references and redundancy -- in other words, it will be terrible.

Who needs outlining? Anyone who is too busy to waste time correcting mistakes. Outlines are a planning tool that help you do the job right the first time.

25 years ago, creating an outline was a  cumbersome job in and of itself, requiring constant writing, erasing, and rewriting on paper. Rearranging your outline back required either filling your outline with long, looping arrows, or more likely, a complete rewrite.

Then outliner processors were invented. An outline processor is a software program enabling the user to quickly construct outlines, and better yet, to correct and rearrange the outline. Keeping in mind that lines of an outline are called "headlines", outline processors typically have the following capabilities:

VimOutliner Implementation
Add a headline.
Vim Insertion commands
Delete a headline, possibly including all the headlines subservient to the headline.
Vim line deletion commands
Make a headline subservient to the one above it
Tab key, VI >> command, or Ctrl+T within insert mode
Make a headline equal or superior to the one above it
VI deletions on beginning tabs, << command, or Ctrl+D within insert mode
Move a headline or an entire tree to a different location in the outline
VI delete followed immediately by a VI paste in the new location. Soon will also be implemented with "move up one place" and "move down one place" keystrokes
Copy a headline or tree to another location in the outline
VI yank followed immediately by a VI paste in the new location
Make every headline in the tree below the headline of interest invisible. This is good for getting the "big picture". When the entire headline is collapsed to a certain level, this also facilitates quick location of the tree of interest
Vim folding, together with specialized Vim functions to facilitate visually pleasing collapsing. Collapsing on a single tree or whole outline basis facilitated by Vim folding commands.
The opposite of collapsing, expanding makes collapsed headlines visible again. Expanding can be all the way down the tree, or only to a certain level, such that below that level the headlines are still collapsed.
Vim folding, together with specialized Vim functions to facilitate visually pleasing collapsing. Expanding on a single tree or whole outline basis facilitated by Vim folding commands.
Running a program or command directly from a specially configured headline. Typical use is to bring up an html file in a browser or an OpenOffice document in OpenOffice. Having this capability enables you to have a true single-tree knowledge base.
Not yet in VimOutliner (as of 0.2.0), but the team has successfully prototyped it and expect it to be in the next version.
Body text
A lowest level entity that word wraps. Having this enables a substantial part of a document's writing process to occur within the outline.
Not yet in VimOutliner (as of 0.2.0), but the team has successfully prototyped it and expect it to be in the next version.
Headline numbering
Numbering of the outline's headlines, typically III, C, 3, c, etc.
Not implemented in VimOutliner. However, scripts exist to export VimOutliner outlines into a numbered outline.
Interoutline linking Links between outlines similar to links on web pages. Interoutline links are used to create "superhierarchies" where a master outline links to suboutlines, themselves linked to sub-suboutlines, and so on. Conceptually this enables you to place all your knowledge in a single hierarchy for quick and easy recording and retrieval.
Vim tags and the ctags program
Headline appearance by level
Outlines are much easier to read if headlines at different levels have different appearances. The distinct appearance is typically the result of a different font or a different color.
Vim syntax facilities to color leveled colors. Scripts could be written to export an outline to html, with various fonts, for printing.
Hoisting and dehoisting
The ability to temporarily treat a subtree as a main outline, with the subheadlines at the top level. This facilitates greater focus on a small area of interest.
Not yet implemented in VimOutliner, but it's being discussed.
The ability for many people to simultaneously work on the outline, thus "brainstorming" together. Few if any outline processors feature groupware.
Not yet implemented in VimOutliner, but it's being discussed.
The ability to turn an outline into a diagram.
Not specifically implemented, but doable with perl scripts.
The ability to have one headline be a reference to another, such that when one changes the other changes identically. This feature is useful in rapid-fire associative thinking, and in computer program design.
Not yet implemented in VimOutliner.
Fast retrieval
The ability to retrieve anything in the outline quickly with a minimum of keystrokes.
Implemented with VI's search command. Further quick lookup features might later be added.

Obtaining VimOutliner

VimOutliner is free software that can be downloaded from The current version is 0.2.0, and is downloaded as a 25K (that's Kilobyte) file. Simply extract the tarball in the directory above where you want its executables to reside, and the tarball will create an otlbin directory under it. Within the otlbin directory, while logged in as the user who will be using VimOutliner, run the ./ script. The script asks 3 questions, and if you answer "yes" to all 3, VimOutliner is automatically installed for that user.

The current VimOutliner is known to work on Linux. We have every reason to believe it will work on any UNIX clone or workalike, including BSD and OS/X. We suspect it can be adapted to Windows usage, but have not yet made the port.


Because so much of the world around us, and so much of human thinking, is hierarchical in nature, the outline has always been the design tool of choice for writers, and the planning tool of people too busy to work by trial and error. Outlining is so powerful that even before computers, when outlining was a painful pencil and paper process involving writing, marking up, and rewriting, outlines were used extensively.

With the advent of computerized outline processors, the cost of outlining has plunged. In the pencil and paper days creating a finished 200 headline outline could have taken several days. Today, assuming most of the the research and though have been completed, a 200 headline outline would take between 2 and 6 hours.

With different features and keystroke interfaces, computerized outline processors vary widely in their productivity. Due to the incredibly efficient VI keyset, VimOutliner is probably the most productive outline creation tools. The current version (0.2.0, released 12/3/2002) has the following fully developed features:
Two additional important features, spawning and body text, have already been prototyped by the VimOutliner team, and almost certainly be added to the next version (after 0.2.0). Other features such as hoisting/dehoisting, spellcheck, user friendly menu interface, level aware sorting, and single step rearrangement are being actively developed, and some of these features are likely to make the next version. It's very likely that the next VimOutliner version will be more featureful than commercial outliners.

Perhaps most intriguing is the fact that the VimOutliner team has discussed techniques to add groupware capability to VimOutliner. When that feature is in place, VimOutliner can be expected to be the best of breed outline processor, for any price, on any kind of computer.

If you are a busy person you need an outline processor. If you use Linux and are at all familiar with VI, VimOutliner is likely the most productive outline processor you can get.
Steve Litt is the author of " Troubleshooting Techniques of the Successful Technologist".  Steve can be reached at Steve Litt's email address .

Life After Windows: Linux is a Wishing Well

Life After Windows is a regular Linux Productivity Magazine column, by Steve Litt, bringing you observations and tips subsequent to Troubleshooters.Com's Windows to Linux conversion.
By Steve Litt
My family bought a house when I was 7. My parents liked the neighborhood, the school system, and the house. I liked the wishing well.

Of course it wasn't a real wishing well. It was just a 15 foot deep, 3 foot wide space between the garage and the fence. Densely overgrown with thorny weeds, it inspired fear and curiosity. I went in, and kept going in. Because every time I went in, I came out holding something cool. A marble, a ball, whatever I wanted. Once I wished for a scooter, and sure enough there it was, 10 feet back in a heretofore unexplored section of the wishing well.

Any adult knows what happened. The last several owners had children, each of whom left things behind. I was a teenager when we moved out of that house. Surely the child of the new owner found the cool toys I abandoned in that overgrown space.

Only a kid could think of it as a wishing well. A magical source of found dreams. It was the magic of childhood, all too brief -- never recaptured.

Until I found Linux.


After purchasing a copy of Red Hat Linux 5.1 in October 1998, Linux remained a cute toy while my work continued in Windows 98. That lasted a couple weeks, until real life needs began incrementally transferring my work to Linux. One day someone sent me a uuencoded email message, and I needed to decode it. I could purchase a Windows uudecode program, or maybe download a shareware one and feel guilty.

Then the lightbulb went off. Uuencode came from the UNIX world, so perhaps there would be a uudecode utility in Linux. A quick apropos command and some man pages led the way to the Linux uuencode and uudecode commands, and from then on all my uudecode work was done in Linux.

The preceding paragraph was my first of many experiences where I'd wish for something, and find it in Linux.

I'd always wished to have a web server on my Windows box so to really test web pages, but Windows web servers were either underfeatured or expensive, or didn't run on Win98. The Apache software that ships with every Linux distro took care of that, enabling me to upload web pages to create a duplicate of my web host.

Novell Netware was sooooo cool, but priced way out of my league. Armed with my discoveries of uudecode and Apache, I researched file servers on Linux, and discovered Samba. Here was, for my purposes, a Novell Netware replacement I could use, for free, in my own office, or the offices of my customers.

Now in possession of a kewl file server, I wished it to plug in any old computer to the network and have it work. I went on in and found DHCP. Now any old computer could be connected to my system, and work flawlessly on my network.

I wished for the ability to write database enabled apps, and discovered dbi::dbd and postgreSQL to make a web app.

Sometimes the wishing well grants wishes oddly. In the words of the Stones, "you can't always get what you want, and if you try sometimes, you just might find, you get what you need". When converting my business to the Linux desktop, all the wishing in the world didn't produce a decent outline processor. Nothing came on the distributions, and web research showed the few attempts at Linux based outliners were embrionic at best. A serious impediment to productivity, but for reasons discussed in the April 2001 Troubleshooting Professional Magazine (basically, "who owns your data") I had to move forward with the Windows to Linux conversion.

My wish had not been granted. The wishing well had failed.

You Get What You Need

Or had it? Within a month of the conversion, a thread on LEAPLIST made me aware that Vim version 6 had come out, that it had a feature called "folding", and that "folding" could be used to simulate an outline processor's collapse/expand capability. That capability was the only outlining feature lacking in Vim. A week's experimentation with Vim6 produced a series of scripts and config files to turn Vim6 into a crude outline processor. A few weeks later I refined the scripts, added a feature to link outlines, and packaged the scripts and configurations as the VimOutliner outline processor, licensed with the GNU General Public License.

And sometimes you get what you hadn't thought to wish for.

The original VimOutliner's collapse/expand feature was somewhat dysfunctional for an outliner. Instead of hiding all of a headline's subheadings, it placed a line below the main heading showing, in gray background, the first subservient heading, and the number of lines hidden. It was ugly, counterintuitive, and slowed productivity to some extent, but I had no idea how to code a real collapse/expand capability. I was satisfied with the kludge.

In June of 2002, VimOutliner user Matej Cepl wrote to ask if I could fix VimOutliner's collapse/expand feature. I replied that I didn't have time to fix it. On October 13 Matej wrote me back and asked if VimOutliner was officially dead, or should he keep holding his breath.

Timing is everything. On October 18, 2002, Noel Henson emailed to congratulate me on the IceWM content of the 9/2002 Linux Productivity Magazine. As an aside he thanked me for VimOutliner, which he uses every day. Remembering Matej's question, I responded to Noel with a question about how to make collapse/expand be more outliner like, and less Vim like.

Noel quickly came back with a substantially changed outliner.vim file which implemented collapse/expand correctly, though it had some bugs. After a few days of back and forth with Noel's new outliner.vim, we started sending the messages to Matej also.

Two is company, three is a project. We now had critical mass, complete with suggestions, feedback and testing. LEAP President Phil Barnett arranged for Billy Knight, owner of FiberHosting.Com, to donate a mailing list. Thanks Phil and Billy! Armed with our mailing list, progress was quick and sure. The new VimOutliner 0.2.0, sporting correct collapse/expand, level based color coding, sorting, and several other handy commands, came out on 12/3/2002.

The next version is already under discussion. It will have facilities for headlines that are links to executable programs, so you can link from an outline to an html page, a Gimp graphic, an Xmms sound file, or a OpenOffice document. This opens the door for a true single-tree knowledge base. The next version will also have body text -- the last basic outlining feature missing from VimOutliner.

Noel is working on hoisting, dehoisting, a menu driven interface for VI newbies, and improved sorting and rearranging techniques. Matej is helping with documentation, and is researching some esoteric and powerful features of professional products that we could add to VimOutliner in order to make it into a thought processor. We've all discussed the possibility of making a VimOutliner-based groupware product, and the possibility isn't as remote as might be imagined.

The Wishing Well isn't Magic

My back yard wishing well seemed magic, but adult logic showed it to be a natural result of an overgrown area of a yard long inhabited by kids. My Linux wishing well seems magic, but is in fact the natural result of a community of computer user/developers empowered by the GNU GPL and other free software licenses.

Free software always starts with an itch to scratch. I desperately needed a Linux-based outline processor. That was the itch. I scratched it by making VimOutliner, and the GNU GPL license enabled me to give it to the world without the possibility of someone changing it, making it proprietary, and making me pay for it.

Matej and Noel needed an outliner, and scratched that itch by downloading VimOutliner. Matej had an additional itch -- he wanted intuitive collapse/expand instead of the Vim folding kludge I'd used. Soon the itch belonged to the three of us, and Noel, who has the best knowledge of the Vim scripting language, made it happen, with plenty of help from Matej and myself.

In every respect except the lack of body text, VimOutliner 0.2.0 is a highly respectable outline processor. And from an authoring standpoint, I believe it to be the fastest outlining environment ever created.

Emboldened by this victory we've started going after other itches. Body text. Hoisting. Sorting. Groupware. And some thoughtware functionalities I don't understand (but I'm sure Matej will explain them). There's an excellent chance that a year from now VimOutliner will outshine even the expensive proprietary outline processors.

From the day that Richard Stallman inked the GNU Manifesto and the GNU General Public License, the wishing well has been our destiny. It's not magic. It's simply another example that the pen is mightier than the sword.

Or the campaign contribution.

Microsoft can pull all the strings they want in order to evade antitrust laws. They can attempt to make free software illegal. But The Wishing Well is just too powerful, producing superior software at a phenomenal rate. It produces useful software, rather than producing a collection of features calculated to capture market share or lock competitors out of the market.


Unlike their fairy tale counterparts, real life wishing wells have thorns. Some thorns are brambles that scratch you bloody as you triumphantly emerge clutching a scooter. And some thorns take the form of a huge corporation creating booby traps attempting to prevent you from using the dream software found in the wishing well.

Challenge is good. Fairy tale wishing wells are welfare;  real life wishing wells are a triumph of the human spirit.

The wishing well with free software is a download away. Wonderful software you've barely dared dream of. Software to ease your life and boost your productivity. Software not encumbered by proprietary license usage restrictions. Its real. Millions have already partaken, but the wishing well's bounties are limitless and growing.

It's yours for the asking, if you dare to laugh at the thorns and go on in.

Steve Litt is the author of the course on the Universal Troubleshooting Process.  He can be reached at Steve Litt's email address .

Letters to the Editor

All letters become the property of the publisher (Steve Litt), and may be edited for clarity or brevity. We especially welcome additions, clarifications, corrections or flames from vendors whose products have been reviewed in this magazine. We reserve the right to not publish letters we deem in bad taste (bad language, obscenity, hate, lewd, violence, etc.).
Submit letters to the editor to Steve Litt's email address, and be sure the subject reads "Letter to the Editor". We regret that we cannot return your letter, so please make a copy of it for future reference.

How to Submit an Article

We anticipate two to five articles per issue, with issues coming out monthly. We look for articles that pertain to the Linux or Open Source. This can be done as an essay, with humor, with a case study, or some other literary device. A Troubleshooting poem would be nice. Submissions may mention a specific product, but must be useful without the purchase of that product. Content must greatly overpower advertising. Submissions should be between 250 and 2000 words long.

Any article submitted to Linux Productivity Magazine must be licensed with the Open Publication License, which you can view at At your option you may elect the option to prohibit substantive modifications. However, in order to publish your article in Linux Productivity Magazine, you must decline the option to prohibit commercial use, because Linux Productivity Magazine is a commercial publication.

Obviously, you must be the copyright holder and must be legally able to so license the article. We do not currently pay for articles.

Troubleshooters.Com reserves the right to edit any submission for clarity or brevity, within the scope of the Open Publication License. If you elect to prohibit substantive modifications, we may elect to place editors notes outside of your material, or reject the submission, or send it back for modification. Any published article will include a two sentence description of the author, a hypertext link to his or her email, and a phone number if desired. Upon request, we will include a hypertext link, at the end of the magazine issue, to the author's website, providing that website meets the Troubleshooters.Com criteria for links and that the author's website first links to Troubleshooters.Com. Authors: please understand we can't place hyperlinks inside articles. If we did, only the first article would be read, and we can't place every article first.

Submissions should be emailed to Steve Litt's email address, with subject line Article Submission. The first paragraph of your message should read as follows (unless other arrangements are previously made in writing):

Copyright (c) 2001 by <your name>. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, version  Draft v1.0, 8 June 1999 (Available at (wordwrapped for readability at The latest version is presently available at

Open Publication License Option A [ is | is not] elected, so this document [may | may not] be modified. Option B is not elected, so this material may be published for commercial purposes.

After that paragraph, write the title, text of the article, and a two sentence description of the author.

Why not Draft v1.0, 8 June 1999 OR LATER

The Open Publication License recommends using the word "or later" to describe the version of the license. That is unacceptable for Troubleshooting Professional Magazine because we do not know the provisions of that newer version, so it makes no sense to commit to it. We all hope later versions will be better, but there's always a chance that leadership will change. We cannot take the chance that the disclaimer of warranty will be dropped in a later version.


All trademarks are the property of their respective owners. Troubleshooters.Com(R) is a registered trademark of Steve Litt.

URLs Mentioned in this Issue