Learning the vi Editor/Vim/Useful things for programmers to know

Useful things for programmers to know
There are quite a few things programmers ought to know about vim that will make their experience that much easier. Programmers can save hours and weeks of man-hours over the long haul with effective editors. Here are some tricks and tools that vim provides. With the time you save, you might speed up your work and have some extra time for a quick Quake deathmatch or eventually increase your productivity to help justify a larger wage increase.

Word, variable, function, and line completion
Sometimes the word you're typing is really long. You shouldn't have to type it all out. If it's in your dictionary, or in the current file, you can save a lot of time with and. Let's take a closer look at how this works:


 * Word/variable/function name Completion

Generally, any word in the current file, or any of the other files (buffers) you are editing in the same instance of vim, will match for completion. This means once you've typed it once, you can type the first couple letters next time, and press Ctrl-N (several times if you need to cycle through several options) until you find the word you're looking for.

Technically, this isn't true. You can tell vim where to look for words in the  function. In Vim 7, the  function will generally be set to figure out a lot about what you're typing — drawing information from function libraries (As of the last update on this book, the author knows C and C++ are supported by default). Keyword completion since Vim 7 will also show a popup menu.

You can also define a dictionary of your own for completion. For more detail, you might want to consult the vim help system ":help complete", ":help complete-functions", and so forth.

 Example 1 

As an example, you might edit a C program file, "blah.c". You want a function that starts with "str", but you can't remember what it is. You first type "str". It remains regular text until you press or. In vim 7, you will see a menu appear, like this:



You can use and  to cycle through the entries shown. In Vim versions 7 and higher, you can actually use the arrow keys to cycle through entries in the menu. There might be too many to show on the screen at once (you will notice the black box on the right represents a scroll position on a gray bar--not all the options are shown on-screen in this example.) The files from which the options were drawn are shown, to help you decide if it's what you're looking for.

(You will also notice in this example that words show up from files the author has recently edited, such as 'strict' from 'cgi-bin/ftplist.pl' -- we certainly don't want that.)

 Example 2 

Now, suppose you need the sine function, but you know it has an odd name. You type  and press, and it doesn't show up:



You're not out of luck, you just haven't included the math library yet. All you have to do is add the line


 * 1) include 

