|
^ Back to Top 1. Introduction |
|
|
vi is unlike most other editors in that it has two "modes". These are: COMMAND mode and INSERT mode. When you are in COMMAND mode, the characters you type will perform special functions (commands), instead of appearing on the screen in your document. When you are in INSERT mode, the characters you type will appear like normal. One advantage of having these two distinct modes is that you can perform a very large and diverse number of complex functions without ever moving your hands from the "home row" on your QWERTY keyboard. I have found that after working through the first few painful days of becoming accostomed to this new editing concept, I am able to edit files (especially programs) much, much more quickly than before. As is usually the case, the quickest way to master the vi editor is practice. USE IT. The command keys will soon flow from your fingers in a way you cannot even imagine now. :-) Give it a shot. You'll probably like it. (And while you're shooting it, make sure you search this document for "undo"... it will save you a lot of time and anguish.) This document attempts to provide an at-a-glance explanation for many of the vi commands. For more precise and in-depth documentation, see the vim help files, by typing :h[elp] at the vim command-line. NOTE: To navigate the help files, you need to have a basic understanding of tags. |
|
^ Back to Top 2. The Tiniest Bit of History |
|
|
The original vi editor has the basic functionality described here. But more recently, a new editor has been developed: vim (standing for vi-improved). The vim editor is extremely capable, as well as well-documented. This document is written for the real newbies (as well as the old-bies who, like myself, are constantly forgetting old tricks). I have probably made mistakes in this document. If you find one, PLEASE email me! |
|
^ Back to Top 3. Conventions |
|
|
I've tried to specify the relevant help-keywords below the title of each section. For example, in section 7 (Edit Mode Access) you see ":help inserting" under the title. If you run that help command in vim you will be taken to the part of the actual vim manual that deals with that topic. |
|
|
Commands preceeded by a colon must be typed on the COMMAND LINE. To reach the COMMAND LINE, type a colon (":") while you are in COMMAND MODE. I will point out here that vim (like bash) has the beautiful feature of TAB-COMPLETION. That means that when you are typing commands on the vim command line, you can press the TAB key, and vim will guess what your command is going to be. (vim will guess command names and filenames!) And if you use my .vimrc (see below), vim will present you with a menu of available options whenever there is ambiguity in your command line at the time you press TAB. |
|
|
Commands with no colon may be typed at any time you are in COMMAND MODE. |
|
|
Commands preceeded by this string: bash $ are shell commands, runable from the Linux command line. (They will only be used in the "Invoking vi" section, below.) Ok, so I'm lying just a little. I also mention shell commands in one other place- in the Misc section. |
|
|
If there appear to be two commands separated by a comma, that is probably the case. Either performs the same function. For example: ZZ, :wq Means that either "ZZ" or ":wq" saves your work and quits. |
|
|
Unless otherwise noted, an optional number in a command string (usually denoted 'n' in this document) always defaults to '1' if it is not present. |
|
|
Except for the regular expression usage of the brackets ("[" and "]"), arguments and portions of arguments in brackets are optional. |
|
|
Except for the regular expression usage of the braces ("{" and "}"), braces with pipes ("|") represent a choice you must make. For example: {h | j | k | l} means that you must choose "h", "j", "k", or "l" as an argument. |
|
|
^ Back to Top 4. Invoking vi[m] |
|
| bash $ vi ["filename"] |
begins a vi session, editing "filename", if "filename" is specified (default is to open a blank session) |
| bash $ vim ["filename"] |
begins a vim session, editing "filename", if "filename" is specified (default is to open a blank session) |
| bash $ alias vi=vim |
makes the command 'vi' invoke vim instead, but only for the current shell To make this "permanent" (which I recommend), insert that command line into your ".bashrc" file, located in your home directory. (Make sure to look your .bashrc over first, in case your administrator has asked you to make your personalizations in another file.) Once you have determined into which file you should insert your environment personalizations, typing the following string of characters would do so. (In this example, the string "filename" represents your filename, and you should substitute yours for it. "{CR}" represents a Carriage Return, and "{ESC}" represents the Escape key.) Keystrokes: vim filename{CR} Goalias vi=vim{ESC}:wq! |
| bash $ man vi |
shows you the manual for vi This will let you know about all the arguments you can pass to vi, so that it behaves in different ways. |
| bash $ man vim |
shows you the manual for vim This will let you know about all the arguments you can pass to vim, so that it behaves in different ways. |
|
^ Back to Top 5. Settings & Your .vimrc |
|
|
One of the cool things about vim is that you can control much of your environment through a config file, which lives in your home directory and is called ".vimrc". This file is examined every time you start a vim session, and it can create a whole host of settings for you. Here is my entire vim setup: my vimsettings. Run bash $ tar -xzvf vim_settings.tgz in your home directory to use my settings, which have been compiled from a number of sources. CAUTION: Yours will be overwritten! |
|
| :set | shows you the current settings of your vim session |
|
^ Back to Top 6. Command Mode Access Command |
|
| ESC |
Enter COMMAND mode (may be repeated in case you are not sure in which mode you are) CAUTION! If you are using classic vi, hitting ESC twice will exit your editor! |
|
^ Back to Top 7. Edit ("Insert") Mode Access Commands :help inserting |
|
| i |
Enter INSERT mode, and place the cursor before the current character. |
| I |
Enter INSERT mode, and place the cursor at the beginning of the line. |
| a |
Enter INSERT mode, and place the cursor after the current character. |
| A |
Enter INSERT mode, and place the cursor at the end of the current line. |
| o |
Enter INSERT mode, and place the cursor in a new, blank line below the current line. |
| O |
Enter INSERT mode, and place the cursor in a new, blank line above the current line. |
|
^ Back to Top 8. Mastering the Vim Command Line |
|
|
The vim command line behaves in a manner similar to the bash or ksh command lines when they are in emacs mode. <irony> THE VIM EDITOR USES EMACS- STYLE COMMAND LINE EDITING.</irony> That means that some of the editing keys from emacs work on the vim command line. These include... |
|
| ^a |
place the cursor at the beginning of the current command line ("^a" means CTRL-a) |
| ^e |
place the cursor at the End of the current command line ("^e" means CTRL-e) |
| ^p, up-arrow |
recall previous commands, travelling upward through your command history ("^p" means CTRL-p) |
| ^n, down-arrow |
recall next command, if you have already travelled upward into your command history ("^n" means CTRL-n) |
| ^c |
abort current command & return to editor ("^c" means CTRL-c) |
| ^u |
erase current command line and place cursor at its beginning, after the colon ("^u" means CTRL-u) |
| ESC (pressed twice) |
abort current command & return to editor (same functionality as "^c") |
|
^ Back to Top 9. File Commands |
|
|
In general, following a command with an exclamation point forces the command to execute and squelches warnings. You will see examples of this below. |
|
| :w[rite] | Write current file |
| :w[rite] "filename" | Write to "filename" |
| :w[rite]! "filename" | Write to "filename" even though "filename" exists |
| :m,nw "filename" | Write lines m through n to "filename" |
| :q[uit] | Quit |
| ZZ, :wq |
Combination of ":w[rite]" and ":q[uit]"; Write current file and quit |
| :wq! |
This time I MEAN IT!!! WRITE AND QUIT!! Seriously, squelches "This file is read only, are you SURE you want to write to it?" warning. |
| :q[uit]! | Quit without saving changes |
| :r[ead] "filename" |
Read and insert contents of "filename" after current cursor location |
| :e[dit] "filename" |
Close current file, and open "filename" in its place. |
| :e[dit]! "filename" |
Close current file, discarding changes, and open "filename" in its place. |
| ^g, :f[ile] | report information about the current file ("^g" means CTRL-g) |
|
^ Back to Top 10. Cursor Movement Commands :help left-right-motions :help up-down-motions :help scroll-down :help scroll-up :help scroll-cursor |
|
|
The regular arrow keys may work in your vim setup. I would recommend that you learn the following "home row" movement commands, however. First of all, the original vi won't let you use the arrow keys, and you may be forced to use it someday. Secondly, by using the arrow keys you lose so much of the benefit of being able to do everything you want to without needing to move your hand... 'h','j','k', and 'l' will quickly become natural to you, and you will be frustrated that other editors don't have this convenience. |
|
| h | move left one position |
| l | move right one position |
| j | move down one line |
| k | move up one line |
| gj |
move down one screen line (avoids line-wrap annoyances) |
| gk |
move up one screen line (avoids line-wrap annoyances) |
| 0 (zero) | move to beginning of current line |
| $ | move to end of current line |
| w |
move forward one word (punctuation delimited) |
| W |
move forward one word (whitespace delimited) |
| b |
move backward one word (punctuation delimited) |
| B |
move backward one word (whitespace delimited) |
| e |
move to the end of the current word (punctuation delimited) |
| E |
move to the end of the current word (whitespace delimited) |
| [n]^e |
scroll forward n "Extra" lines ("^e" means CTRL-e) |
| [n]^y |
scroll back n lines NOTE: In MS Windows, CTRL-y is remapped to "redo". ("^y" means CTRL-y) |
| [n]^b |
scroll back n pages ("^b" means CTRL-b) |
| [n]^f |
scroll forward n pages ("^f" means CTRL-f) |
| [n]^u |
scroll back (Up) n/2 pages ("^u" means CTRL-u) |
| [n]^d |
scroll forward (Down) n/2 pages ("^d" means CTRL-d) |
| G | go to end of file |
| nG, :n | go to line n |
| L | go to last ("Low") line on screen |
| M | go to middle line on the screen |
| H | go to first ("High") line on screen |
|
^ Back to Top 11. Edit Commands :help deleting :help { delete-insert | replacing } :help { simple-change | changing } :help complex-change :help copy-move :help formatting :help C-indenting |
|
|
In general, 'd' deletes. Preceeding 'd' with a number makes that many deletions happen, and following 'd' with a movement command (h,j,k,l,w,b,e,W,B,E) makes the deletion happen in that direction. |
|
| [n]x |
delete n characters |
| [n]dw |
delete n words |
| [n]dd |
delete n lines |
| d$ | delete to end of line |
| d^ | delete to beginning of line |
| dgg | delete through beginning of file |
| dG | delete through end of file |
| [n]cw |
change n words (delimited by punctuation) |
| [n]cW |
change n words (delimited by whitespace) |
| c$ | change to end of line |
| c^ | change to beginning of line |
| cG | change through last line |
| [n]~ |
switch the case of the next n characters |
|
"Yanking" takes some portion of your file and places it in a "buffer", so that you can "place" that portion of your file somewhere else. (You are probably familiar with the analogous terms "copy" and "paste".) In this somewhat out of context place, I will mention that if you wish to paste into vi from another application you should: 1. be in insert mode 2. have "paste" set (Run ":set paste" on the vi command line.) |
|
| [n]yw |
yank (copy) n words (delimited by punctuation) |
| [n]yW |
yank (copy) n words (delimited by whitespace) |
| yy | yank (copy) current line |
| [n]yy | yank (copy) n lines |
| y$ | yank (copy) to end of current line |
| y^ | yank (copy) to beginning of current line |
| [n]p |
place the contents of the buffer after the current cursor location, n times |
| [n]P |
place the contents of the buffer before the current cursor location, n times |
|
All of the above commands yank into and place from the default buffer. It is also possible to yank into a named buffer. The advantage of this is that you can have several different things available for placing ("pasting") at any time. For example, right now I can 'place' A new table, a new row, or a new 'separating' row, like the one above this cell. (Go ahead, look at it.) Thus, with three keystrokes, I can place any one of those three html constructs into my file, and I avoid the hassle of typing each and every html tag repeatedly... So how can you do that? Read on... |
|
|
A buffer may be named with a single character. I'm not exactly sure which ones are available, I just use the alphabetic characters. Any of the above yanking or placing commands can be preceeded by (literally): "a Where the 'a' is the name of your buffer. For example, "t3yy copies the current line and the next two lines into the buffer named 't'. To place the contents of a buffer, use the same syntax. For example: "tp places the contents of the buffer named 't' after the current cursor location. I have read that the original vi editor only has 4 named buffers, so whenever you write to a fifth, the first is destroyed. I really don't know how many the vim (vi-improved) editor has... I've never used more than 4 or 5. The only way to master these is to experiment. In time, you'll find these methods of duplicating and moving your text so much more convenient than constantly moving your hand to your mouse and scrolling, copying, pasting, scrolling, copying, pasting... |
|
| r |
replace current character |
| R |
replace (overstrike) until you enter command mode (by pressing ESC) |
| [n]u |
undo the last n changes you made |
| U | undo all changes to current line |
| [n]^r |
redo the last n changes you undid |
|
^ Back to Top 12. Markers :help mark-motions |
|
|
You can have "markers" in your file, meaning that a certain line-location in your file can be named by a marker, so that you can return to it instantly if you desire to do so. (This can prevent you from scrolling back and forth in a file time after time after time...) |
|
| ma |
mark the current location and name it 'a' (I'm not sure which characters may be used to name markers, but I've never needed more than a few alphabetic characters.) |
| 'a | jump immediately to the marker named 'a' |
|
^ Back to Top 13. Search Commands :help search-commands |
|
|
Regular expressions may be used here, see list of metacharacters below. |
|
| /searchstring |
search forward for "searchstring" |
| ?searchstring |
search backward for "searchstring" |
| [#]n |
repeat last search # times, whatever it was (1 is default for #) |
| [#]N |
repeat last search # times, but search in opposite direction (1 is default for #) |
| * |
searches forward for the word currently under the cursor |
| # |
searches backward for the word currently under the cursor |
|
^ Back to Top 14. Search & Replace :help substitute |
|
|
Regular expressions may be used here, see list of metacharacters below. |
|
| :[scope]s/searchstring/replacestring/[g][c][i] |
search for "searchstring" and replace it with "replacestring" By default, the search & replacement only happens in your current line. Including the optional 'scope' argument can change that. (Possible values for a 'scope' argument specified below.) By default, the search & replacement only happens for the first instance of "searchstring" on a line. Including the optional 'g' suffix changes that to be "Global", all instances of "searchstring" are replaced on a line. By default, the search & replacement happens all at once. Including the optional 'c' suffix changes that, and each replacement must be actively "Confirmed" before it is performed. By default, the search & replacement is case-sensitive. Including the optional 'i' suffix changes that, and the operation happens with case "Insensitivity". |
| Possible definitions of "scope" | |
| % | entire file |
| m,n | include lines m through n |
| '<,'> | text selected in Visual Mode |
|
^ Back to Top 15. Vi Metacharacters (characters that mean more than themselves) These will likely be very confusing at first, so start small. It will help if you familiarize yourself with such tools as sed, awk, and grep, and the language PERL, as well. NOTE: The vi metacharacters differ slightly from those in other regex tools. ADDITIONAL NOTE: I neglected to refer to the "magic" and "nomagic" modes in this section; this is an important oversight which I hope to correct someday. |
|
| ^ | matches the start of a line |
| $ | matches the end of a line |
| . |
matches any single character (except an end-of-line) |
| \p | printable character |
| \s |
whitespace (space or tab) character - same as typing [\ \t] |
| \S |
non-whitespace character (opposite of \s) - same as typing [^\ \t] |
| \d |
digit (0-9) - same as typing [0-9] |
| \D |
non-digit - same as typing [^0-9] |
| \a |
alphabetic character - same as typing [A-Za-z] |
| \A |
non-alphabetic character - same as typing [^A-Za-z] |
| \l |
lowercase character - same as typing [a-z] |
| \L |
non-lowercase character - same as typing [^a-z] |
| \u |
uppercase character - same as typing [A-Z] |
| \U |
non-uppercase character - same as typing [^A-Z] |
| \t | tab character |
| \r |
return (carriage return) character (in replacestring only) |
| \n |
return (newline) character (in searchstring only) |
| [] |
accept any character between the brackets (indicate ranges with a hyphen) For example: [abcde] will find 'a', 'b', 'c', 'd', and 'e'. [a-e] will find the same letters. [a-zB-F] will find all the lowercase letters, along with the uppercase letters B through F. |
| [^] |
The '^' character has special meaning when it is between brackets. In that context it reverses the effect of the brackets. For example: [^abcde] will find anything but 'a', 'b', 'c', 'd', and 'e'. [^a-e] will find anything but those same letters. [^a-zB-F] will find anything that is neither a lowercase letter nor an uppercase letter from B through F. |
| * |
Find 0 or more of the preceeding item. For example: /du*mb finds a 'd' followed by any number of 'u's, followed by 'm' and 'b'. |
| + |
Find 1 or more of the preceeding item. For example: /du+mb finds a 'd' followed by AT LEAST ONE 'u', followed by 'm' and 'b'. |
| \= |
Find 0 or 1 of the preceeding item. For example: /du\=mb finds only "dumb" and "dmb". |
| \{m,n\} |
Find at least m but not more than n of the preceeding item. For example: /du\{1,5\}mb matches the following strings: dumb duumb duuumb duuuumb duuuuumb /d\{1,2\}u\{3,6\}m\{3,4\}b matches the following 16 strings: duuummmb dduuummmb duuuummmb dduuuummmb duuuuummmb dduuuuummmb duuuuuummmb dduuuuuummmb duuummmmb dduuummmmb duuuummmmb dduuuummmmb duuuuummmmb dduuuuummmmb duuuuuummmmb dduuuuuummmmb |
| \(\) |
Keeps the characters between the parenthesees in a special "search and replace" buffer, so those characters can be used in the replace string. The characters within the first set of parenthesees are saved in special buffer \1, and each successive set of parenthesses saves its contents into the next number. For example: :s/^\([a-z][B-E][1-8]\)/wobba \1/ searches for the ranges [a-z][B-E][1-8] at the beginning of the line, and replaces that string with "wobba " plus itself. More usefully, the following command switches the first two fields in a comma delimited file: :%s/^\([^,]*\),\([^,]*\)/\2,\1/ |
|
In order to search for a character that is also a metacharacter, you must precede it with a backslash. For example: /^balzak\^ will find an instance of the string "balzak^" at the beginning of a line. /\\backslash\/forwardslash will find the following string: \backslash/forwardslash Experimentation is the key here. If it didn't work the way you wanted, undo your mistaken changes, and try it again. |
|
| Much-needed search/replace examples | |
| :%s/\t/ /g |
scope: file-wide searchstring: tab character replacestring: two spaces Replaces all tab characters in file with two spaces. |
| :%s/cellpadding=3/cellpadding=6/gc |
Replace all occurances of "cellpadding=3" with "cellpadding=6". |
| :%s/^\([\ \t]*\)n/\1\[n\]/c |
scope: file-wide searchstring: beginning of line followed by 0 or more spaces or tabs, until the character 'n' is found. This is all saved into buffer 1. replacestring: the contents of buffer 1, followed by "[n]", pending individual confirmations. In other words, every time 'n' is the first character on a line, retain its indentation level, and replace 'n' with "[n]". (I just used this to place brackets around the optional 'n's in this document.) |
| :%s/^\([^,]*\),\([^,]*\)/\2,\1/ |
scope: file-wide searchstring: beginning of line followed by 0 or more characters that are anything but commas, all saved into buffer 1, followed by a comma, followed by 0 or more characters that are anything but commas, saved into buffer 2. replacestring: the contents of buffer 2, (the second field in a comma delimited file) followed by a comma, followed by the contents of buffer 1 (the first field in a comma delimited file). |
|
^ Back to Top 16. Using Vim Editing Windows :help opening-window |
||
|
Vim gives you the capability to edit more than one file simultaneously. (This allows you conveniently to yank (copy) and place (paste) between files.) |
||
| :sp[lit] [filename] |
opens an additional window in the current session, editing the file "filename", if specified |
|
| :vsp[lit] [filename] |
opens an additional vertical window in the current session, editing the file "filename", if specified (most often used with vimdiff) |
|
| z height | make the current window "height" lines tall | |
| ^w |
prepare for a window command ("^w" means CTRL-w) |
|
|
The following commands must be preceeded by the ^w command (see above). |
||
| h |
Move cursor to the window to the left of the current window. |
|
| j |
Move cursor to the window below the current window |
|
| k |
Move cursor to the window above the current window. |
|
| l |
Move cursor to the window to the right of the current window. |
|
| [n]+ |
increase the current window's relative size by n lines |
|
| [n]- |
decrease the current window's relative size by n lines |
|
|
^ Back to Top 17. Tags - How to Navigate Intelligently :help tag-commands |
|
|
A tag is an identifier that appears in a "tags" file; it is a sort of label to which you can jump. This "tags" file must be generated by a program like ctags before the tag commands can be used. (One very common use of tags is to jump to and from different function definitions in C programs; see the ctags manpage for details.) |
|
| ^] |
jump to the tag referenced by the keyword currently under the cursor; push this location onto the stack ("^]" means CTRL-]) In the vim help file, these appear like this: |I-am-a-keyword-tag-thingy| |
| ^t |
return from the current jump; pop the previous location off the tag stack ("^t" means CTRL-t) This returns you to wherever you were before you hit "^]". |
|
^ Back to Top 18. Visual Mode - How to Select Text Quickly :help visual-start |
|
|
In vim you can select text visually when you are in Visual Selection Mode. Simply move your cursor normally, and the text over which you move will be highlighted. After you have highlighted the section of text you want, you can perform commands upon it, such as deletion, yanking, searching, and replacing. Experimentation is the key; always remember undo. If you type a colon (":") while you have text selected, the following will appear on your command line: :'<,'> This simply means that the scope of your command is the text you have selected. |
|
| v | enter visual selection mode |
| ESC (pressed twice) |
leave visual selection mode (selected text is un-selected) |
|
^ Back to Top 20. Macros - How to Record and "Play back" Complex Operations :help { q | recording } |
|
| q{0-9a-zA-Z"}.+q |
The first {0-9a-zA-Z"} character after q is used as the name of a register into which the remaining commands/characters up to the concluding q are recorded. |
| [n]@{0-9a-z".=*} |
Execute the contents of register {)-9a-z".=*} n times. Example: qh0w2xibarf{ESC}jq This records in register 'h' a command to replace the first 2 non-blank characters of the current line with "barf", before moving on to the next line. 10@h This command, when executed subsequently, replaces the first 2 letters of the current and next 9 lines with "barf". Of course, this could be done with a simple s[ubstitute] command as well, but the next one wouldn't be so easy: qf0w3^aj This has recorded in register 'f' a command that increments the number at the beginning of the current line by 3. ("^a" means CTRL-a) NOTE the 'j' at the end of each of these examples. If you're going to use a macro with a number of repititions, you need to move to the next (or previous) line before the next repition starts. These are very simple examples, but macros can be incredibly complex. See the vim help for much more precise documentation. |
|
^ Back to Top 98. Other Vi[m] References |
|
| Linuxdoc How-To | |
| Vim Cookbook | |
| Newbie C/C++-focused Reference | |
|
^ Back to Top 99. Miscellaneous Useful Stuff |
|
| [n]. |
repeats previous command n times (doesn't work for everything, you'll just have to experiment) |
| J |
deletes carriage return at end of current line |
| % |
when cursor is on a parenthesis, a bracket, or a curly brace, the "%" sign moves it to the corresponding opening or closing character (handy for checking that your statements are closed off, and for moving back and forth between the beginning and end of a function) |
| gq{h | j | k | l} |
fix justification (line wrapping) of current paragraph |
| :!shell_command |
executes "shell_command" in the shell, and returns the results to your terminal If you combine this with the ":r[ead]" command, you can read the output of your shell command into your file. For example: :r !ls $HOME will read a list of the files in your home directory into your file. |
| [n]== |
adjust the indentation of the current line and the
following (n-1) lines If you have a certain indentation scheme configured (such as C code), this can re-indent your code for you. Very handy. |
| ^l |
redraw the screen deletes annoying stderr messages from other programs ("^l" means CTRL-l) |
| ^p |
complete the word under the cursor, if possible, by searching backward through the current document to find words that begin the same way (awesome tool that helps you avoid re-typing long names) ("^p" means CTRL-p) |
| ^n |
complete the word under the cursor, if possible, by searching forward through the current document to find words that begin the same way (awesome tool that helps you avoid re-typing long names) ("^n" means CTRL-n) |