vi/vim lessons 1 - 7

Basic Editing

1 Like

We are going to put each one of these seven lessons into it's own thread and then see if we can get a discussion going on each (improvements, suggestions, errors, etc.) - Maybe we'll make a new (better?) set?

1 Like

Good idea!

Just an addendum:

vi auto-indent mode

vi is a programmers editor and programmers usually want their texts to be neatly indented. One doesn't write:

if [ <some condition> ] ; then
while [ <other condition] ; do
something
done
else
something_else
fi

but rather

if [ <some condition> ] ; then
     while [ <other condition> ] ; do
          something
     done
else
     something_else
fi

To indent every line by hand is possible - but there computers for that, no? Alas, it is not obvious how to do this with vi. Here is, how it works.

The first thing you have to decide upon is how many characters you want to indent. I am most comfortable with 5 characters, as you can see in the little piece of pseudocode above, but that is just personal taste - whatever works for you is fair game. How many characters make one "indent-step" is controlled by the variable "sw" (for shift-width), which you can set at the colon-prompt (lasting only for the current session) or in your "~/.exrc" (for lasting effect). Enter:

sw=5

or any other number of characters you want to indent. Now have the following keys/possibilities: at the colon-prompt you can use ">" and "<" along with ranges to move (a number of) lines to the left or right. For instance, sippose your current line is 2 and you want to indent the while-block one level:

if [ <some condition> ] ; then
while [ <other condition> ] ; do
     something
done
else
     something_else
fi
~
~
~
~
:.,+2 >

You can also use "<<" and ">>" as commands, which will move the current line one level leftwards/rightwards. Prepend these commands with numbers to move blocks of lines. In the above example "3>>" issued with line 2 as current line would have done the same thing. This way you can reindent large pieces of code you have copied from somewhere else quickly.

You probably want new lines to start automatically at the same indent level as the last line. For this there is another vi switch which complements "sw": it is "ai" (auto-indent). Again, set it from the colon-prompt ("set ai" to switch on / "set noai" to switch off) or put that in your "~/.exrc"-file for lasting effect. When you hit "<ENTER>" to end a line you will notice that the cursor will be positioned in the next line not in column 1 but at the same column where the last line started. Indent a line, switch to insert mode by pressing "A" (append to end of line) and the press <ENTER> to see the effect.

CAUTION: You probably sometimes change to insert mode, mark something with your mouse in another window and then paste it into your vi buffer. You can do that, but when autoindent mode is set lines not start in the leftmost line will "accumulate" the indentation.

Paste this:

  line 1
  line 2
  line 3

into a vi session with autoindent on and it looks like this:

  line 1
    line 2
      line 3

Pasting for vi is just keystrokes and the end of a line is like an <ENTER>. Switch off the mode at the colon-prompt first (":set noai"), paste and only then switch it back on (":set ai").

All this is nice and fine, but you probably want also a way to change indent levels while in insert mode, because you don't want to first write a line, then change its indentation, then write the next line, etc.. For this there are two commands which change the indentation level of a whole line in insert mode:

CTRL-T
CTRL-D

Both shift the whole current line, regardless of cursor position, to the right (CTRL-T) or the left (CTRL-D). Both will not leave insert mode.

Another word of caution: vi uses tab characters to indent lines when the indentation is deeper than one tab only fills up with spaces. It even silently replaces space characters with tabs if you change a lines indentation. Many people (me included) don't like their program files not to be indented with tabs, because tabs width can be redefined to destroy the proper indentation. I have not found yet how to switch off this rather annoying behavior, instead i have written a small sed-program to change leading tabs to (eight) spaces. Replace "<spc>" and "<tab>" with literal tabs/spaces:

sed -e :a -e 's/^\(<spc>*\)<tab>/\1<spc><spc><spc><spc><spc><spc><spc><spc>/;ta'

I hope this helps.

bakunin

2 Likes