[NOTE THIS FILE IS A WORK IN PROGRESS] VI Handout - J. Maybury (adapted from notes of J. Plane) -------------------------------------------------------- To start vi you type: vi or vedit [for beginner users I suggest using vedit] at the UNIX prompt (%). is the name of the file you wish to edit. When you do this vi will start up and will COPY the contents of the file into the work buffer (see below). NOTE: does not have to appear between < and > (unless the name of the file starts with a < and ends with a >. Also if does not exist it will start vi editing a new empty/blank file. vi is a "full screen" editor and that the buffer will fill up the entire screen *except* for the bottom most line which is the "status or command" line (pressing control-g will display the current status of the buffer down here). vi is fairly "old" and is based off of a single line editor (ex) which is where vi "inherits" many of its features/flaws. Also, vi will "display" the end of a file by displaying any lines beyond the end of the file with tildas (~) on them (open up a new file and you will see a bunch of tildas - they are not part of the file, but just vi telling you where the file ends. Disclaimer: This is not a complete reference of all possible vi commands and some versions of vi may or may not support all of the commands listed below. In vi you are always in one of 3 modes (states): ------------------------------------------------ INPUT (or insert) MODE - in this mode any keys you type get inserted into the work buffer (which upon saving gets written to the file associated with the work buffer). To get out of INPUT MODE you need to press the escape (pressing escape multiple times is ok). COMMAND MODE - this is the *DEFAULT* mode that you start out in. In this mode any key you press acts as a command and may or may not have immediate results. This is the main (and "mysterious") mode to move around in the file and perform operations on the file - if you master using the COMMAND MODE you have basically mastered using vi. LASTLINE (or command-line) MODE - this is similar to command mode but where you can enter special commands or commands that may require pressing more than one or two keys. IF AT ANY TIME YOU EVER RUN INTO "TROUBLE" DO THE FOLLOWING: 1) Press escape several times - this will force you into command mode no matter what mode you are in. 2) Type ":quit" (without the quotes). If this doesn't work you can type the following ":quit!" - note this will loose any changes you may have made. LASTLINE MODE related commands: ------------------------------- To get into lastline mode you must currently be in command mode (pressing escape once (or many times) will get you into command mode no matter what mode you are in). When in command mode if you type : you will be placed into lastline mode where you then type the rest of the lastline command given below and press return (or escape) to execute that command. :$ - will move the cursor to the last line in the buffer :1 - will move the cursor to the first line in the buffer : - will move the cursor to the 'th line in the buffer. For example :50 will move to line 50 :quit - will exit vi (only if no changes have been made to the buffer since it was openned or last saved). :q - identical to :quit :quit! - will exit vi even if changes have been made (it does NOT save those changes). Also can type :q! :write - will save the buffer to the file which the buffer is currently associated with. :w - identical to :write :wq - will save and exit vi. Pressing ZZ in command mode will do the same as this. :w - will save a copy of the buffer into a new file named (it will not overwrite a file that already exists). :w! - will save a copy of the buffer into even if that file already exists. :w >> - will append a copy of the buffer to . :e - will clear out the buffer and replace it with (only if the current buffer has not been "modified"). :edit also works (means you want to edit a new file). :e! - will clear out the buffer (no matter what) and replace it with . :e or :e! - by itself it will bring in a "fresh" copy of the current file (into the buffer) - note: :e! is very dangerous (but sometimes useful). :r - (:read also works) will read/insert the entire contents of into the current buffer and will place it *between* the line the cursor is currently on and the line just below the line the cursor is currently on. :r - this is an "odd" operation to do but should be self explanatory (based on your knowledge of :w and :e). :! - allows you to do one Unix shell command without modifying the buffer. It will display the results of the Unix command at the bottom of the screen and then when you press any key those results will disappear and you will be back in vi. For example try: :! ls - this will list the current directory, or try :! ls ~ - this will list your home directory, or try :! ls -l - this will give a long listing :shell - (or :sh for short) this will temporarily suspend (freeze) and "exit" vi and will start up a shell (not necessarily a bourne shell - it depends on your vi settings which shell is started up). You can then execute shell commands to your hearts content, BUT when you are done using that shell (say to check your mail) you MUST type "exit" which will quit that shell and return you back to vi. Be careful that you haven't modified the file you were (and now are) editing. !! - this is not necessarily a lastline mode command (it is actually a command mode command) because it doesn't begin with a : but it is relevant to discuss here. Note: when you press ! the first time is seems like nothing happens - be careful because (for various reasons) vi is waiting for you to press ! a second time - then you are placed down in the lastline "area" and you can type one Unix shell command - this time vi will execute that command and place the results of it into the current buffer replacing the line the cursor is currently on with the all of the output the Unix command generates. WARNING - vi will delete the current line when you do this. ------------------------------ COMMAND MODE related commands: ------------------------------ Note: most keys you press while in command mode will either act immediately as a command or will begin a command sequence which when complete will perform some command. This is the "mysteriousness" behind vi - sometimes you press a key (while in command mode) and nothing visually appears to happen - vi is just waiting for you to finish the command key sequence before it performs some action. Movement command keys: ---------------------- All of the "movement" commands will potentially move the cursor to some new position and vi will remain in command mode. the arrow keys - usually the arrow keys work (but not always due to some keyboard character mappings not being performed correctly) h - pressing the h key will move the cursor left on space - it can not move beyond the beginning of the line (meaning it won't wrap up to the end of the previous line). j - pressing the j key will move the cursor down one line. k - move up one line. l - move right one space (can not move beyond the end of the line). Notice that on the keyboard h,j,k,l are all under your right hand (assuming you have taken a standard typing course and have your hands positioned correctly). Thus it is much easier to use these keys to move around instead of the arrow keys. Also you might say that l,d,u,r (left,down,up,right) might be easier to remember, but they are "harder" to find (for your fingers) on the keyboard. w - moves to the beginning of the NEXT word (this will move to the next line if the cursor is on the last word of the current line). W - moves to the beginning of the next whitespace delimited word (try both versions to see the difference - pay attention to where the cursor moves). b - moves to the beginning of the PREVIOUS word (or current word if it isn't at the beginning of it already). B - moves back to the beginning of the previous whitespace delimited word. e - moves to the end of the current word (or the end of the next word if it is already on the end of the current word). E - moves to end of current whitespace delimited word. ) - moves to the beginning of the next "sentence" (where the end of a sentence is either the next blank line or the next period followed by 2+ spaces or a newline). ( - moves to beginning of previous sentence. } - moves to the beginning of the next "paragraph" (where paragraph is the next blank line containing 0 characters and only the \n). { - moves to beginning of previous paragraph. [ - pressed twice this will move the cursor to the beginning of the buffer. ] - pressed twice will move to the end of the buffer. G - will move to the end of the buffer. 0 - (the number zero) moves to the beginning of the current line. ^ - moves to the first non-whitespace character of current line. $ - moves to the last character of the current line. - - try it. + - try it. H - moves to the top of the currently visible screen. L - moves to the bottom of the screen. ^D - (control d) moves the screen (and possibly cursor) down 1/2 a screen. ^U - (control u) moves the screen up 1/2 a screen. ^B - back (up) 1 full screen. ^F - forward (down) 1 full screen. ^G - USEFUL - doesn't move the cursor, but it displays down in the status line the current position (line number) of the cursor (along with other information). Deletion command keys: ---------------------- All of the "deletion" commands will potentially delete some characters based on the current position of the cursor and vi will remain in command mode. x - deletes the single character currently under the cursor. d - (delete _____) has no immediate effect BUT the if the next character you type is: w - (so dw) will delete all characters from the cursor to the beginning of the next word. W - (dW) same as dw but will delete up to beginning of the next whitespace word. e - (de) deletes up to the end of the current word (not the beginning of the next word). E - (dE) self explanatory. b - (db) self explanatory. B - (dB) self explanatory. ),(,},{,H,L,^,$ - all self explanatory (d( or d) or dH or ...). most other characters will have no effect, but a few others might. dd - deletes the entire line which the cursor is currently on and moves every line below it up one. D - deletes from the cursor to the end of the line. X - deletes the character just before the cursor (like backspace). J - deletes the end of line (newline) character (at the end of the current line). The result of this is that the line below the one which the cursor is on is "joined" to the current line (appended onto the end of it). . - repeats the last deletion (or replacement, or insertion) operation performed (at the spot where the cursor currently is). u - will undo the one last deletion (or replacement, or insertion) operation performed. If pressed a second time it will "redo" the last deletetion (replacement, insertion) performed. Replacement command keys: ------------------------- All of the "replacement" commands will overwrite one or more characters in the buffer based upon the current position of the cursor and vi may temporarily go into INPUT MODE but when finished (by pressing escape) will return back to command mode. r - has no immediate effect BUT the very next character you type will replace the one currently under the cursor (and vi will automatically go back into command mode). R - this will put vi into INPUT MODE and until you *press escape* (to get back into command mode) every character you type will replace the character currently under the cursor and the cursor will then move to the next character on the line. One could consider calling this "REPLACEMENT MODE". c - (change _____) has no immediate effect BUT the if the next character you type is: w - (so cw) will put vi into INPUT MODE and will replace all characters from the cursor to the end of the current word with whatever is typed up until *escape is pressed* (at which time vi goes back into command mode). W - (cW) same as cw but changes from the cursor to the end of the whitespace word. e,E - identical to cw and cW respectively. b,B,(,),{,},H,L,^,$ - all self explanatory (cb or cB or ...). cc - similar to dd (but replacing instead of just deleting). Multiplying commands: --------------------- Almost all of the commands above (and others in vi) can be "multiplied" to occur N times rather than once. For example if you want to delete 10 lines you could press dd ten times (or d 20 times) - but using a "multiplier" you press/type the number 20 then dd and it (vi) will perform dd 20 times. The general format for using a multiplier is to type a positive number followed by a command: and vi will perform the command that many times. Some examples are: 5j - moves down 5 lines 3x - deletes 3 characters 8dw - deletes 8 words (d8w also works) 10cw - changes the next 10 words with whatever you type in (same as c10w). Remember - not all commands can be multiplied but a lot can. Insertion command keys: ----------------------- All of the "insertion" commands will not delete any characters already in the buffer, but rather will move the cursor to a specific position and put vi into INPUT MODE allowing you to enter text into the buffer. When finished inserting text *press escape* to get back into command mode. i - pressing i (while in command mode) will put vi into insert mode where the cursor is currently at and any text you type will be inserted between the character that used to be right before the cursor and the character right "under" the cursor. Pressing escape will put you back into command mode (leaving any text you typed in the buffer). a - very similar to i but will insert text after the character which is right "under" the cursor when a is pressed. Pressing escape will put you back into command mode. I - moves the cursor to the beginning of the current line and starts the insertion there. Press escape when done. A - moves the cursor to the end of line and begins insertion there (similar to pressing $ and then a). o - (the letter oh) will "open" up a new line BELOW the one that the cursor is currently on and puts you into insert mode on that line (where you can enter text). Press escape when done. O - (capital oh) will "open" up a new line ABOVE the current one. Pasting (and related) command keys: ----------------------------------- Every time you perform a delete operation (see "Deletion command keys" above) vi stores the one "item" (character, word, line, etc.) into a "hidden" buffer which can hold only one "item" at a time. p - will "paste" the item in the "hidden" buffer (if one is in there) into the current buffer immediately AFTER the character the cursor is on (or the line after the line that the cursor is on - if the item in the buffer contains one or more newline characters). P - similar to little p but will "paste" the item in the "hidden" buffer immediately BEFORE the character the cursor is currently on (or the line before the line the cursor is on). Yanking command keys: --------------------- By default any of the "yanking" commands place items into the "hidden" buffer. y - works exactly like d (see deletion command keys) but it does not delete the item, but rather "yanks" a copy of it (the thing that would have been deleted) and puts that copy into the "hidden" buffer. For example: y - (yank _____) has no immediate effect BUT the if the next character you type is: w - (yw) will copy (yank) from the cursor to the beginning of the next word and will place that copy in the "hidden" buffer (so the next p (paste) will use that item last "yanked"). W - (yW) same as yw but yanks from the cursor to the beginning of the next whitespace word. e,E - (ye and yE) will yank from the cursor to the end of the current word (but may not yank the last character of the word). b,B,(,),{,},H,L,^,$ - all self explanatory (yb or y} or ...). yy - yank the current line. Named buffers: -------------- Sometimes you want to "yank" several different items and then paste them at a later time - unfortunately the "hidden" (general purpose) buffer can only store one item at a time. Thus there are 26 extra "named buffers which you can use. The name of each buffer is "a, "b, "c, "d, "e, ... "x, "y, "z respectively (for a total of 26). To use a named buffer (in command mode) you type the name of the buffer first and then the command you want to execute. If the command you type is a deletion or yanking command the result of that delete or yank will be placed INTO the named buffer (and the "hidden" buffer). If the command you type (after the named buffer) is a paste command it will paste using the contents FROM the named buffer. Some examples are as follows: "zdd - deletes the current line and puts a copy of it in the "z buffer (and the general purpose buffer). "myy - yanks the current line into the "m buffer (and general purpose). "ky} - yanks from the cursor to the end of the paragraph and places it into the "k buffer. "kdw - deletes the word and puts a copy of it in the "k buffer (anything that used to be in the buffer is removed because each buffer can store at most one "item"). "kp - will paste the contents of the "k buffer after the character the cursor is currently on. "mP - will paste the contents of the "m buffer before the cursor. Note: if you have items in the named (and general purpose) buffers and you :edit a different file (without leaving vi) then the contents of the named (and general purpose) buffers will still be there. Searching command keys: ----------------------- vi uses regular expressions (actually something similar to regular expressions) to allow you to search for words or patterns within the current buffer. /string - will search forward to find the next occurence of string and will move the cursor to be at the start of the next occurence of that string (if the end of file is encountered it will continue searching from the top of the file). ?string - will search backward (up) to find the next occurence of string. n - pressing n will repeat the last search you performed (to find the "next" occurence of the item you are searching for). N - repeats the last search but in the opposite direction. / - by itself will perform the last search in the forward direction. ? - similar to / by itself but in the backward direction. Common usage: search for "foo", replace foo with "bar" (cw), and repeat by pressing n and then . then n then . then n then ... The following characters have special meaning when searching: ^ - means beginning of line $ - means end of line . - means any one character [ ] - means any one character from within the list of characters found between the "square brackets". [^ ] - means any one character that is NOT in the list of characters found between the "square brackets (with the ^ at the beginning)". * - means match the one character (or item) before it 0 or more times \{n,m\} - means match the prior character (or item) n to m times (where n and m are positive integers and n is < m). You can leave off m (ie \{4,\}) and it will match n or more times. \< - means beginning of a "word" (note: by itself < has no special meaning) \> - means end of a "word" / - has some sort of special meaning (I think) If you want to search for one of these "special" characters you need to "escape" it using \ for example \^ will find the next occurence of ^ in the file (buffer). Substitution (or searching and replacing): ------------------------------------------ You can perform the manual - one by one - search and replace using the search commands listed above. The following permits you to perform this on the whole file at once (or portions of the file). To perform search and replace (aka substitution) you use a LASTLINE command: :s/searchstring/replacestring/ - will search for the first occurence of the "searchstring" on the current line and will replace it with the "replacestring". The search string can be similar to the / and ? search strings and can use those special characters. :s/srchstr/rplstr/g - same as the prior one but will replace *all* occurences of "srchstr" that occur on the current line with "rplstr" (sorta a "global" mode of the substitution command). Using "addressing" you can search and replace on the whole file (buffer) or a portion thereof: :[address]s/srchstr/rplstr[/g] - where [address] is replace by a valid address - it will search and perform substitutions on all the lines that the address refers to. Note: without the /g at the end it will only replace the first occurence of "srchstr" on each line - with the /g it will replace all occurences of "srchstr" on each line. A valid [address] can be of the form: - where is an integer and represents a line number, for example: 50 - means line 50, so: :50s/hello/hi will go to line 50 and replace the first occurence of hello with hi , - where and are two integers representing the line number to start on and the line number to end on. An example is: 10,50 - lines 10 through 50 . - represents the current line. For example: .,50 - current line to line 50 1,. - line 1 through the current line .,.+10 - ("relative") the current line through the current line plus 10 (11 lines total). .-5,. - 5 lines prior to the current through the current line (6 lines total). $ - represents the last line in the buffer. For example: .,$ - current line through (and including) the last line of the buffer. Remember pressing control-g (^G) will tell you what line you are currently on. You can use "addressing" with the :w command(s) to selectively save only those lines refered to by the address. For example: :.,$ w! newfile.txt - will save all lines from the current one to the end of the buffer into the file "newfile.txt" Marking the buffer: ------------------- vi permits you to insert up to 26 hidden "markers" in the current buffer - note this is NOT the same as the 26 "named buffers" (those are completely different from this). To place a marker in the buffer just press the m key and then the name of the marker (a-z) that you want to place and vi will put that marker at the beginning of the current line. For example: ma - places the marker a on the current line. mf - places the marker f on the current line (and removes it from any other line it may have been on). To move back to a line that you placed the marker on do the following: :'a - moves the cursor the the beginning of the line with the a marker on it (note the is a lastline command). Note that to place a marker you just press m then the letter of the marker, but the actual name of the marker is preceeded by a ' (so the markers names are 'a, 'b, 'c, ..., 'x, 'y, 'z respectively). They are *not* named "a, "b, ... (the pasting buffers are named that). You can also use the markers when using addressing. For example: :.,'as/hello/hi/g - will look from the current line down to the line with the 'a marker on it (if this line is above the current one an error will be generated) and will substitute (s) all occurences of hello with hi. A more advanced use of markers is to "yank" a section of text into a named buffer: "ay'd - will Yank all of the text from the current position up (or down) to the marker 'd and put it into the named buffer "a An even more advanced use of markers is to "magically" yank a section of text and "redirect" it as input to a Unix command and then have the results (of the Unix command) placed back into the buffer *in place of* the lines that were "yanked": !'dsort - (note only one !) - will remove all lines from the line the cursor is on down (or up) to the line the marker ('d) is on and send (redirect) those lines (as input) to the Unix command (sort in this example) and the result of the Unix command will be placed back into the current buffer where the lines removed used to be. Configuring the vi "environment": --------------------------------- You can modify the way that vi "behaves" by setting or unsetting certain options. For example you can have vi display the line numbers in the current buffer, or change the shell that vi uses when you execute the :sh command, or have vi "wraparound" when searching or have vi not wraparound when searching or many other things. To see the current settings (when in vi) type: :set all and then press escape (or any key when done). more to come. Other ways to start up vi: -------------------------- Another way you can start vi is by typing "view " or "vi -R " and this will start up a "readonly" session of vi - which will not allow you to save any changes made to the file. One other way to start up vi is to type "vi -r " - this is useful when you are editing a file (using vi) and your computer crashes or internet connection goes down you might be able to "recover" the file even if you hadn't saved it. vi will determine if a recoverable version of the file exists and if so will open it up - if not it will open up an empty file (be careful not to save this empty file as it may overwrite your real file). If you just type "vi" at the Unix prompt it will start up vi with an empty buffer associated to no file. If you want to save any text you type into the buffer you need to use ":w " or some similar command.