" Smith) (01/22/88)
Here it is... I will follow up in a few weeks or so, some of this material needs to be explained better, but I did want to get this out now. dan # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by ceylon!daniel on Thu Jan 21 08:22:47 PST 1988 # Contents: README vicoms.doc macros.doc sample_exrc echo x - README sed 's/^@//' > "README" <<'@//E*O*F README//' Wow. Enough mail reached me to justify posting this. This is a shar of a vi summary and a short tutorial on writing macros. I have also included a sample .exrc file that I use for programming. Thank Yous: I owe thanks to a couple of people who recently posted vi info to the net. A good summary came from: (very well laid out) maart@cs.vu.nl (Maarten Litmaath) VU Informatica, Amsterdam A macro package with lots of files also was helpful. Thanks also to: Greg McGary -- gmcgary@ecd.sun.com gmcgary@suneast.uu.net For developing mkid, gid, aid, eid, and co. My macros allow you to quickly use the ID database that mkid generates. Forward: It's amazing how much power there is in vi, once you get past the initial learning bunny slope :-) There are many complete summaries out there, but fewer sources of info about macros. I'd like to help change that... I'll update this soon, but want to post what I have now. dan dan smith, island graphics, marin co., ca | "My opinions: you can borrow them, uucp: ..!ucbvax!ucbcad!island!daniel | but don't take them out bowling" uucp: ..!ptsfa!unicom!daniel !well!daniels | (415) 332 FAST (h) 491 1000 (w) @//E*O*F README// chmod u=rw,g=r,o=r README echo x - vicoms.doc sed 's/^@//' > "vicoms.doc" <<'@//E*O*F vicoms.doc//' commands for the editor VI command mode (hit escape (ESC)) cursor positioning h left j down + down l right k up - up <space> right <return>down one line H home line (top of window, not necessarily file) M middle line of window L last line of window b back a word B back a word (real words, punctuation doesn't count) w next word W next word (real words, punctuation doesn't count) 3w skip three words 0 beginning of line $ end of line ^ (caret character)...first non-blank character on the line. { previous paragraph, section } next paragraph, section ^D scroll half screen down note: (use control key when you ^F screen down see '^' and a letter, and ^U scroll half screen up press both at the same time, you do not ^B screen up press the shift key) ('x' means type x) 1G top of file (any number)G...go to (any line) of file -- ex: 5g goes to line 5 G end of file '' (two single quotes)...return to previous line or mark (long distance) `` (two back quotes)..return to same place in a line " " t forward to just before a character T backward to just after a character These are handy for things such as: dto (delete all of the characters on this line up to (but not including) the letter 'o') ^G what line am I on? shows file, status, line number, total lines, % searches /text search for "text" hit 'n' for next occcurence hit 'N' for previous occcurence ?text ?text search backwards for "text" ? by itself, change from forwards <-> backwards search local searches (usually used on same line as you are on) fx search forwards for the next letter "x"..use a semicolon ";" or "," to keep searching (the "," reverses direction of search) Fx search backwards for the next letter "x"..use a semicolon ";" "," to keep searching (the "," reverses direction of search) undo u is undo, and you can undo an undo... U is "undo everything that I have done to this line since I have landed on it..." marking and returning m(any alpha character) mark a place '(any alpha character) return to a place (line) `(any alpha character) return to a place exactly (see below) hit "ma" to set up a mark with the letter "a" to get back...'a 'a takes you back to the first non-blank space on that line, while `a takes you to that character exactly marks can be used to specify the scope of a change...such as d'a or >'a more on that later... buffers... all changes are saved into a buffer, and are retrieved with an undo (u or U) or a put (p or P) y, c, and d are for yank, change, and delete, and are operators yy, cc, and dd affect entire lines w, b, 0, $, {, }, are how you determine the extent (scope) of a change, as well as any motion operator such as H, M, L, etc. / and ? are used for searches, and can be used to delete, yank, or change up to the phrase you specify. example: d/would<return> deletes up to (but not including) the next occurrence of the word "would". If you want to make it line specific (go to the line of the word "would") you would use d/would/+0<return> (d/dog/+10 would delete up to the line with "dog", plus the 10 lines that follow) changes or copies are set up by [optional number][operator][scope] such as 2d}...which would delete the next two paragraphs examples: x delete character xp transpose characters ddp transpose lines yy yank line 15yy yank 15 lines yM yank from here to the middle line of window yw yank word to end yb yank word to beginning y0 yank to beginning of line ...all yanks and x's go into buffer 1 y$ yank to end of line p put buffer on line below P put buffer on line above cc change line cw change word 3dw delete 3 words (goes into the temporary buffer) dd delete line " " " " 5dd delete 5 lines " " " " dH delete from here to the top line of the window (top of screen) dL delete from here to the bottom line of the window (bottom of screen) 3yy yank three lines " " " numbered and named buffers The last 9 changes you have made are saved in the buffers named 1-9. For example, you would retrieve the change before last by entering "2p (use the quote) to dump out whatever is in buffer 2. As a special case, you can repeatedly press the dot key '.' and dump out all the buffers until you run out of saves or get to buffer 9, whichever happens first. example: "1p........ would dump all of the last 9 deletions that you have made. alpha named buffers setting up.."[alpha named buffer][optional number][delete or yank operation] example..."add delete a line INTO buffer "a" "b5yy yank 5 lines INTO buffer "b" using the buffer..."[name you gave the buffer][p or P] example..."ap put contents of buffer "a" below appending to a buffer... you can gather text from many locations into one named buffer, just capitalize the name of the buffer: "Ayy ...now, move somewhere else, then... "Ayy ...move somewhere else, and try: "ap you should see the lines from the two different locations. When using named buffers, choose letters that have some mnemonic value to you. If I were yanking the line "The quick young dolphin jumped over the lazy bagpipes", I would probably use "nyy - the 'n' for "nonsense". Named buffers and numbered buffers are quick ways to transfer text between files if you are switching back and forth between two or more. (unmap the home key via :unmap ^^ (home key or control caret), and you can toggle between two files by hitting the home key. This would be the last thing in your .exrc) example: moving text between two files... have the home key unmapped (in .exrc "unmap ^^" (type ^V<home key> or ^V<control caret> while editing .exrc... you should see "^^")... go into a scratch file...start up another file (:e fooby)... notice that you can toggle between the two files by typing the home key (usually if a terminal doesn't have one, control caret (a shifted '6' for most terminals) will do it)... toggle between the two files a few times to get familiar with it... go to one of the files, and delete a few lines into a buffer via: "a3dd ...then toggle into the other file, and enter: "ap If all went well, you have just transferred lines from one file to another. The same works for yanks ("a3yy). I found out only recently that using the buffers 1-9 works too: 3dd, toggle with home key, then "1p I find it handy to mark a place very quickly via mm (mark this spot, to be referenced by 'm), go to another place, and to use a named buffer via: "ay'm (yank into buffer 'a' whatever is between here and the mark 'm') quick changes r replace single character R replace mode...type over old text and clobber it 2s substitute whatever I type (until I hit ESC) for the next two characters xs I'm going to change the next "x" characters, you may type more than "x" characters in your substitution. S is synonomous with "cc"...change effects an entire line. tilde '~' change case of current char. >> shift current line over right by a shiftwidth (usually a tab) << shift current line over left by a shiftwidth (usually a tab) >L would shift all of the lines from where you are to the bottom of the screen to the right... 50<< left shifts 50 lines... getting into text input mode a append A append at the end of line i insert I insert at first non blank character of line o open line below O open line above Using things like s, S, cc, C, etc... are also ways of getting into text input mode. ^D backtab (insert mode only) ^V follow it with a control combination to insert a control char. into text ESC hit to get back into command mode file manipulations and others...all from command mode :w write file :wq write file and quit ZZ another way to write file and quit :e filename edit file :e! filename insist on editing file, a way to start with a fresh copy of the current file name, WITHOUT any of the changes that you may have just made. :r read in a file after the current line (merge) :q quit :q! really quit! don't save changes! :w! overwrite a protected file :n edit next file in arg list (:se ar gives the list of files) :rew rewind back to first file :!<shell command> you don't have to leave vi to do something like finding out the date or compiling a program. The second time you do the same command, you can say ":!!" to repeat that command. :1,$!fmt..pipe the text through the formatting program "fmt", if you don't like what you see, hit 'u' for undo... this works for many commands, you can do something like :40,50!nroff -ms to see how lines 40 through 50 will format with the program "nroff" using the "ms" macro package. You could also do something like :'a,'b!nroff -ms if you have a mark 'a' and a mark 'b'. (first address must be lower than the second as far as which line it refers to in the buffer) :%!fmt....A shorthand for doing the same thing as above. If '%" is being used as an address, then it means "the whole file", otherwise it expands to be the filename of the current buffer... try: :!wc % now try: (read below first...) :%!wc (*here*) remember...'u' is undo, and 'U' is "undo everything that I have done to this line since I have landed on it..." !! two exclamations given from command mode. You follow this with a unix command that has some output, and the output is inserted into your text, clobbering the current line. You should set up a blank line before calling this mechanism. See below for a different way of doing this. ex: open a blank line, then hit escape, then enter "!!date" Actually, if you want to read the output of a command into the file, :r !command works (it runs the command and puts the output into your buffer). There is also the opposite, :w !command, which sends the buffer as input for the command (useful for :w !more, or something like that). notes "^" and a letter and means to use and the control key...ex: ^D means "control d" I haven't mentioned a lot, and this file needs to be better organized and more comprehensive, on the other hand, this should keep a beginner->intermediate level VI user going for a little while :-) mail comments to "island!daniel", special thanks to David Vezie (dv) for clarification and spotting gremlins. dan smith, island graphics, marin co., ca | "My opinions: you can borrow them, uucp: ..!ucbvax!ucbcad!island!daniel | but don't take them out bowling" uucp: ..!ptsfa!unicom!daniel !well!daniels | (415) 332 FAST (h) 491 1000 (w) @//E*O*F vicoms.doc// chmod u=rw,g=rx,o=rx vicoms.doc echo x - macros.doc sed 's/^@//' > "macros.doc" <<'@//E*O*F macros.doc//' Part 2 of a series: more commands for the VI editor Part two: macros and abbreviations Macros and abbreviations are ways for you to customize vi to suit your way of doing things, as opposed to you having to change your editing habits to accomodate vi. There are two types of macros, those that work in the input mode, and those that work from the command mode. Abbreviations only work in the input mode. Where to use macros: I use macros for things that I like to do frequently, where the existing key sequence for getting something done gets to be too tedious. If you are in vi right now, hit the colon key, and type in "map", like this: :map After hitting return, you'll see the macros that you currently have access to in the command mode. You should at least see four, one each for up, down, left, and right. Let's make a simple one to add to this list...you type in the colon to get the ex prompt ":" :map g ^G <--- that's a "control G" When you've hit return, you'll have created a new definition for the "g" key. Go ahead and hit the g key a couple times, move the cursor a couple of lines, and try the g key again. You've made it so that you don't have to hit control g to get this result anymore, which is a slight improvement. Let's try a more useful example: :map @m :w^M:!more %^M This can be slightly confusing at first to try to type in, so I'll explain the business about the control M. When you are in vi, and want to represent a control character, instead of performing the action that it would usually do, you preceed that character with a control V (think of it as control V for "view", as in "view the next character"). Thus, the preceeding example becomes "colon, w, control V, return (which prints the ^M character), colon, ! (meaning: we're going to run a unix command from vi), more, % (which is vi's way of saying "the current file"), another ^M (same sequence (control V return) as before). Now, what does this all do? First, I used "@m" to define the keys that I will hit for my macro. On the adm5 terminals I learned unix on, it is very convenient to hit "@" and then "m" very quickly. Now that I use a Wyse 50, I find the '[' and ']' characters very handy for defining macros - this is an issue best suited for the user to figure out what is comfortable. The rhs (right hand side of the macro) says "write the file by ":w^M", and then do another command by hitting the ":", Hit the "!" to show that we're doing a unix command, and run the current file that we have in vi (represented by vi as "%") through "more" by saying ":!more %^M"" Now let's do a fun one. :map ^> I ^[^ This one is typed as: control V, control greater than, space, I, space, control V, escape, and then a caret (^), return it appears as: :map ^N I ^[^ and that is perfectly ok. Try this one out now, while you have it on the screen in front of you, if you goof somehow, you can hit ^C (for now on, a "^" in front of a letter most often means it is a control key combination) to get out. This last macro shoves a whole line over to the right by inserting a space in front of it, and leaves the cursor on the first non-blank character on the line. I chose ^> because to me it symbolizes the direction that I am trying to move something, and it is also a close relative of ">>", which shifts a line over by a tab. This macro has the counterpart: :map ^< ^X and appears as :map ^L ^X <--- not a control x which is typed as (left hand side) control V, control less than, and the rhs (right hand side) is not a control X, even though it appears as such. It is a caret, and then a capital X. This macro shoves the whole line to the left by one space (or tab if there is one in the text) until it can't anymore. I will come back to macros for temporary use. saving macros...the .exrc file It's nice to be able to play around with macros for now, but it would be even better to have them ready to go everytime you want to use vi for something. Fortunately, there is such a mechanism, and it involves a file called .exrc that is in every directory where you want to have vi set up a certain way. Look at an .exrc file by using the public domaing pager "less", or by view'ing it (view .exrc (view is vi without the ability to write back changes). You should have a .exrc file in every directory where you'll be using vi with any consistent set of macros that you develop. Vi reads the file upon starting up, but you can also "source" a file while you are already in vi by saying: :so .exrc After that, you can take a look at the present macros by entering ":map". Macros in input mode The macros I just discussed all work in the command mode, a couple of them enter the input mode to do something, and then hit escape by them- selves to keep you in the command mode. There is another flavor of macros, and these are called "input macros". They work the same way as command mode macros, but they can be invoked as you are typing along. A sample one could be: :map! ^W ^]:w^Mi Which would write out the file as you are going along, with a small pause...it is typed as ^V, escape, :w, ^V, return, i. There are many more macros that could be done in this mode, but you need to avoid ^S...it will make the terminal appear to freeze, when in fact it is just waiting for you to hit ^Q in order to resume (you use this combination to look through a long file that is being catted. A strong point in favor of using input macros is that they can consist of many characters. Let's say that you are a C, Fortran, Pascal, or Logo user, and you want some sort of way to speed up writing statements that print out a phrase. If we are dealing with pascal, we could do this: :map! @wr writeln ('');^[hhi in C: :map! @pf print ("");^[hhi in Fortran :map! @wr write (6,)'^[hi and so on... I think you get the idea. A more advanced use is to place some text in a buffer (a la: "ayy), and then have that buffer copied out from within a macro, making for a different result from the macro every time. Let's say I copy this next sentence with "nyy the time has come for all good men to tie their shoes. and let's assume we have the following macro (I'll use the command mode form here): :map @w "npOprintf ("^[JxA");^[^ this results in: printf ("the time has come for all good men to tie their shoes."); The macro comes out different every time, depending on what you put into buffer n. Before I take a break from macros, let me share some things that I've found: There is a limit to how many macros you can define, depending on the total amount of characters that exist in all of your macros put together. I find that 1024 characters total for all macros is a common limit. I changed a local copy of vi to handle 4096... not that I am using that many yet, but I like to be flexible :-) Macros can be recursive, and can also call other macros. This can be fun, and confusing. Try to write macros that you are really going to use, if they look impressive, but you never use them because you can't remember them, it takes that much more time every time you start up vi to set something up that is going to waste. If you want to get into a whole series of commands, have a macro source a file...the file can consist of unix and vi commands, and can even define and undefine macros as you go! To undefine a macro, you say :unm <macro name>, or for an input mode macro, you would say :unm! <macro name> Abbreviations Abbreviations are much easier to understand than macros. Here is a simple one: :ab HT hi there! Once this is set up, you type in "HT", and then hit the space bar, return key, a "*", " " " (quote), or one of many other keys. They transform what you have just typed into what you want them to become. I will warn you, but you may still run into this problem someday: Don't make an abbreviation that is easy to confuse with something you want to type normally! It can take a few seconds of watching an abbreviation appear, get deleted by you, and have it reappear before you figure out a way around it. You need to experience the annoyance this can cause to fully appreciate what I'm saying! It will seem that this word or phrase will not want to go away! In other words, use groupings such as "wrn" for "writeln", or "prc" for procedure. You will soon discover what you are most comfortable with. Another thing about abbreviations is that they leave a space just after they transform themselves, such as: :ab wrn writeln (' which is mildly annoying. A last example is that abbreviations can do something that is very routine, such as: :ab wneof while not eof do^M begin^M There is a final space after the second return, and the output is: while not eof do begin (cursor) with the cursor resting where the next statement should go. I'll post a file soon that goes into more detail. For now, I've included a uuencoded sample of my .exrc. To use it: touch .sample (these two lines are neceesary if you chmod 666 .sample are working with a stubborn version of uudecode) uudecode sample_exrc (go into vi) :so .sample Note that the character " is a comment line... do not have lines in your .exrc that are blank. This wraps up an introduction to macros and abbreviations, please mail all questions, comments, complaints, and so forth to: dan smith, island graphics, marin co., ca | "My opinions: you can borrow them, uucp: ..!ucbvax!ucbcad!island!daniel | but don't take them out bowling" uucp: ..!ptsfa!unicom!daniel !well!daniels | (415) 332 FAST (h) 491 1000 (w) @//E*O*F macros.doc// chmod u=rw,g=r,o=r macros.doc echo x - sample_exrc sed 's/^@//' > "sample_exrc" <<'@//E*O*F sample_exrc//' begin 666 .sample M;6%P(%MA(#IA<@T*(@HB"7-E87)C:"!F;W(@=&AE(&YE>'0@;V-C=7)E;F-E M(&]F('1H92!P871T97)N(&-U<G-O<B!I<R!R97-T:6YG(&]N"FUA<"!=+R!D M95!O&VDO&W B>F1D0'H*(@HB"6=R97 @9F]R(&%L;"!O8V-U<F5N8V5S(&]F M('1H92!P871T97)N(&-U<G-O<B!I<R!R97-T:6YG"B();VX@:6X@=&AI<R!F M:6QE+BXN"FUA<"!;+R!M>F1E4&\;:3HA9W)E<" M;B ;<&$@)2 6?" O=7-R M+VQO8V%L+V)I;B]L97-S&R)Z9&1 >F!Z"B(*(@D@=&%K92!T:&4@;F5X="!W M;W)D(&%N9"!U<V4@:70@87,@:6YP=70@=&\@86ED("AA<')O<&]S(&ED*2XN M+@IM87 @76$@;7IE8F1E4$\;:3HA86ED(!MP82 6?" O=7-R+VQO8V%L+V)I M;B]L97-S&R)Z9&1 >F!Z"B(*(@ET86ME('1H92!N97AT('=O<F0@86YD('5S M92!I="!A<R!I;G!U="!T;R!E:60N+BX*;6%P(%UE(&5B9&503QMI.B%E:60@ M&W B>F1D0'H*(@HB"2!T86ME('1H92!N97AT('=O<F0@86YD('5S92!I="!A M<R!I;G!U="!T;R!G:60@*&=R97 @:60I+BXN"FUA<"!=9R!M>F5B9&503QMI M.B%G:60@&W!A(!9\("]U<W(O;&]C86PO8FEN+VQE<W,;(GID9$!Z8'H*(@HB M"6=E="!A('-A=F5D('-C<F5E;B!F<F]M('-O;64@<')O8V5S<R!R=6X@8GD@ M(G-C<F5E;B(*;6%P(%US(#IR("]U<W(R+W!E;W!L92]D86YI96PO=&5X="]S M8W)E96YS+VAA<F1C;W!Y+@IM87 @76,@;6TG8SHN+"=M('<A("]U<W(R+W!E M;W!L92]D86YI96PO<W)C+RYC=70-"FUA<"!=;B Z;@T*;6%P(%UP(#IR("]U M<W(R+W!E;W!L92]D86YI96PO<W)C+RYC=70-"FUA<"!;<" Z<&]P#0IM87 @ M77$@.G$-"FUA<"!==" Z=&$@"FUA<"!==R Z=PT*(@HB"7=R:71E(&$@8F%C M:W5P(&9I;&4N+BX*;6%P(%MW(#IW(2 E+F)A:PT*(@HB"6-O;6UE;G0@82!L M:6YE"FUA<"!=*B!/+RH;:F\J+QL*(@HB"75N8V]M;65N="!A(&QI;F4*;6%P M(%LJ(&MD9&ID9 IM87 @%R Z=PT>"FUA<"! <R Z<V5T('-H96QL/2]B:6XO M8W-H#0IM87 @0$!S(#IS970@<VAE;&P]+V)I;B]S: T*=6YM87 @'@IS92!R (97!O<G0],0H@ end @//E*O*F sample_exrc// chmod u=rw,g=r,o=r sample_exrc echo getting .sample file... touch .sample chmod 777 .sample uudecode sample_exrc chmod 644 .sample exit 0