shell

Vim for programmers (III)

Welcome to the last “Vim for programmers” issue. Ironically, in this issue I will show you some nice characteristics despite they are not specific of programming. However they make much more sense when they are applied to programming.

Getting C help
This first feature is oriented directly to C programming. In most UNIX systems, there is a collection of system manual pages available with the command “man”. Although I will not explain man in detail (you can read more here (or type man man) it is worth saying it shows information about the command, system call, file, etc passed as parameter. In the simplest case it works this way:

$ man scanf

How is this related to Vim? Vim allows contextual access to the system manual using the K command. For example, given the code below:

#include 
int main(int argc, char **argv)
{
  printf("Hello world);
}

We can place the cursor at the “printf” function call and press K.
However, the information showed by man relates to the printf user command. At this point, it is necessary to explain that the system manual is split into several sections (man man for more information). To query the manual about a specific section, we need to pass the section number as first parameter, e.g:

$ man read   # Section 1, shows read /bin/sh built-in command.
$ man 2 read   # Section 2, shows read system call.

Going back to our example, if we want to see the manual page on the printf C function (Section 3 “System library calls”) we need to type 3K. Once you are done with the manual, type ENTER to return to Vim.
This is an extremely useful feature (unless you have memorized all the functions / system calls present in your system)

Folding
Folding is just great. It is a feature that lets you “compress” several lines into a single one which is useful to compress function bodies for instance. The fold can be opened and closed at will. To create a fold, type “zf”. But first, you have to instruct Vim which lines to include. You can do this
in several ways (repetition, selecting the lines in visual mode, etc):

void simple_function(void)
{
 int i;
 int j;
 float f;

return;
}

If we want to fold the variable declaration section and the cursor is placed at the first variable declaration line, we can do the following: “zf2j”.
This tells Vim to create a fold and include the current line and the next two. The same thing can be done with “Vjjzf”. In this case, we go to visual mode, move two lines downwards and create the fold. In both cases, we end up with the following:

void simple_function(void)
{
+--  3 lines: int i;-------------------------------------------------------------------------------------------
       return;
}

Vim replaces the selected lines with a single one. This line has a leading ‘+’ character and shows the first folded line as a reminder for the user. Placing the cursor at that line we can operate with the fold. We can either open it (zo) or close it (zc). These two operations can be applied at every line inside the fold.

Folds behave as other text objects in most aspects. You can cut a fold and paste it elsewhere, however, when you paste it, the fold is destroyed (hold your horses, I said the fold, but your text is still there). If you undo (u) the copy-paste operation, the fold does not come back. If you make a copy, the fold persists, and the new text (wherever you paste it) is pasted unfolded.

Folds can be nested, as in the example below:

int main(int argc, char **argv)
{
       int var1;
       int var2;
       float var3;

       struct person {
               unsigned int salary;
               unsigned char siblings;
               char *name;
       };

       struct person john;

       return 0;
}

First, we collapse the struct person

int main(int argc, char **argv)
{
       int var1;
       int var2;
       float var3;

+---  5 lines: struct person {---------------------------------------------------------------------------------
       struct person john;

       return 0;
}

And then, we compress everything but the return statement.

int main(int argc, char **argv)
{
+-- 11 lines: int
var1;----------------------------------------------------------------------
       return 0;
}

If we unfold the top level fold, the inner one is shown collapsed. The states of nested folds are independent. zd and zD are used to deleted folds (the latter recursively), and zE deletes all the folds in the current window. As a general rule, the capitalized version of all the commands (zC, zO) applies the action recursively.

Marks
The name speaks by itself. Marks allow you to refer to a location in a file, using a name. I make an intensive use of marks, because often, I need to jump from one place to another in the code. Let us see how to use them playing with a small text:

This is the first line
This is a second line
And finally, this is the last line

The cursor is placed at the “r” in boldface in the first line. We use the m command followed by the letter (the identifier) of the mark to create a new mark. For instance ma creates a mark called a. Marks are not shown in Vim in any way, they just exist :)
Once the mark is set, you can jump to it using either or ` followed by the mark identifier. The single quote jumps to the beginning of the line (the T letter) and the backtick jumps to the specific location of the mark (the r letter). The :delmarks command deletes the specified mark and :marks shows all the marks.
There are two kind of mark identifiers:

  • a – z. Valid within a file as long as it is loaded in a buffer
  • A – Z. Valid between files.

When using upper case letters as identifiers, Vim loads the required file if necessary.

Note: There is another kind of mark identifiers (0 – 9) but they are out of the scope of this post.

Marks are specially useful for jumping between two or more functions or locations in your code.

Undo branches
This is a complex topic and I will just introduce it. For more information, see :help new-undo-branches on a Vim 7 editor.
Vim supports undo branches. This means Vim can keep track of the different changes you made to your text (or your code). In its simplest form, you can use two commands, :earlier and :later to bring your code to a previous state. E.g:

:earlier 20s
:later 5m
:earlier 2h

The commands above bring the code to the state it was 20 seconds earlier, 5 minutes later and 2 hours later.
This is useful when making changes to code under no source control systems. Undo branches is a new feature present in Vim since version 7. I recommend you to play with it and learn how to get the maximum out of it.

Vim Sheet (VI)

  • [number]K. Show manual page for the word under the cursor.
  • zf. Create a fold.
  • zo / zc Open / close a fold.
  • zd Delete a fold.
  • zE Delete all the folds in a file.
  • m[identifier] Creates a mark
  • ‘[identifier] Goes to the first non-blank character of the line where the mark is located
  • `[identifier] The same as above but move to the precise location of the mark.
  • :marks Show all the marks
  • :delmarks Delete a mark.
  • :earlier [s/m/h] Brings the text to an earlier state
  • :later [s/m/h] Brings the text to a later state from a past point in the undo branch.

speak up

Add your comment below, or trackback from your own site.

Subscribe to these comments.

Be nice. Keep it clean. Stay on topic. No spam.

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*Required Fields