and try again. This time you see the function name you wanted (it wasn't easy to remember since it has an odd name)




 * Line Completion

You can complete entire lines if you need to, though this is less likely. , will load the matching lines (white space matters!) into the menu, and from there you can move forward and backward with arrows or  and  (for Previous and Next)

Indentation
Vim can figure out how to indent most common filetypes.

For most of the popular programming languages, vim can detect the file type by the filename's extension, and from there it will decide how to indent your files. If you don't see it automatically creating the proper indentation for you, try



In the GUI version, you might be able to turn it on at the same time you turn syntax highlighting on for that file. Choose Syntax -> on/off for this file, or Syntax -> Show Filetypes in menu, then go back into the syntax menu and choose the appropriate file type from the list.

You might want to put the above-mentioned ":filetype ..." line in your vimrc file (discussed earlier) and open your program file again, though this really shouldn't be necessary.

If you still have problems, you might want to check that your runtimepath variable is set properly (:help runtimepath). It's also possible (though unlikely) that your programming language is rare enough that nobody has written an indent plugin for it yet. The official site for vim, vim.org, may have an indent plugin file that meets your needs, even if it didn't come with your default installation of vim.

For those times when you've pasted some text in and the indentation is wrong, (your indent plugin must be loaded), you can use the = command. It's probably easiest to type '10=' to re-indent the next ten lines, or to use visual mode and press.

If you want, you can indent lines with ">>" and unindent them with "<<".

If you are in insert mode, use and  to change the indentation of the line ( decreases indentation by one level and Ctrl-T increases it by one level)

If you can't manage to get filetype specific indentation working, you might try setting one or more of the following options: smartindent, autoindent, cindent, and copyindent. Chances are these won't work completely right, so and  will be more important. To turn autoindent on, type. To turn autoindent off, type

Repeating commands, or Performing the Same Command Many Times
If you feel comfortable with vim, you might record your keystrokes to an invisible register and repeat them later. It might be easier to write a vim script, or even filter your file with another program (such as a perl script) for complex enough actions.

That said, sometimes it really is easier to record a command and reuse it, or even perform it on any matching line. For more advanced execution patterns (e.g. executing one command on the whole file), see below. You might also consider creating a mapping (discussed below) or running a :global command (also discussed below).

Repeating the last single command
Suppose I want to put a semicolon on the end of a few lines, where I forgot:

cout << "Hello world\n" i = j + k cout << "i is " << i << endl

On the first line, I type  followed by the   key. I move to the next line and press  (the period tells vim to repeat the last command -- don't worry, it doesn't duplicate movement commands).

Recording a command macro
Vim has a powerful form of command repetition available through the use of macros. A user can record a series of commands into a register and run the register as a macro. Macros can be recorded into any of 26 registers (a through z).

To start recording a macro, press  followed by a register name (any letter   through   -- Registers are defined by only one letter of the alphabet, so only one character may be used as the storage buffer). After performing a series of commands, finish recording the command macro by pressing  again. For example to start recording into register z, press  and press   again to finish recording.

To run a macro from a register, run it with  where x is the register with the desired macro recording. Register  is the default register for macro recordings, so if you have recorded into register   you may simply type   to run the macro.

(Note: Keep in mind that scripts or mappings may sometimes use an arbitrary register--so if you have a conflict, especially with a third party script or mapping, you should consider recording to a different register. You can view the contents of a register with the :registers command.)

Example 1
As a simple example, suppose you have the following lines in the buffer, and you want each line to repeat the last word on the line. Initially, the buffer looks like this:

The quick brown fox jumps over the lazy dog The sly gray fox circles around the unsuspecting rabbit The slow gray fox crawls under the rotting fence

And you want the buffer to look like this: (where additions are highlighted in bold)

The quick brown fox jumps over the lazy dog dog The sly gray fox circles around the unsuspecting rabbit rabbit The slow gray fox crawls under the rotting fence fence

To do this, start recording into the default register with, then append the line with  , type a space, then  , then press the   key. To finish recording, press  again. Now the macro has been recorded into register q. To repeat the command, move down one line, and repeat the command by typing  or. You can use  to run this macro because q is the default register for macros.

Example 2
In another example, suppose you have the following lines in the register:

The quick brown fox jumps over the lazy dog dog The sly gray fox circles around the unsuspecting rabbit rabbit The slow gray fox crawls under the rotting fence fence

and you want to put HTML tags around the animal names (fox, dog and rabbit) to make them bold (eg,  needs to become  ). Suppose you want to use register a for the macro.

To start, move the cursor onto the first animal name--fox. Place the cursor somewhere on the word, such as on the 'o' in fox. Begin recording by typing. Next, delete the word into register b by typing  (see   and   and   for an explanation of this command). Next, enter insert mode by typing  and then type   followed by , then   (see   for an explanation of this command). Next, type   and press ESC. Finally, stop the recording by typing. To repeat the command, move the cursor over the next word you wanted to surround with the HTML tags and run the macro by typing. You can see what the macro looks like by examining the register. To do so, you may run the command. In this case, vim will show the following output:

--- Registers --- "a  "bdawi  ^O"bP  ^[

Note that a recording remembers all your movement commands, so you will need to put the cursor in the correct starting position before you begin recording.

Example 2b: fixing a macro
Suppose you made a minor mistake in your macro, but the macro is rather complex and you don't want to repeat all those commands again. We would like to modify the contents of a register. In order to do this, we use the feature that typing  in the escape mode uses the contents of register x for the next delete, yank, or put.

Assume that we are using register a,
 * create a new line (this line will be eventually deleted) and put the register's contents on the line with  in the escape mode. This command is pasting (note the p in the command) the contents of register a (via "a) into the line.
 * Make the modifications as needed, and
 * put the modified line back into register a by moving to the start of the line (with ) and typing   in the escape mode.  (Do not use   because D will capture the newline character in the buffer as well.)
 * Test the macro to be sure it is working properly, then use it as needed.

Executing a command macro
To execute a macro stored in register  once, you can just press. But often, you would not write a macro to execute it only once and here the full power of Vim kicks in.

To apply the command to the lines 23 through 42, use, to apply it to all lines in your document use you can use.

The same also works for single commands that you can access with the dot. If you have forgotten semicolons on some lines in your document, you would just execute  followed by the   key. Then the command  will apply the same action to the lines 23 to 42 and insert a semicolon at the end of each line.

Mapping a command
One of the advantages of mapping a new command is that you can put the mapping into your vimrc file for use later. I have the following mapping map &lt;C-k&gt; :!%:p&lt;C-m&gt; What this does is maps the normal command Ctrl-K to run the current file as a script. You could also perform the second "Recording a command" exercise from above (encase a word in bold tags) with this mapping: map &lt;C-x&gt;b "bdawi&lt;b&gt;&lt;C-o&gt;"bp&lt;/b&gt;&lt;ESC&gt; Note that in this case, I can get away with "&lt;b&gt;" because it doesn't match a special character name. However, if I needed to avoid a conflict (if I wanted to map an insertion of "&lt;ESC&gt;") I would use &lt;lt&gt; and &lt;gt&gt; for the less than and greater-than symbols. (See ":help key-codes")

If you want to map a command for insert mode, use imap instead of map.

If you want to prevent any of the commands in your map definitions from being interpreted in other mappings, use noremap (or inoremap for insert mode inoremap meaning insert mode no re-map)