Tuesday, May 29, 2007

Moving around in VIM : buggy terminal edition

Buggy terminals are one of the most frustrating things one can encounter when trying to edit a file on remote site.

Big boys like Emacs are out of question immediately, since they depend on <Esc> sequences too much. And the sequences are what is used to represent functional, arrow and motion keys in Unix world. Often even Backspace and Delete fall victims of buggy terminals.

Though unpractical, it is often required to edit at least single file on remote site - to tell it proper terminal configuration - before anything else might be done.

VIM is for rescue. VIM (ans as its ancestor VI) were designed in times when there were no such keys available at all. It might be painful to work that way, yet quick edit is quite OK.

All the command are to be used in normal (non-insert) mode. Some of them as noted change vim's mode. To go back to normal mode, press Ctrl-[ or Esc.

u Most important command here: undo.
/ Search forward - the most effective way to move around in vim.
? Search backward.
:NNN<Enter> Go to line number NNN.
Pressing 'x' would delete character under cursor. With repetition counter, can delete more than single character in a go: e.g. '20x' would delete 20 characters starting with current one (and analogous to pressing 'x' twenty times).

Backspace key (delete backward) is 'hx'. Delete key (delete forward) is 'x'.

Pressing 'r' would replace character under cursor with character pressed after 'r'. e.g., 'ra' would replace character under cursor with character 'a'.
'f' stands for Find and moves cursor forward to next occurrence of given character.

e.g., 'fa' would move cursor to next character 'a' in current line.

Variation: 'F' (capital f) searches backwards.

Move cursor to the end of current line.
Move cursor to the beginning of current line.
h, j, k, l Move cursor to left, down, up and right correspondently. Very useful with repetition counter: e.g. '10h' (typed 10 followed by 'h') would move cursor ten characters left.
w, e Move cursor over words forward. 'w' stops at word beginnings. 'e' stops at word ends. 'W' and 'E' are the same, but they move backwards.
d Most dangerous command here. Or rather 'd' isn't command, but a modifier. Pressing 'd' before any motion command would delete characters/lines traveled.
e.g. 'df<Space>' would delete all characters from one under cursor till next Space (Space itself included).
e.g. 'dl' would delete current character and one next to it. Analogous to 'xx' or '2x'.
e.g. 'dj' would delete current line and one after it. Analogous to 'dddd' or '2dd'.
e.g. 'd$' would delete characters starting from current one to the end of line. Analogous to 'D'.
e.g. 'd/xxx' would delete characters starting with current one up to next entry of 'xxx' string in text (not including - search stops before - string itself).
dd Delete current line.
c Change operator. Analogous to 'd', it deletes according to given motion, but after deletion switches to insert mode.
cc Clears current line and switches to insert mode.
C Clears line starting from character under cursor and switches to insert mode.
i Pressing 'i' would put vim into edit (insert) mode.
R Pressing 'R' (Shift-r) would put vim into replace mode (or in PC editors called "overwrite" mode). Unlike insert mode, where typing inserts characters, in replace mode any typed character would replace character under cursor.
A Pressing 'A' (Shift-a) in command mode would make vi to go into insert mode and move cursor to end of line after last symbol.

That's about it. Move around with searches ('/' and 'f'), delete with 'x' or 'd'. Insert mode - 'i'. Replace mode - 'R'. Ctrl-[ - to go back to normal mode. Something went wrong - undo with 'u'. And of course ':w' to write changes and ':q' to exit.

Edit1. He-he. As soon as I have written that I ended up working under the ever-sucking Solaris with its original vi whos author needs to be shot dead 666 times to get him out of genetic pool - to make sure that no such thing would ever appear.

Another important point. Adding something at the end of something. This is next to impossible in original vi. With little bit of tinkering I came to conclusion that only way to do that is through substitution.

Add at the end of the line with :s/$/ missing word./<Enter> (See also 'A')

Add new line with :s/$/<^V><^M>/<Enter> (<^V><^M> == Ctrl-V Ctrl-M == ^V says to terminal to insert next typed symbol (^M) verbatim. And ^M is "new line" symbol, which understood by vi as your intention to add a new line. (Enter under Unices is "carriage return")). Doing that on last line in file would add a new line after last.

Adding new line before first apparently can be done with :s/^/<^V><^M>/<Enter> which is analoguos to previous trick - but instead of '$' (end of line) we substitute '^' (beginning of line).

Last words: Solaris muzz-die. It looks to me like my beloved Belarus which is often called a "reservation of communism." Same way, Solaris can be called a "reservation of Unix" - of all those mistakes made 30 years ago, fixed everywhere else, with only Sun keeping them in place. For backward compatibility I gather.

Edit2. Added '^' - moving to beginning of line.

Edit3. Added 'A' - inserting text at end of line.

No comments: