home *** CD-ROM | disk | FTP | other *** search
/ Nebula / nebula.bin / Documents / Others / viCourse+ / vi-macros.txt < prev    next >
Internet Message Format  |  1992-12-20  |  35KB

  1. From s220@brems.ii.uib.no Fri Mar  8 18:59:05 1991
  2. Received: from eik.ii.uib.no by viggo.blh.no ; Fri, 8 Mar 91 18:58:59 +0100
  3. Date: Fri, 8 Mar 91 18:47:18 +0100
  4. From: s220@brems.ii.uib.no
  5. Message-Id: <9103081754.AA01593@flue>
  6. To: rubenro@viggo.blh.no
  7. Status: OR
  8.  
  9. @ F TR 12
  10. Vi Macros, Abbreviations, and Buffers
  11. Copyright (C) 1988 by Fred Buck; all rights reserved.
  12. Additions: 1989 Maarten Litmaath <maart@cs.vu.nl>
  13. Thanks to: Jean-Pierre Radley <jpradley!root@uunet.uu.net>
  14.  
  15. Heading summary:
  16. =================
  17.  
  18.    Introduction
  19.    
  20.    Non-macro stuff you really should know about when writing macros
  21.    
  22.        Text markers
  23.        Text buffers
  24.        The escape filter
  25.    
  26.    Simple description of the various 'vi' macro mechanisms
  27.    
  28.        Text abbreviation
  29.        Keystroke remapping: text mode ("map!")
  30.        Keystroke remapping: command mode ("map")
  31.        Text-buffer execution
  32.    
  33.    More detail about 'vi' macro operation
  34.    
  35.        Mode-bouncing
  36.        Chained macros
  37.        Recursive macros
  38.        Terminating a recursive macro
  39.    
  40.    Peculiar limitations and restrictions on 'vi' macros
  41.    
  42.        Size
  43.        Putting and yanking to/from named buffers
  44.        Which keys to remap?
  45.    
  46.    Conclusion
  47.  
  48. Introduction 
  49. =============
  50.  
  51. 'Vi' offers a variety of "macro" facilities; a "macro" in this context is a
  52. mechanism whereby a small number of keystrokes, usually a single keystroke,
  53. is made to represent another set of keystrokes, so that typing the first set
  54. of keystrokes is equivalent to typing the second set.  Applications for
  55. macros fall into three major classes:
  56.  
  57.         (a) during text entry, allowing a long, often-repeated
  58.     string of text to be represented by a short abbreviation; for
  59.     instance, in your biography of Ramaswamy Gopalikrishnan, you
  60.     might assign "rgn" as a macro for the name of your subject;
  61.  
  62.         (b) existing 'vi' commands can be made invokable by
  63.     keys other than the traditional ones, so that for instance if
  64.     your terminal has function keys, you can remap the sequences
  65.     generated by the function keys to existing 'vi' commands, and
  66.     thereafter use the function keys instead of the standard 'vi'
  67.     command keys;
  68.  
  69.         (c) complex operations that would take many keystrokes,
  70.     or that would take a hard-to-remember sequence of keystrokes,
  71.     can be tied to an easy-to-remember sequence of keystrokes, and
  72.     be executed quickly and easily.
  73.  
  74. If your primary interest lies in category (c), then 'vi' macros should be the
  75. LAST topic you take up when learning about 'vi', because you can't write
  76. macros to accomplish things you couldn't do yourself if you were typing
  77. everything in at the keyboard: your macros are only as good as your overall
  78. skill at using 'vi'.  If you're not familiar with using the named and unnamed
  79. 'vi' text buffers, or with the use of text markers, or with the shell-escape
  80. ("!") filtration mechanism, the next section contains a bare-bones
  81. introduction to these things, but you should really play with them at some
  82. length yourself in order to see their full possibilities.
  83.  
  84.  
  85. Non-macro stuff you really should know about when writing macros
  86. =================================================================
  87.  
  88. The following is only a very cursory summary of some basic 'vi' mechanisms
  89. that are essential to be familiar with when writing complex 'vi' macros.
  90. These summaries are intended to make at least intelligible the discussion
  91. that is to follow them.  If you don't know about these mechanisms, and if
  92. you want to write complex 'vi' macros, you'd be well-advised to seek out
  93. a text on 'vi' read up on these things.
  94.  
  95. Text Markers:
  96. --------------
  97.  
  98. 'Vi' has 26 available text markers, corresponding to the 26 lowercase letters
  99. of the alphabet.  A marker can be emplaced by moving the cursor to the place
  100. you want to mark, and typing "m" followed by the marker name you want to use,
  101. from "a" to "z".  Typing "ma" marks that location with marker "a".  To return
  102. to this location from somewhere else in the text, type "`a", where "`" is a
  103. backquote sign, or grave accent.  The backquote moves the cursor to the
  104. precise location you were at when you emplaced the mark.  If instead you're
  105. satisfied merely to go to the beginning of the line you were on when you
  106. emplaced the mark, type "'a", where "'" is a standard single-quote sign.
  107.  
  108.     A text region can often be defined by a cursor-movement command, and
  109. the single-quote and back-quote commands are cursor-movement commands. 
  110. Placing text markers makes it much more easy to yank text into a buffer.
  111.  
  112. Text buffers:
  113. --------------
  114.  
  115. 'Vi' has a remarkable total of 36 user-reachable text buffers.  26 of these
  116. are static buffers, meaning that they don't change until the user tells them
  117. to change, and these are called the "named" text buffers, with names
  118. corresponding to the 26 letters of the alphabet.  Don't confuse these "named"
  119. buffers with the 26 text-marker names; the two are entirely separate and
  120. independent.  The text markers must always be in lowercase; the text-buffer
  121. names can be either uppercase or lowercase, although whether a text-buffer
  122. name is in uppercase or in lowercase changes the way text gets loaded into
  123. the buffer.
  124.  
  125.     To put text into a named buffer, type a double-quotation mark, then
  126. the name of the buffer, and then a cursor-movement command, like this:
  127.  
  128.         "ay`b
  129.  
  130. which yanks into named text buffer "a" the text between your current cursor
  131. position and the exact location of text marker "b", which we assume you've
  132. previously set.  The "yank" will end JUST BEFORE the exact location of text
  133. marker "b".  To yank simply an entire line, use "yy" (or "Y") instead of "y"
  134. and the cursor-movement command; to yank N number of lines from your current
  135. cursor position, use 
  136.  
  137.         "aNyy
  138.  
  139. The double-quote mark, '"', is the 'vi' command character that indicates that
  140. you want to manipulate a text buffer.
  141.  
  142.     If you use an uppercase rather than a lowercase letter for the name
  143. of the text buffer, then whatever you yank into the buffer will be appended
  144. to the buffer, rather than over-writing the buffer's previous contents.
  145.  
  146.     To re-insert text from a text buffer, position the cursor where you
  147. want to make the insertion, and type a double-quote sign, then the name of
  148. the buffer (case doesn't matter for re-insertion), and then either "p" or
  149. "P":
  150.  
  151.         "ap
  152.  
  153. If you use a lowercase "p", then the text is re-inserted after your current
  154. cursor position; if you use an uppercase "P", then the text is re-inserted
  155. before your current cursor position.
  156.  
  157.     In addition to the 26 named text buffers, 'vi' stacks deleted text
  158. in a set of 10 volatile buffers, generally called the "unnamed" buffers.  By
  159. "volatile" I mean that the contents of these buffers change without the
  160. user's explicit direction.  Actually, only the first of these volatile,
  161. delete buffers is really "unnamed"; it's the buffer that the most-recently-
  162. deleted text resides in, and from which the bare "p" and "P" commands work.
  163. The other nine delete buffers are reachable with the names "1" through "9".
  164. So if you delete some text in 'vi', the text you've just deleted is in the
  165. "unnamed" delete buffer and can be recovered with "p" or "P".  If, without
  166. recovering that text, you now delete some more text, then the text you
  167. previously deleted is moved to delete buffer "1" and the most-recently-deleted
  168. text is now in the "unnamed" delete buffer.  Keep deleting text, and the text
  169. you deleted the first time will advance from buffer "1" to buffer "2" and so
  170. on, until it gets to buffer "9", and if you delete more text after that,
  171. whatever is in buffer "9" is thrown away, and can no longer be recovered.
  172. Actually it can be recovered if you haven't written the file since you deleted
  173. the text:
  174.         :w temp
  175.         :e!
  176.  
  177. The first command writes the current (modified) contents of the file you're
  178. editing to a temporary file called 'temp', the second command tells 'vi' to
  179. reload the original file WITHOUT saving the modifications you've made.
  180. They are, however, still available in 'temp'.
  181.  
  182.     The syntax for working with the delete buffers is the same as that
  183. for the named buffers: to extract text from, say, delete buffer "1", you'd
  184. say
  185.  
  186.         "1p
  187.  
  188. The "unnamed" delete buffer, in which the most-recently-deleted text is
  189. stored, is recoverable simply by typing a "p" or a "P".
  190.  
  191. The escape filter
  192. ------------------
  193.  
  194. An arbitrary set of text lines can be sent through a Unix or Xenix command
  195. and the result substituted for these lines in place.  This is done within
  196. 'vi' by the command
  197.  
  198.         !<cursor-movement-command><Unix/Xenix command>
  199.  
  200. which has the effect of sending the text lines beginning with the current
  201. line and ending with the line your cursor-movement-command has taken you to. 
  202. If in 'vi' the cursor were placed at the beginning of this paragraph, "An
  203. arbitrary", and then the command
  204.  
  205.         !/has the effect/<RETURN>tr '[a-z]' '[A-Z]<RETURN>
  206.  
  207. were entered, every alphabetic character from the cursor position to the end
  208. of the line containing the string "has the effect" would be forced to
  209. uppercase.  Note that most versions of 'vi' operate only in whole-line
  210. increments when using the shell-escape filter; some versions of 'vi' allow
  211. the shell-escape filter to work on text areas that don't correspond exactly
  212. to line boundaries.
  213.  
  214. Simple description of the various 'vi' macro mechanisms
  215. ========================================================
  216.  
  217.     (1) text abbreviation, which operates only in text-entry mode (the
  218.         "abbr" ex-escape command); once set, an abbreviation works
  219.         only in "vi" text-entry mode;
  220.  
  221.     (2) keystroke remapping, which can operate either in text-entry
  222.         or in command mode (the "map!" and "map" ex-escape commands);
  223.         once set, a "map!"'ed sequence is triggered only in text-entry
  224.         mode, and a "map"'ed sequence is triggered only in "vi"
  225.         command mode;
  226.  
  227.     (3) text-buffer execution, which operates only in command mode:
  228.         once text has been placed in any of the named text buffers,
  229.         that text can be executed as if it were a sequence of 'vi'
  230.         commands.
  231.  
  232. Text abbreviation
  233. ------------------
  234.  
  235. Using macros during text-entry is almost always motivated by the goal of just
  236. saving keystrokes.  The text-abbreviation macro in 'vi' is set up by going to
  237. "ex-escape" mode by typing a colon, and has the form
  238.  
  239.         abbr <abbreviation> <expansion>
  240.  
  241. where an example might be
  242.  
  243.         abbr gatt General Agreement on Tariffs and Trade
  244.  
  245. [Note that the name of the text abbreviation cannot contain an embedded
  246. space.  This is a limitation of all the 'vi' macro mechanisms except for text-
  247. buffer execution, which uses the names of the named text buffers to define
  248. which macro to execute; a buffer name is a single alphabetic letter.]
  249.  
  250.     Once this is done, then while in text-entry mode, whenever you type
  251. a non-alphanumeric character followed by the string "gatt", 'vi' will examine
  252. the next character you type to see if it's non-alphanumeric, and if so, then
  253. "gatt" will be erased and "General Agreement on Tariffs and Trade" will be
  254. substituted for it.  (Typing "gatt" at the very top of your text qualifies as
  255. a non-alphanumeric character followed by "gatt".)
  256.  
  257.     If you don't want a particular instance of "gatt" to get converted,
  258. even though it's preceded and followed by a non-alphanumeric character, you
  259. have to escape the first character following "gatt" by typing
  260.  
  261.         ^V
  262.  
  263. (that is control-V), so if you want "gatt!" to appear, you type
  264.  
  265.         gatt^V!
  266.  
  267.     With text abbreviations, your text appears as you type it, and no
  268. transformation is performed on your specified abbreviation until you follow
  269. it with a non-alphabetic character (which includes an immediate exit from
  270. text-entry mode).  This differentiates text abbreviation from text-mode
  271. keystroke-remapping using the "map!" command, which will be discussed soon.
  272.  
  273.     Text abbreviations can be canceled with the ex-escape "unabbr"
  274. command,
  275.  
  276.         unabbr gatt
  277.  
  278. Most simple abbreviations can be unabbreviated via a simple ex-escape
  279. command, the kind you introduce by typing a colon from 'vi' command mode. 
  280. But many cannot, especially mode-bouncing abbreviations, to be discussed
  281. later.  For these, you must enter genuine "ex" mode by typing a capital Q
  282. ("Q") from 'vi' command mode.  Then do your "unabbr gatt".  To return to "vi"
  283. mode, enter "vi" or "visual" at the "ex" colon prompt.
  284.  
  285. You can get a list of your currently active abbreviations by entering simply
  286. "abbr" in ex-escape mode.
  287.  
  288. Keystroke remapping: text mode ("map!")
  289. ----------------------------------------
  290.  
  291. As previously mentioned, the text abbreviation mechanism won't make a
  292. substitution on text that you type until you type a character AFTER the
  293. abbreviation that persuades 'vi' that you want 'vi' to expand the
  294. abbreviation.  Also, 'vi' echoes each character of the abbreviation as you
  295. type it, just in case you really want the "abbreviation" to be a literal
  296. sequence of characters in your text.  So with the previous example, if you're
  297. typing away and enter
  298.  
  299.         "I also want to introduce a new word, 'gattblather'..."
  300.  
  301. then if you have "gatt" abbreviated for "General Agreement on Tariffs and
  302. Trade", your text line will remain as-is, with no substitution for the string
  303. "gatt" in "gattblather".  Furthermore, an abbreviated sequence must be preceded
  304. as well as followed by a non-alphanumeric character for the substitution to be
  305. triggered.
  306.  
  307.     Keystroke-remapping works a bit differently.  Keystroke-remapping is
  308. handled by the ex-escape "map" command, which takes two forms: "map" operates
  309. on characters that are typed in command mode, and "map!" operates on
  310. characters that are typed in text-entry mode.  (Some versions of 'vi' may
  311. reverse this.)
  312.  
  313.     Staying with the previous example, the ex-escape command
  314.  
  315.         map! gatt General Agreement on Tariffs and Trade
  316.  
  317. causes the key-sequence "gatt" to be instantly replaced by "General Agreement
  318. on Tariffs and Trade" wherever it's typed.  The abbreviation mechanism waits
  319. to see what the NEXT character after the abbreviation is going to be, before
  320. deciding whether to make a substitution, and if the sequence wasn't preceded
  321. by a non-alphanumeric character (or by the top of the file), the abbreviation
  322. mechanism doesn't start working at all.
  323.  
  324. By contrast, the keystroke-remapping mechanism instead starts a per-character
  325. timer that begins whenever you type the first character of a remapped
  326. sequence.  When you type "g", nothing will be echoed to your screen unless
  327. you type some character other than "a", or unless you type nothing at all
  328. within a timeout period, typically about two seconds long.  In short, 'vi'
  329. watches to see if you've typed the beginning of a remapped sequence, and if
  330. the sequence is longer than a single character, 'vi' waits to see if you'll
  331. type the complete sequence, in which case 'vi' will supply whatever remapping
  332. you've specified for the sequence you've just typed.  This will happen
  333. regardless of what follows the remapped sequence.  So if you've remapped
  334. "gatt" to "General Agreement on Tariffs and Trade", then entering
  335.  
  336.         "I also want to introduce a new word, 'gattblather'..."
  337.  
  338. in text mode will yield
  339.  
  340.         "I also want to introduce a new word, 'General Agreement
  341.         on Tariffs and Tradeblather'..."
  342.  
  343. As with abbreviations "^V" will let you escape the mapping, but this time
  344. the macro has to be preceded rather than followed by it.  The following will
  345. get you a plain "gatt", regardless of how fast you type it:
  346.  
  347.         ^Vgatt
  348.  
  349. To un-map! a previously map!'ed text-mode sequence like "gatt", use the ex-
  350. escape command
  351.  
  352.         unmap! gatt
  353.  
  354. Most simple map!'ings can be un-map!'ed via a simple ex-escape command, the
  355. kind you introduce by typing a colon from 'vi' command mode.  But many
  356. cannot, especially mode-bouncing map!'ings, to be discussed later.  For
  357. these, you must enter genuine "ex" mode by typing a capital Q ("Q") from 'vi'
  358. command mode.  Then do your "unmap! gatt".  To return to "vi" mode, enter
  359. "vi" or "visual" at the "ex" colon prompt.
  360.  
  361. You can get a list of your currently active text-mode remapped sequences by
  362. entering merely "map!" in ex-escape mode.
  363.  
  364. NEVER MAKE A map!'ed DEFINITION RECURSIVE!  More on this later.
  365.  
  366.  
  367. Keystroke remapping: command mode ("map")
  368. ------------------------------------------
  369.  
  370. Sequences that you've made into text abbreviations, or that you've remapped
  371. using "map!", are triggered only when you're in text-entry mode, and are not
  372. triggered in command mode.  (Note, however, that an ex-escape command line is
  373. considered by 'vi' to constitute text-entry mode.)  Command-mode remapping is
  374. done with the "map" ex-escape command -- note the missing exclamation point
  375. -- and works identically with text-entry remapping except that "map"'ed
  376. sequences are triggered only in command mode and are not triggered in text-
  377. entry mode.
  378.  
  379.     Command-mode keystroke remappings can be canceled the same way text-
  380. entry mode keystroke remappings can, except without the exclamation point:
  381.  
  382.         unmap ;
  383.  
  384. Some 'vi' command keys simply cannot be remapped in command mode; the set of
  385. these keys varies according to the implementation of 'vi'.  The most common
  386. unremappable keys are ":" and "u".
  387.  
  388. You can get a list of your currently active command-mode remapped sequences
  389. by entering merely "map" in ex-escape mode.
  390.  
  391.  
  392. Text-buffer execution
  393. ----------------------
  394.  
  395. This topic, which is often glossed over or omitted entirely in most
  396. proprietary 'vi' documentation, can be stated very simply: any named text
  397. buffer can be treated as a 'vi' command-mode macro by typing the at-sign
  398. character ("@") followed by the name of the buffer.  If named buffer "a"
  399. contains 
  400.  
  401.             H!Lsort
  402.  
  403. then "@a" from 'vi' command mode will sort the lines now on the terminal
  404. screen.  The same would of course be true of a "map" that said the same
  405. thing; this example is for illustration.  
  406.  
  407.     The ability to execute a named text buffer as if the buffer were a
  408. sequence of commands allows 'vi' macros sometimes to operate in a self-
  409. modifying way, because a macro can load a text buffer from text in the
  410. current file and then invoke that text buffer as a command macro, without
  411. having to know in advance what the text is that will be loaded into the
  412. buffer.
  413.  
  414. More detail about 'vi' macro operation
  415. =======================================
  416.  
  417. Mode-bouncing
  418. --------------
  419.  
  420. The various 'vi' macro facilities differ in whether they're triggered in text-
  421. entry or in command mode.  Text-abbreviation is triggered only in text-entry
  422. mode; the "map!" command creates macros that are triggered only in text-entry
  423. mode; the "map" command creates macros that are triggered only in command
  424. mode; and the "@" command works only in command mode.
  425.  
  426.     But all this just means that the >trigger< for the macro must come
  427. within the mode that the macro corresponds to.  Any macro, regardless of
  428. type, can switch between the invocation mode and other modes and back again. 
  429. This is what's meant by a "mode-bouncing" macro.  Any 'vi' macro can go
  430. from text-entry to command mode, to ex-escape mode, or to vi-mode.  You just
  431. define the macro with the exact keystroke sequence that you yourself would
  432. use if you were changing modes.  I refer to macros that shift from one mode
  433. to another as "mode-bouncing" macros.
  434.  
  435.     Control characters are entered into macro definitions by preceding
  436. them with a control-V.  The result, after the control character is typed,
  437. appears as something like "^M" for a carriage return, or "^[" for an ESCAPE. 
  438. Say for the sake of argument you've abbreviated "dater" this way:
  439.  
  440.     abbr dater ^M^[:.!date +\%D^MkJA 
  441.  
  442. where "^M" stands for the keystroke sequence "control-V" followed by "control-
  443. M", and "^[" stands for "control-V" "<ESCAPE>".  Try jotting this down on a
  444. piece of paper, or printing it, and then trying the definition out by typing
  445. each keystroke manually.  Then try defining the abbreviation with the ex-
  446. escape "abbr" command, going into text entry mode, and typing text that
  447. contains the string "dater" preceded and followed by a non-alphanumeric
  448. character, say,
  449.  
  450.     I wonder if today is dater?
  451.  
  452. Note that strange things might happen if instead of an abbreviation, you
  453. used "map!" to make this macro, and then made a minor spelling error in
  454. the middle of some other sentence and said "validater".  This difference
  455. is the reason that 'vi' retains both "abbr" and "map!".  Even with
  456. "abbr", it's possible to collide with some valid use of "dater", as in
  457. "Please take this form and run it through the dater;" the lesson here is,
  458. the main problem with 'vi' text macros is pilot error, the failure to
  459. anticipate future collisions that will have unintended effects.
  460.  
  461. [Sidenote: the reason that '%' is preceded by a backslash in the above
  462. example is that on the "ex" command line, '%' is a magic character standing
  463. for the name of the file currently being edited, and therefore must be
  464. escaped to avoid this special meaning.  The two most common other
  465. characters that have special significance on the "ex" command line are
  466. "#", which stands for the last file previously edited, and "!", which
  467. stands either for the shell-escape, shell-filter, or command-history
  468. mechanisms depending on its position within the line.  All of these
  469. characters should be escaped on the "ex" command line when you don't
  470. want "ex" to see them specially.]
  471.  
  472. Text-entry macros that bounce between modes are notoriously difficult to
  473. cancel ("unabbr" or "unmap!") with a simple ex-escape command, the kind you
  474. introduce by typing a colon in 'vi' command mode.  This is because 'vi'
  475. believes that a simple ex-escape command line is being typed in text-entry
  476. mode, therefore it expands the name of the abbreviation or remap!'ing as you
  477. enter it.  The only effective way to get rid of such macros (and probably you
  478. should make it your habit to use this method to unmap ALL macros, just so you
  479. don't have to risk making a mistake evaluating which macro should be erased
  480. this way and which should not) is to type a capital Q ("Q") in 'vi' command
  481. mode, which puts you into genuine "ex" mode.  From now on, 'vi' can't see
  482. you.  Do your "unabbr" or "unmap!", then enter "vi" or "visual" at the next
  483. colon prompt to return to 'vi'.
  484.  
  485. Chained macros
  486. ---------------
  487.  
  488. Macros, being merely pre-defined sequences of keystrokes, can invoke other
  489. macros, anywhere in their definition.  Such "sub-macros" operate like
  490. subroutines in a computer program.  Take the following example:
  491.  
  492.     map = :set wm=3^M
  493.     map ; ^[=oThe End^[O
  494.  
  495. What this does is to first enter 'vi' command mode, in case we're not already
  496. there; invoke the "=" macro to set word-wrap with a hotzone of 3 characters,
  497. open text for entry, insert the words "The End" on a line by themselves, exit
  498. text-entry mode, open a new line above "The End", and let the user start
  499. typing in whatever text is to be ended by "The End".
  500.  
  501. This can be done at any number of levels; the "=" macro could itself call
  502. other macros, and so forth.
  503.  
  504.  
  505. Recursive macros
  506. -----------------
  507.  
  508. A macro that invokes itself is called a "recursive" macro.  'Vi' tries to
  509. limit the creation of recursive macros by prohibiting macros that embody
  510. "tail recursion", which is to say, a macro that ends by invoking itself. 
  511. This policing system is only partial.  Nothing stops you from imbedding a
  512. recursive macro call INSIDE (as opposed to at the end of) a macro definition.
  513. Although 'vi' will object to a definition like
  514.  
  515.         map! $ 123456$
  516.  
  517. it'll accept
  518.  
  519.         map! $ 123$456
  520.  
  521. THIS IS AN ABSOLUTE DISASTER.  You probably wouldn't make this mistake
  522. yourself, but you MIGHT define a text-entry macro as something like
  523.  
  524.         map! usr /usr/group
  525.  
  526. and this is just as disastrous.  The sequence that you use to define a
  527. remapped text-entry macro MUST NOT also appear in the macro text, because
  528. with the "map!" mechanism, the sequence in the macro text will be infinitely
  529. expanded.  This sort of thing is especially pernicious for "map!"; it's very
  530. rare with "abbr", but can happen there, too, provided that the sequence
  531. constituting the abbreviation name appears in the macro text and is bracketed
  532. by non-alphanumeric characters.
  533.  
  534. A macro is just like a computer program, and can be induced to execute
  535. endless loops that either do nothing or else wreak great damage on your text.
  536.  
  537.     However, there is nevertheless a place for a recursive macro call,
  538. almost exclusively in the realm of command-mode macros.  Most often, such
  539. useful recursive macros require just the sort of tail-recursion that 'vi'
  540. resentfully guards against.  'Vi' won't let you end a macro definition with
  541. the same character that you use to name the macro, so that
  542.  
  543.         map ; 123456;
  544.  
  545. won't work; but if you say, instead,
  546.  
  547.         map = ;
  548.         map ; 123456=
  549.  
  550. you're set.  If you invoke the remapped macro key ";" from command mode, then
  551. 'vi' will substitute "123456", and then find that "=" has been remapped to
  552. ";", that ";" has been remapped to "123456=", and repeat itself.  This is
  553. obviously a useless macro, of course; but unlike the text-entry mode macros,
  554. for reasons explained below, it isn't disastrous; it's merely useless.  Useful
  555. tail-recursive macros exist.
  556.  
  557. Sidenote: in this regard, note the "remap" option, which is controlled by the
  558. ex-escape commands "set remap" and "set noremap".  When the remap option is
  559. set (and this is usually the default case) then remapped characters are tried
  560. repeatedly until they are unchanged.  If "o" is mapped to "O" and if "O" is
  561. mapped to "I", then if the remap option is set, "o" will be mapped to "I". 
  562. If the remap option is not set, or to put it another way, if the "noremap"
  563. option is set, then "o" will only be remapped to "O".  Controlling the state
  564. of the remap switch can be used in very sophisticated recursive or chained
  565. macros to control macro termination and macro flow, because since macros can
  566. bounce among modes, it's quite possible, and sometimes useful, to include as
  567. part of the text of a macro,
  568.  
  569.         "...:set noremap^M...:set remap^M"
  570.  
  571. This allows the macro to toggle the remap switch transparently to the way the
  572. option is set outside the context of the macro.
  573.  
  574.  
  575. Terminating a recursive macro
  576. ------------------------------
  577.  
  578. Recursive macros aren't necessary very often -- the ex-escape "g" command
  579. serves pretty well -- but when they are necessary, you might wonder just how
  580. they ever stop.  The first answer is that ordinarily a macro can be
  581. terminated by hitting a keyboard interrupt -- the BREAK or DELETE key, or
  582. sometimes control-C.  The second answer is that a 'vi' macro will terminate
  583. if somewhere in the middle of the macro it finds a command that it can't
  584. execute successfully. 
  585.  
  586. Let's say that you want to count the times a given word or phrase occurs in
  587. your text between your cursor position and the end of text.  The macro
  588.  
  589.         map ; /Monty zuma/^M:!echo>>somefile^M^M=
  590.  
  591. if followed by
  592.  
  593.         map = ;
  594.         set nowrapscan
  595.  
  596. when invoked with the single keystroke ";" will recursively echo a blank line
  597. into "somefile" each time the string "Monty zuma" is encountered in the
  598. current text file.  When the scan reaches the end of the file, the "/"
  599. command will fail because "nowrapscan" is set, and the macro will terminate. 
  600. Such a macro differs from merely counting the lines on which the string
  601. "Monty zuma" occurs, because "Monty zuma" might occur more than once on a
  602. single line.  When it's done, and assuming that "somefile" was nonexistent or
  603. empty when the macro began, then the number of instances of "Monty zuma" from
  604. your cursor position when you invoked the macro to the end of your text file
  605. will correspond to the result of ":!wc -l somefile".  
  606.  
  607. In the above example, note the double "^M" after the shell-escape "echo"
  608. command.  Remember that a 'vi' macro merely duplicates a set of keystrokes. 
  609. Had you typed the command manually at the keyboard, the shell-escape "echo"
  610. command would have ended with a "Press return to continue" banner from 'vi'. 
  611. You'd have had to hit RETURN after typing the "echo" command, then hit RETURN
  612. again after the "echo" command completed, before doing anything else with
  613. 'vi', and the same principle applies to your macro.
  614.  
  615. On the other hand, remember also that some kinds of ex-escape commands do NOT
  616. require an extra RETURN after the command completes.  Most common are the
  617. filtering commands, like the ":.!date^M" command in the "dater" abbreviation
  618. discussed earlier.  You must always keep in mind that the macro is merely
  619. doing keystrokes for you, and that deciding upon the correct sequence of
  620. keystrokes is up to you.  The best approach to writing complex 'vi' macros is
  621. to take a pad and pencil and step through your projected macro keystroke by
  622. keystroke to make sure your logic is correct.  Only after you're sure that it
  623. is, should you actually enter the macro itself.
  624.  
  625. There are some peculiarities and limitations on just how well a macro can
  626. mimic your own keystrokes, and that will be discussed next.
  627.  
  628. Peculiar limitations and restrictions on 'vi' macros
  629. =====================================================
  630.  
  631. Size
  632. -----
  633.  
  634. This is probably the most exasperating restriction.  In most implementations
  635. of 'vi' for microcomputers, the total text of "abbr", "map!", or "map" cannot
  636. exceed some small fixed limit, often the size of a single disk block. 
  637. Moreover, the text of any given abbreviated or remapped sequence, and the
  638. content of any named text buffer used as a macro, cannot be longer than some
  639. even smaller fixed limit, often something like 128 characters.
  640.  
  641. Getting around these restrictions takes some ingenuity.
  642.  
  643. For getting around the size of an individual macro definition, chain macros
  644. together.
  645.  
  646. For getting around the overall limit on macro text, there's really no answer
  647. except to use different sets of macros depending on the job you're doing at
  648. the moment.  An excellent suggestion is to keep a file of every complex macro
  649. you've ever composed, where "complex" here means "hard to remember."  Place
  650. these macros in a text file, and put comments above each one to tell you what
  651. it does and why it works.  Something like
  652.  
  653.     # This macro opens a window in a Compuserve Forum capture
  654.     # file to allow entry of a reply for automatic upload
  655.     # later on.  It assumes that control-A has previously been
  656.     # mapped to the sequence ":set wrapmargin=3^M".  Text marker
  657.     # "a" is set to the top of the block, and marker "b" is
  658.     # set to the bottom of the block, so later, the block from
  659.     # "a" to "b" can be sent to an upload file.
  660.     ?^#: [0-9][0-9]* ?^M/[0-9]/^MdwP/^$/^MP0irep ^[ma^Ao/post^[mbkO
  661.  
  662.     # This macro takes the text between text markers "a" and "b",
  663.     # inclusive, and appends it to the text file "tangen" for later
  664.     # upload to the Compuserve Tangent Forum.
  665.     :'a,'b!cat >>tangen
  666.  
  667. In these examples, the control characters are all printable ascii, so that
  668. RETURN is represented by a caret and then an "M".  In your own "macro
  669. notebook" file, you should have the control characters made explicit, so
  670. that, say, "^M" is a REAL carriage return rather than a caret and an M.  You
  671. insert such characters with the control-V prefix, as discussed earlier.
  672.  
  673. You'll never use such a file directly.  Instead, you'll use the lines in it
  674. to select macros either to place into named text buffers -- you might want to
  675. put the first of the above macros into named buffer "x", and the second into
  676. named buffer "t", so that if you were reading your capture file and wanted to
  677. compose a reply, you'd hit "@x", compose your reply, and then hit "@t" to
  678. save it.
  679.  
  680. Another approach is to use the lines in the file to generate "map", or "abbr"
  681. or "map!" commands to place into the EXINIT environment variable later on. 
  682. You do this by bringing up your macro notebook file in 'vi', prefixing each
  683. line you want to, say, map, with "map soandso ", yanking that line into a
  684. named buffer with a capital-letter name; then saying ":e! new_vi" and using
  685. the "put" command to stick your accumulated text into the "new_vi" file. 
  686. Make sure that you don't re-save the notebook file; one of the nice things
  687. about 'vi' is that it's a non-destructive editor.  Now, in "new_vi", massage
  688. the text so that it's all a massive EXINIT initialization string.  At the
  689. bottom of the file, add "export EXINIT", and then "vi $*".  Write the file,
  690. exit, and enter "sh new_vi", and you'll have a custom-remapped 'vi' for the
  691. present purpose.  Often you'll find that only a very few such different
  692. customized 'vi's are needed.  Only rarely, using this method, does it become
  693. irritating to be limited to, say, a 512-byte block of total macro text.
  694.  
  695. A third approach is to customize a file called '.exrc' in the current
  696. directory: if different kinds of editing jobs are kept in different
  697. directories, each '.exrc' file will contain macros suitable for the job
  698. you're working on.  The format of a '.exrc' file:
  699.  
  700.     ab gatt General Agreement on Tariffs and Trade
  701.     map = :!date^M
  702.     map! qq rot E + dB/dt = 0
  703.     set ai
  704.  
  705. Putting and yanking to/from named buffers
  706. ------------------------------------------
  707.  
  708. Sometimes you'll have inside a macro a directive to yank text into a named
  709. text buffer, and 'vi' will tell you that you can't yank from inside a macro. 
  710. Or put inside a macro.  This is usually a lie: when this error message comes
  711. up, it's probably because of a fault in 'vi's program logic.  You will
  712. probably be able to get around it by making the yank the first thing that
  713. happens in the macro; sometimes, with particularly boneheaded implementations
  714. of 'vi', this will require that you split a single logical macro into two
  715. separate keystrokes.
  716.  
  717. Which keys to remap?
  718. ---------------------
  719.  
  720. As previously mentioned, some keys you can't remap at all in command mode. 
  721. Not much you can do about this.  There are only a limited set of keys that
  722. don't correspond to existing 'vi' commands, so unless you stick with that
  723. limited set, you're eventually going to redefine an existing command key. 
  724. When you do, make sure it's not a command key that you have any pressing
  725. immediate need for.  You can avoid the command-key-name crunch to some extent
  726. by using the named buffers for your macros; very few applications really
  727. require 26 active non-volatile text buffers, so that leaves quite a few of
  728. the named buffers from a-z available for use as macros.
  729.  
  730.  
  731. Conclusion
  732. ===========
  733.  
  734. Writing and using 'vi' macros is roughly equivalent to writing shell scripts,
  735. or other computer programs.  The functionality is limited only by your skill
  736. in using 'vi's own capabilities, the tools available from Unix, and your
  737. imagination.  If you can program in C, don't be afraid of writing a short C
  738. filter that you can tie into a 'vi' macro to do things with text that you
  739. can't see any other easy way to do.  If you can't program in C, there are a
  740. multitude of tools available anyway.  How to use 'vi' in general, and how to
  741. use the multifarious Unix tools, is beyond my scope here.  Have fun.
  742.  
  743.  
  744. resulbuts the requivlt buts the requivlt buts the requivlt buts the re