Wills' Projects: Vi, VIm, and Friends
A Brief History
Historically, vi (the "VIsual editor") is a front end to a family of other editors including 'ex' and 'ed'. These are roughly analogous to DOS' edlin.
vi's sources were originally licensed in such a proprietary way that the only way to have vi on Linux-based systems was to use a clone. The most revered is VIm (Vi IMproved), which amongst other plus points has a "minimal" implementation for use as /bin/vi, and extended features [and a "compatibility" mode] when built for use as /usr/bin/vim and/or /usr/bin/gvim (the GUI version).
Even VIm's "minimal" implementation is a bit bloaty for embedded class systems, however, and the alternative you'll find in use will either be a workalike (BWIM editor with vi key bindings), or the vi applet belonging to the 'busybox' utility. As one might suspect, busybox-vi does not implement everything listed here; in other cases, the behaviour differs in some slight way.
Basic Philosophy
Designed for use over a slow network link, vi is one of the most powerful text editors you will ever use. Because you'll probably very rarely use meta-keys other than shift, you should never need to move your hands far from the 'home' position - making vi incredibly efficient in the hands of a touch typist.
Bare Essentials
vi starts in "command mode" by default, where any keypress performs some operation. Some operations leave vi in command mode, and some enter insert mode - from which the Escape key exits at the end of your text entry. Pressing shift often invokes a related variant of some operations (although sometimes it's a different command entirely) - see notes in brackets.
All vi clones support at least the following:
Keys/Command | Behaviour |
---|---|
h,j,k,l | Single-character movement [left, down, up, right]. |
i(I)...<Esc> | Insert at cursor (at start of line - ignore spaces). |
a(A)...<Esc> | Append text [after cursor] (at end of line). |
r<c> | Replace character under cursor with <c> |
s...<Esc> | Substitute character under cursor for specified text. |
x | Delete character at cursor [place into cut buffer]. |
p(P) | Paste cut buffer into text after (at) cursor/current line |
/...<Enter> | Search for specified regexp (use ? for backwards) |
n | Find next match (N to reverse direction) |
u | Undo/redo (vi - see Vim Specifics) |
^L,^R | Redraw editor screen [when background processes have corrupted the display] |
Although there are 'vi' commands to save, it's often less confusing to use the 'ex' command line by pressing : in command mode, where the following are useful:
Keys/Command | Behaviour |
---|---|
:<n> | Go to line <n> |
:w | Enter 'ex' command mode; save the file. |
:wq | Enter 'ex' command mode; save file and quit |
:q | Enter 'ex' command mode; quit (unless not saved) |
:q! | Enter 'ex' command mode; quit (even if unsaved) |
:w! | Enter 'ex' command mode; save (if flagged read-only) |
All 'vi' commands can be repeated by prefixing a number; for example 10j moves ten characters to the left, and 4r replaces a four-character string [with four copies of the character you specify] - compare and contrast to 4s, whereby insert mode means any alternative text [ie, a replacement string of any length].
Advanced Movement
Keys/Command | Behaviour |
---|---|
H,M,L | Move cursor to highest/middle/lowest line of screen |
<n>gg | Go to line <n> [in file] |
G | move to end of file |
^,$ | Go to start/end of line (cf. regular expressions) |
w,e,b | Move forward/back one word |
{,},2{,2} | Move forward/back one [two] paragraph[s] |
m<c> | Set marker with name <c> |
`<c> | Go to mark named <c> |
`` | Go to position of last change |
% | Find matching brackets - works for (/),[/],{/} |
^D,^U | Move up/down half a screenful |
Complex Operations
As well as repeating a command by using a numeric prefix, the more complex commands require an "operating region". There is often a default region, which you override by specifying a movement command.
Keys/Command | Behaviour |
---|---|
<<,>> | Indent or outdent current line |
<%,>% | Indent or outdent region - eg. block of code. |
dd | Delete (current line) |
3dw | Delete three words |
cc...<Esc> | Change (current line) |
c}...<Esc> | Rewrite rest of paragraph |
yy | "Yank" (current line) into cut buffer |
3yw,3ye | Yank "words" into cut buffer |
Miscellany - Cut Buffers
If you've done several delete/change/subsitute/etc commands, 'undo' might not do what you want (especially in 'vi'). There is a ten-level history of such changes, all recoverable with prefixes to p or P [ie., the paste command]. There are also twenty-six lettered buffers, which you can employ at will, viz:
Keys/Command | Behaviour |
---|---|
"1p | Paste the last change-history buffer (same as p alone) |
"<n>P | Same, but for buffer <n> |
"ayy | Yank current line to buffer 'a' |
"<c>2yy | Yank [two] lines to buffer <c> |
Miscellany - Other
Also useful:
Keys/Command | Behaviour |
---|---|
:help | Help page {VIm only - not a standard 'ex' command} |
^G | Show current file, file size, whether modified |
J | Join two lines |
K | Search the manual pages for keyword under cursor {VIm} |
xp | (Compound) Swap two characters |
eas<Esc> | (Compound) Pluralise word |
~ | Change character case, and move to next |
:set nu | Short for 'number' - line numbers. (nonu -> off) |
:set all | Show all settings |
:set | Show only settings which are not at default |
:e! | Abandon current changes; reload current file |
:e <filename> | Load specified file (use e! if current buffer unsaved) |
:r <filename> | Read (insert) specified file |
:n <filenames> | Edit each file in turn - add ! as above |
:n | Short for 'next' - move to next file in list |
:prev | Short for 'previous' - move back one file in list |
:!... | Execute command ... in shell |
!!... | Execute command ...; paste output into current line |
VIm Specifics
VIm has a number of extensions which reflect functionality in modern text editors, including multi-level undo. Relevant controls include:
Keys/Command | Behaviour |
---|---|
u | Undo (always) |
U | Undo/redo (as per u in classic vi) |
^R | Redo (beware your terminal reacting to ^R) |
:set compatible | Turn (most) VIm extensions off |
:set ff=unix | Force VIm to save with unix newlines (for DOS files) |
:split | Enter split-screen mode, filename optional. :qa quits editor |
^Wj,^Wk | Move up/down between 'split' windows |