home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 2001 May / SGI Freeware 2001 May - Disc 3.iso / dist / fw_elisp-intro.idb / usr / freeware / info / emacs-lisp-intro.info-12.z / emacs-lisp-intro.info-12
Encoding:
GNU Info File  |  1998-10-28  |  45.0 KB  |  1,148 lines

  1. This is Info file emacs-lisp-intro.info, produced by Makeinfo version
  2. 1.67 from the input file emacs-lisp-intro.texi.
  3.  
  4.    This is an introduction to `Programming in Emacs Lisp', for people
  5. who are not programmers.
  6.  
  7.    Edition 1.05, 21 October 1997
  8.  
  9.    Copyright (C) 1990, '91, '92, '93, '94, '95, '97 Free Software
  10. Foundation, Inc.
  11.  
  12.    Permission is granted to make and distribute verbatim copies of this
  13. manual provided the copyright notice and this permission notice are
  14. preserved on all copies.
  15.  
  16.    Permission is granted to copy and distribute modified versions of
  17. this manual under the conditions for verbatim copying, provided also
  18. that the sections entitled "Copying" and "GNU General Public License"
  19. are included exactly as in the original, and provided that the entire
  20. resulting derived work is distributed under the terms of a permission
  21. notice identical to this one.
  22.  
  23.    Permission is granted to copy and distribute translations of this
  24. manual into another language, under the above conditions for modified
  25. versions, except that this permission notice may be stated in a
  26. translation approved by the Free Software Foundation.
  27.  
  28. 
  29. File: emacs-lisp-intro.info,  Node: rotate-yank-pointer,  Next: yank,  Prev: Kill Ring,  Up: Kill Ring
  30.  
  31. The `rotate-yank-pointer' Function
  32. ==================================
  33.  
  34.    The `rotate-yank-pointer' function changes the element in the kill
  35. ring to which `kill-ring-yank-pointer' points.  For example, it can
  36. change  `kill-ring-yank-pointer' from pointing to the second element to
  37. point to the third element.
  38.  
  39.    Here is the code for `rotate-yank-pointer':
  40.  
  41.      (defun rotate-yank-pointer (arg)
  42.        "Rotate the yanking point in the kill ring."
  43.        (interactive "p")
  44.        (let ((length (length kill-ring)))
  45.      
  46.          (if (zerop length)
  47.      
  48.              ;; then-part
  49.              (error "Kill ring is empty")
  50.      
  51.            ;; else-part
  52.            (setq kill-ring-yank-pointer
  53.                  (nthcdr (% (+ arg
  54.                                (- length
  55.                                   (length
  56.                                    kill-ring-yank-pointer)))
  57.                             length)
  58.                          kill-ring)))))
  59.  
  60.    The function looks complex, but as usual, it can be understood by
  61. taking it apart piece by piece.  First look at it in skeletal form:
  62.  
  63.      (defun rotate-yank-pointer (arg)
  64.        "Rotate the yanking point in the kill ring."
  65.        (interactive "p")
  66.        (let VARLIST
  67.          BODY...)
  68.  
  69.    This function takes one argument, called `arg'.  It has a brief
  70. documentation string; and it is interactive with a small `p', which
  71. means that the argument must be a processed prefix passed to the
  72. function as a number.
  73.  
  74.    The body of the function definition is a `let' expression, which
  75. itself has a body as well as a VARLIST.
  76.  
  77.    The `let' expression declares a variable that will be only usable
  78. within the bounds of this function.  This variable is called `length'
  79. and is bound to a value that is equal to the number of items in the
  80. kill ring.  This is done by using the function called `length'.  (Note
  81. that this function has the same name as the variable called `length';
  82. but one use of the word is to name the function and the other is to
  83. name the variable.  The two are quite distinct.  Similarly, an English
  84. speaker will distinguish between the meanings of the word `ship' when
  85. he says: "I must ship this package immediately." and "I must get aboard
  86. the ship immediately.")
  87.  
  88.    The function `length' tells the number of items there are in a list,
  89. so `(length kill-ring)' returns the number of items there are in the
  90. kill ring.
  91.  
  92. * Menu:
  93.  
  94. * rotate-yk-ptr body::          The Body of `rotate-yank-pointer'.
  95.  
  96. 
  97. File: emacs-lisp-intro.info,  Node: rotate-yk-ptr body,  Prev: rotate-yank-pointer,  Up: rotate-yank-pointer
  98.  
  99. The Body of `rotate-yank-pointer'
  100. ---------------------------------
  101.  
  102.    The body of `rotate-yank-pointer' is a `let' expression and the body
  103. of the `let' expression is an `if' expression.
  104.  
  105.    The purpose of the `if' expression is to find out whether there is
  106. anything in the kill ring.  If the kill ring is empty, the `error'
  107. function stops evaluation of the function and prints a message in the
  108. echo area.  On the other hand, if the kill ring has something in it, the
  109. work of the function is done.
  110.  
  111.    Here is the if-part and then-part of the `if' expression:
  112.  
  113.      (if (zerop length)                      ; if-part
  114.          (error "Kill ring is empty")        ; then-part
  115.        ...
  116.  
  117. If there is not anything in the kill ring, its length must be zero and
  118. an error message sent to the user: `Kill ring is empty'.  The `if'
  119. expression uses the function `zerop' which returns true if the value it
  120. is testing is zero.  When `zerop' tests true, the then-part of the `if'
  121. is evaluated.  The then-part is a list starting with the function
  122. `error', which is a function that is similar to the `message' function
  123. (*note message::.), in that it prints a one-line message in the echo
  124. area.  However, in addition to printing a message, `error' also stops
  125. evaluation of the function within which it is embedded.  In this case,
  126. this means that the rest of the function will not be evaluated if the
  127. length of the kill ring is zero.
  128.  
  129.    (In my opinion, it is slightly misleading, at least to humans, to use
  130. the term `error' as the name of this function.  A better term would be
  131. `cancel'.  Strictly speaking, of course, you cannot point to, much less
  132. rotate a pointer to a list that has no length, so from the point of view
  133. of the computer, the word `error' is correct.  But a human expects to
  134. attempt this sort of thing, if only to find out whether the kill ring is
  135. full or empty.  This is an act of exploration.
  136.  
  137.    (From the human point of view, the act of exploration and discovery
  138. is not necessarily an error, and therefore should not be labeled as one,
  139. even in the bowels of a computer.  As it is, the code in Emacs implies
  140. that a human who is acting virtuously, by exploring his or her
  141. environment, is making an error.  This is bad.  Even though the computer
  142. takes the same steps as it does when there is an `error', a term such as
  143. `cancel' would have a clearer connotation.)
  144.  
  145. * Menu:
  146.  
  147. * rotate-yk-ptr else-part::     The else-part of the `if' expression.
  148. * Remainder Function::          The remainder, `%', function.
  149. * rotate-yk-ptr remainder::     Using `%' in `rotate-yank-pointer'.
  150. * kill-rng-yk-ptr last elt::    Pointing to the last element.
  151.  
  152. 
  153. File: emacs-lisp-intro.info,  Node: rotate-yk-ptr else-part,  Next: Remainder Function,  Prev: rotate-yk-ptr body,  Up: rotate-yk-ptr body
  154.  
  155. The else-part of the `if' expression
  156. ....................................
  157.  
  158.    The else-part of the `if' expression is dedicated to setting the
  159. value of `kill-ring-yank-pointer' when the kill ring has something in
  160. it.  The code looks like this:
  161.  
  162.      (setq kill-ring-yank-pointer
  163.            (nthcdr (% (+ arg
  164.                          (- length
  165.                             (length kill-ring-yank-pointer)))
  166.                       length)
  167.                    kill-ring)))))
  168.  
  169.    This needs some examination.  Clearly, `kill-ring-yank-pointer' is
  170. being set to be equal to some CDR of the kill ring, using the `nthcdr'
  171. function that is described in an earlier section.  (*Note
  172. copy-region-as-kill::.)  But exactly how does it do this?
  173.  
  174.    Before looking at the details of the code let's first consider the
  175. purpose of the `rotate-yank-pointer' function.
  176.  
  177.    The `rotate-yank-pointer' function changes what
  178. `kill-ring-yank-pointer' points to.  If `kill-ring-yank-pointer' starts
  179. by pointing to the first element of a list, a call to
  180. `rotate-yank-pointer' causes it to point to the second element; and if
  181. `kill-ring-yank-pointer' points to the second element, a call to
  182. `rotate-yank-pointer' causes it to point to the third element.  (And if
  183. `rotate-yank-pointer' is given an argument greater than 1, it jumps the
  184. pointer that many elements.)
  185.  
  186.    The `rotate-yank-pointer' function uses `setq' to reset what the
  187. `kill-ring-yank-pointer' points to.  If `kill-ring-yank-pointer' points
  188. to the first element of the kill ring, then, in the simplest case, the
  189. `rotate-yank-pointer' function must cause it to point to the second
  190. element.  Put another way, `kill-ring-yank-pointer' must be reset to
  191. have a value equal to the CDR of the kill ring.
  192.  
  193.    That is, under these circumstances,
  194.  
  195.      (setq kill-ring-yank-pointer
  196.         ("some text" "a different piece of text" "yet more text"))
  197.      
  198.      (setq kill-ring
  199.         ("some text" "a different piece of text" "yet more text"))
  200.  
  201. the code should do this:
  202.  
  203.      (setq kill-ring-yank-pointer (cdr kill-ring))
  204.  
  205. As a result, the `kill-ring-yank-pointer' will look like this:
  206.  
  207.      kill-ring-yank-pointer
  208.           => ("a different piece of text" "yet more text"))
  209.  
  210.    The actual `setq' expression uses the `nthcdr' function to do the
  211. job.
  212.  
  213.    As we have seen before (*note nthcdr::.), the `nthcdr' function
  214. works by repeatedly taking the CDR of a list--it takes the CDR of the
  215. CDR of the CDR ...
  216.  
  217.    The two following expressions produce the same result:
  218.  
  219.      (setq kill-ring-yank-pointer (cdr kill-ring))
  220.      
  221.      (setq kill-ring-yank-pointer (nthcdr 1 kill-ring))
  222.  
  223.    In the `rotate-yank-pointer' function, however, the first argument
  224. to `nthcdr' is a rather complex looking expression with lots of
  225. arithmetic inside of it:
  226.  
  227.      (% (+ arg
  228.            (- length
  229.               (length kill-ring-yank-pointer)))
  230.         length)
  231.  
  232.    As usual, we need to look at the most deeply embedded expression
  233. first and then work our way towards the light.
  234.  
  235.    The most deeply embedded expression is `(length
  236. kill-ring-yank-pointer)'.  This finds the length of the current value of
  237. the `kill-ring-yank-pointer'.  (Remember that the
  238. `kill-ring-yank-pointer' is the name of a variable whose value is a
  239. list.)
  240.  
  241.    The measurement of the length is inside the expression:
  242.  
  243.      (- length (length kill-ring-yank-pointer))
  244.  
  245. In this expression, the first `length' is the variable that was
  246. assigned the length of the kill ring in the `let' statement at the
  247. beginning of the function.  (One might think this function would be
  248. clearer if the variable `length' were named `length-of-kill-ring'
  249. instead; but if you look at the text of the whole function, you will
  250. see that it is so short that naming this variable `length' is not a
  251. bother, unless you are pulling the function apart into very tiny pieces
  252. as we are doing here.)
  253.  
  254.    So the line `(- length (length kill-ring-yank-pointer))' tells the
  255. difference between the length of the kill ring and the length of the
  256. list whose name is `kill-ring-yank-pointer'.
  257.  
  258.    To see how all this fits into the `rotate-yank-pointer' function,
  259. let's begin by analyzing the case where `kill-ring-yank-pointer' points
  260. to the first element of the kill ring, just as `kill-ring' does, and
  261. see what happens when `rotate-yank-pointer' is called with an argument
  262. of 1.
  263.  
  264.    In this case, the variable `length' and the value of the expression
  265. `(length kill-ring-yank-pointer' will be the same since the variable
  266. `length' is the length of the kill ring and the
  267. `kill-ring-yank-pointer' is pointing to the whole kill ring.
  268. Consequently, the value of
  269.  
  270.      (- length (length kill-ring-yank-pointer))
  271.  
  272. will be zero.  Since the value of `arg' will be 1, this will mean that
  273. the value of the whole expression
  274.  
  275.      (+ arg (- length (length kill-ring-yank-pointer)))
  276.  
  277. will be 1.
  278.  
  279.    Consequently, the argument to `nthcdr' will be found as the result of
  280. the expression
  281.  
  282.      (% 1 length)
  283.  
  284. 
  285. File: emacs-lisp-intro.info,  Node: Remainder Function,  Next: rotate-yk-ptr remainder,  Prev: rotate-yk-ptr else-part,  Up: rotate-yk-ptr body
  286.  
  287. The `%' remainder function
  288. ..........................
  289.  
  290.    To understand `(% 1 length)', we need to understand `%'.  According
  291. to its documentation (which I just found by typing `C-h f <%> <RET>'),
  292. the `%' function returns the remainder of its first argument divided by
  293. its second argument.  For example, the remainder of 5 divided by 2 is
  294. 1.  (2 goes into 5 twice with a remainder of 1.)
  295.  
  296.    What surprises people who don't often do arithmetic is that a smaller
  297. number can be divided by a larger number and have a remainder.  In the
  298. example we just used, 5 was divided by 2.  We can reverse that and ask,
  299. what is the result of dividing 2 by 5?  If you can use fractions, the
  300. answer is obviously 2/5 or .4; but if, as here, you can only use whole
  301. numbers, the result has to be something different.  Clearly, 5 can go
  302. into 2 zero times, but what of the remainder?  To see what the answer
  303. is, consider a case that has to be familiar from childhood:
  304.  
  305.    * 5 divided by 5 is 1 with a remainder of 0;
  306.  
  307.    * 6 divided by 5 is 1 with a remainder of 1;
  308.  
  309.    * 7 divided by 5 is 1 with a remainder of 2.
  310.  
  311.    * Similarly, 10 divided by 5 is 2 with a remainder of 0;
  312.  
  313.    * 11 divided by 5 is 2 with a remainder of 1;
  314.  
  315.    * 12 divided by 5 is 1 with a remainder of 2.
  316.  
  317. By considering the cases as parallel, we can see that
  318.  
  319.    * zero divided by 5 must be zero with a remainder of zero;
  320.  
  321.    * 1 divided by 5 must be zero with a remainder of 1;
  322.  
  323.    * 2 divided by 5 must be zero with a remainder of 2;
  324.  
  325. and so on.
  326.  
  327.    So, in this code, if the value of `length' is 5, then the result of
  328. evaluating
  329.  
  330.      (% 1 5)
  331.  
  332. is 1.  (I just checked this by placing the cursor after the expression
  333. and typing `C-x C-e'.  Indeed, 1 is printed in the echo area.)
  334.  
  335. 
  336. File: emacs-lisp-intro.info,  Node: rotate-yk-ptr remainder,  Next: kill-rng-yk-ptr last elt,  Prev: Remainder Function,  Up: rotate-yk-ptr body
  337.  
  338. Using `%' in `rotate-yank-pointer'
  339. ..................................
  340.  
  341.    When the `kill-ring-yank-pointer' points to the beginning of the
  342. kill ring, and the argument passed to `rotate-yank-pointer' is 1, the
  343. `%' expression returns 1:
  344.  
  345.      (- length (length kill-ring-yank-pointer))
  346.           => 0
  347.  
  348. therefore,
  349.  
  350.      (+ arg (- length (length kill-ring-yank-pointer)))
  351.           => 1
  352.  
  353. and consequently:
  354.  
  355.      (% (+ arg (- length (length kill-ring-yank-pointer)))
  356.         length)
  357.           => 1
  358.  
  359. regardless of the value of `length'.
  360.  
  361. As a result of this, the `setq kill-ring-yank-pointer' expression
  362. simplifies to:
  363.  
  364.      (setq kill-ring-yank-pointer (nthcdr 1 kill-ring))
  365.  
  366. What it does is now easy to understand.  Instead of pointing as it did
  367. to the first element of the kill ring, the `kill-ring-yank-pointer' is
  368. set to point to the second element.
  369.  
  370.    Clearly, if the argument passed to `rotate-yank-pointer' is two, then
  371. the `kill-ring-yank-pointer' is set to `(nthcdr 2 kill-ring)'; and so
  372. on for different values of the argument.
  373.  
  374.    Similarly, if the `kill-ring-yank-pointer' starts out pointing to
  375. the second element of the kill ring, it length is shorter than the
  376. length of the kill ring by 1, so the computation of the remainder is
  377. based on the expression `(% (+ arg 1) length)'.  This means that the
  378. `kill-ring-yank-pointer' is moved from the second element of the kill
  379. ring to the third element if the argument passed to
  380. `rotate-yank-pointer' is 1.
  381.  
  382. 
  383. File: emacs-lisp-intro.info,  Node: kill-rng-yk-ptr last elt,  Prev: rotate-yk-ptr remainder,  Up: rotate-yk-ptr body
  384.  
  385. Pointing to the last element
  386. ............................
  387.  
  388.    The final question is, what happens if the `kill-ring-yank-pointer'
  389. is set to the *last* element of the kill ring?  Will a call to
  390. `rotate-yank-pointer' mean that nothing more can be taken from the kill
  391. ring?  The answer is no.  What happens is different and useful.  The
  392. `kill-ring-yank-pointer' is set to point to the beginning of the kill
  393. ring instead.
  394.  
  395.    Let's see how this works by looking at the code, assuming the length
  396. of the kill ring is 5 and the argument passed to `rotate-yank-pointer'
  397. is 1.  When the `kill-ring-yank-pointer' points to the last element of
  398. the kill ring, its length is 1.  The code looks like this:
  399.  
  400.      (% (+ arg (- length (length kill-ring-yank-pointer))) length)
  401.  
  402.    When the variables are replaced by their numeric values, the
  403. expression looks like this:
  404.  
  405.      (% (+ 1 (- 5 1)) 5)
  406.  
  407. This expression can be evaluated by looking at the most embedded inner
  408. expression first and working outwards:  The value of `(- 5 1)' is 4;
  409. the sum of `(+ 1 4)' is 5; and the remainder of dividing 5 by 5 is
  410. zero.  So what `rotate-yank-pointer' will do is
  411.  
  412.      (setq kill-ring-yank-pointer (nthcdr 0 kill-ring))
  413.  
  414. which will set the `kill-ring-yank-pointer' to point to the beginning
  415. of the kill ring.
  416.  
  417.    So what happens with successive calls to `rotate-yank-pointer' is
  418. that it moves the `kill-ring-yank-pointer' from element to element in
  419. the kill ring until it reaches the end; then it jumps back to the
  420. beginning.  And this is why the kill ring is called a ring, since by
  421. jumping back to the beginning, it is as if the list has no end!  (And
  422. what is a ring, but an entity with no end?)
  423.  
  424. 
  425. File: emacs-lisp-intro.info,  Node: yank,  Next: yank-pop,  Prev: rotate-yank-pointer,  Up: Kill Ring
  426.  
  427. `yank'
  428. ======
  429.  
  430.    After learning about `rotate-yank-pointer', the code for the `yank'
  431. function is almost easy.  It has only one tricky part, which is the
  432. computation of the argument to be passed to `rotate-yank-pointer'.
  433.  
  434.    The code looks like this:
  435.  
  436.      (defun yank (&optional arg)
  437.        "Reinsert the last stretch of killed text.
  438.      More precisely, reinsert the stretch of killed text most
  439.      recently killed OR yanked.
  440.      With just C-U as argument, same but put point in front
  441.      (and mark at end).  With argument n, reinsert the nth
  442.      most recently killed stretch of killed text.
  443.      See also the command \\[yank-pop]."
  444.      
  445.        (interactive "*P")
  446.        (rotate-yank-pointer (if (listp arg) 0
  447.                               (if (eq arg '-) -1
  448.                                 (1- arg))))
  449.        (push-mark (point))
  450.        (insert (car kill-ring-yank-pointer))
  451.        (if (consp arg)
  452.            (exchange-point-and-mark)))
  453.  
  454.    Glancing over this code, we can understand the last few lines readily
  455. enough.  The mark is pushed, that is, remembered; then the first element
  456. (the CAR) of what the `kill-ring-yank-pointer' points to is inserted;
  457. and then, if the argument passed the function is a `cons', point and
  458. mark are exchanged so the point is put in the front of the inserted
  459. text rather than at the end.  This option is explained in the
  460. documentation.  The function itself is interactive with `"*P"'.  This
  461. means it will not work on a read-only buffer, and that the unprocessed
  462. prefix argument is passed to the function.
  463.  
  464. * Menu:
  465.  
  466. * rotate-yk-ptr arg::           Pass the argument to `rotate-yank-pointer'.
  467. * rotate-yk-ptr negative arg::  Pass a negative argument.
  468.  
  469. 
  470. File: emacs-lisp-intro.info,  Node: rotate-yk-ptr arg,  Next: rotate-yk-ptr negative arg,  Prev: yank,  Up: yank
  471.  
  472. Passing the argument
  473. ....................
  474.  
  475.    The hard part of `yank' is understanding the computation that
  476. determines the value of the argument passed to `rotate-yank-pointer'.
  477. Fortunately, it is not so difficult as it looks at first sight.
  478.  
  479.    What happens is that the result of evaluating one or both of the
  480. `if' expressions will be a number and that number will be the argument
  481. passed to `rotate-yank-pointer'.
  482.  
  483.    Laid out with comments, the code looks like this:
  484.  
  485.      (if (listp arg)                         ; if-part
  486.          0                                   ; then-part
  487.        (if (eq arg '-)                       ; else-part, inner if
  488.            -1                                ; inner if's then-part
  489.          (1- arg))))                         ; inner if's else-part
  490.  
  491. This code consists of two `if' expression, one the else-part of the
  492. other.
  493.  
  494.    The first or outer `if' expression tests whether the argument passed
  495. to `yank' is a list.  Oddly enough, this will be true if `yank' is
  496. called without an argument--because then it will be passed the value of
  497. `nil' for the optional argument and an evaluation of `(listp nil)'
  498. returns true!  So, if no argument is passed to `yank', the argument
  499. passed to `rotate-yank-pointer' inside of `yank' is zero.  This means
  500. the pointer is not moved and the first element to which
  501. `kill-ring-yank-pointer' points is inserted, as we expect.  Similarly,
  502. if the argument for `yank' is `C-u', this will be read as a list, so
  503. again, a zero will be passed to `rotate-yank-pointer'.  (`C-u' produces
  504. an unprocessed prefix argument of `(4)', which is a list of one
  505. element.)  At the same time, later in the function, this argument will
  506. be read as a `cons' so point will be put in the front and mark at the
  507. end of the insertion.  (The `P' argument to `interactive' is designed
  508. to provide these values for the case when an optional argument is not
  509. provided or when it is `C-u'.)
  510.  
  511.    The then-part of the outer `if' expression handles the case then
  512. there is no argument or when it is `C-u'.  The else-part handles the
  513. other situations.  The else-part is itself another `if' expression.
  514.  
  515.    The inner `if' expression tests whether the argument is a minus
  516. sign.  (This is done by pressing the <META> and `-' keys at the same
  517. time, or the <ESC> key and then the `-' key).  In this case, the
  518. `rotate-yank-pointer' function is passed `-1' as an argument.  This
  519. moves the `kill-ring-yank-pointer' backwards, which is what is desired.
  520.  
  521.    If the true-or-false-test of the inner `if' expression is false
  522. (that is, if the argument is not a minus sign), the else-part of the
  523. expression is evaluated.  This is the expression `(1- arg)'.  Because
  524. of the two `if' expressions, it will only occur when the argument is a
  525. positive number or when it is a negative number (not just a minus sign
  526. on its own).  What `(1- arg)' does is decrement the number and return
  527. it.  (The `1-' function subtracts one from its argument.)  This means
  528. that if the argument to `rotate-yank-pointer' is 1, it is reduced to
  529. zero, which means the first element to which `kill-ring-yank-pointer'
  530. points is yanked back, as you would expect.
  531.  
  532. 
  533. File: emacs-lisp-intro.info,  Node: rotate-yk-ptr negative arg,  Prev: rotate-yk-ptr arg,  Up: yank
  534.  
  535. Passing a negative argument
  536. ...........................
  537.  
  538.    Finally, the question arises, what happens if either the remainder
  539. function, `%', or the `nthcdr' function is passed a negative argument,
  540. as they quite well may?
  541.  
  542.    The answers can be found by a quick test.  When `(% -1 5)' is
  543. evaluated, a negative number is returned; and if `nthcdr' is called
  544. with a negative number, it returns the same value as if it were called
  545. with a first argument of zero.  This can be seen be evaluating the
  546. following code.
  547.  
  548.    Here the `=>' points to the result of evaluating the code preceding
  549. it.  This was done by positioning the cursor after the code and typing
  550. `C-x C-e' (`eval-last-sexp') in the usual fashion.  You can do this if
  551. you are reading this in Info inside of GNU Emacs.
  552.  
  553.      (% -1 5)
  554.           => -1
  555.      
  556.      (setq animals '(cats dogs elephants))
  557.           => (cats dogs elephants)
  558.      
  559.      (nthcdr 1 animals)
  560.           => (dogs elephants)
  561.      
  562.      (nthcdr 0 animals)
  563.           => (cats dogs elephants)
  564.      
  565.      (nthcdr -1 animals)
  566.           => (cats dogs elephants)
  567.  
  568.    So, if a minus sign or a negative number is passed to `yank', the
  569. `kill-ring-yank-point' is rotated backwards until it reaches the
  570. beginning of the list.  Then it stays there.  Unlike the other case,
  571. when it jumps from the end of the list to the beginning of the list,
  572. making a ring, it stops.  This makes sense.  You often want to get back
  573. to the most recently clipped out piece of text, but you don't usually
  574. want to insert text from as many as thirty kill commands ago.  So you
  575. need to work through the ring to get to the end, but won't cycle around
  576. it inadvertently if you are trying to come back to the beginning.
  577.  
  578.    Incidentally, any number passed to `yank' with a minus sign
  579. preceding it will be treated as -1.  This is evidently a simplification
  580. for writing the program.  You don't need to jump back towards the
  581. beginning of the kill ring more than one place at a time and doing this
  582. is easier than writing a function to determine the magnitude of the
  583. number that follows the minus sign.
  584.  
  585. 
  586. File: emacs-lisp-intro.info,  Node: yank-pop,  Prev: yank,  Up: Kill Ring
  587.  
  588. `yank-pop'
  589. ==========
  590.  
  591.    After understanding `yank', the `yank-pop' function is easy.
  592. Leaving out the documentation to save space, it looks like this:
  593.  
  594.      (defun yank-pop (arg)
  595.        (interactive "*p")
  596.        (if (not (eq last-command 'yank))
  597.            (error "Previous command was not a yank"))
  598.        (setq this-command 'yank)
  599.        (let ((before (< (point) (mark))))
  600.          (delete-region (point) (mark))
  601.          (rotate-yank-pointer arg)
  602.          (set-mark (point))
  603.          (insert (car kill-ring-yank-pointer))
  604.          (if before (exchange-point-and-mark))))
  605.  
  606.    The function is interactive with a small `p' so the prefix argument
  607. is processed and passed to the function.  The command can only be used
  608. after a previous yank; otherwise an error message is sent.  This check
  609. uses the variable `last-command' which is discussed elsewhere.  (*Note
  610. copy-region-as-kill::.)
  611.  
  612.    The `let' clause sets the variable `before' to true or false
  613. depending whether point is before or after mark and then the region
  614. between point and mark is deleted.  This is the region that was just
  615. inserted by the previous yank and it is this text that will be
  616. replaced.  Next the `kill-ring-yank-pointer' is rotated so that the
  617. previously inserted text is not reinserted yet again.  Mark is set at
  618. the beginning of the place the new text will be inserted and then the
  619. first element to which `kill-ring-yank-pointer' points is inserted.
  620. This leaves point after the new text.  If in the previous yank, point
  621. was left before the inserted text, point and mark are now exchanged so
  622. point is again left in front of the newly inserted text.  That is all
  623. there is to it!
  624.  
  625. 
  626. File: emacs-lisp-intro.info,  Node: Full Graph,  Next: Index,  Prev: Kill Ring,  Up: Top
  627.  
  628. A Graph with Labelled Axes
  629. **************************
  630.  
  631.    Printed axes help you understand a graph.  They convey scale.  In an
  632. earlier chapter (*note Readying a Graph: Readying a Graph.), we wrote
  633. the code to print the body of a graph.  Here we write the code for
  634. print and labelling vertical and horizontal axes, along with the body
  635. itself.
  636.  
  637. * Menu:
  638.  
  639. * Labelled Example::            How a finished graph should look.
  640. * print-graph Varlist::         `let' expression in `print-graph'.
  641. * print-Y-axis::                Print a label for the vertical axis.
  642. * print-X-axis::                Print a horizontal label.
  643. * Print Whole Graph::           The function to print a complete graph.
  644.  
  645. 
  646. File: emacs-lisp-intro.info,  Node: Labelled Example,  Next: print-graph Varlist,  Prev: Full Graph,  Up: Full Graph
  647.  
  648. Labelled Example Graph
  649. ======================
  650.  
  651.    Since insertions fill a buffer to the right and below point, the new
  652. graph printing function should first print the Y or vertical axis, then
  653. the body of the graph, and finally the X or horizontal axis.  This
  654. sequence lays out for us the contents of the function:
  655.  
  656.   1. Set up code.
  657.  
  658.   2. Print Y axis.
  659.  
  660.   3. Print body of graph.
  661.  
  662.   4. Print X axis.
  663.  
  664.    Here is an example of how a finished graph should look:
  665.  
  666.          10 -
  667.                        *
  668.                        *  *
  669.                        *  **
  670.                        *  ***
  671.           5 -      *   *******
  672.                  * *** *******
  673.                  *************
  674.                ***************
  675.           1 - ****************
  676.               |   |    |    |
  677.               1   5   10   15
  678.  
  679. In this graph, both the vertical and the horizontal axes are labeled
  680. with numbers.  However, in some graphs, the horizontal axis is time and
  681. would be better labeled with months, like this:
  682.  
  683.           5 -      *
  684.                  * ** *
  685.                  *******
  686.                ********** **
  687.           1 - **************
  688.               |    ^      |
  689.               Jan  June   Jan
  690.  
  691.    Indeed, with a little thought, we can easily come up with a variety
  692. of vertical and horizontal labelling schemes.  Our task could become
  693. complicated.  But complications breed confusion.  Rather than permit
  694. this, it is better choose a simple labelling scheme for our first
  695. effort, and to modify or replace it later.
  696.  
  697.    These considerations suggest the following outline for the
  698. `print-graph' function:
  699.  
  700.      (defun print-graph (numbers-list)
  701.        "DOCUMENTATION..."
  702.        (let ((height  ...
  703.              ...))
  704.          (print-Y-axis height ... )
  705.          (graph-body-print numbers-list)
  706.          (print-X-axis ... )))
  707.  
  708.    We can work on each part of the `print-graph' function definition in
  709. turn.
  710.  
  711. 
  712. File: emacs-lisp-intro.info,  Node: print-graph Varlist,  Next: print-Y-axis,  Prev: Labelled Example,  Up: Full Graph
  713.  
  714. The `print-graph' Varlist
  715. =========================
  716.  
  717.    In writing the `print-graph' function, the first task is to write
  718. the varlist in the `let' expression.  (We will leave aside for the
  719. moment any thoughts about making the function interactive or about the
  720. contents of its documentation string.)
  721.  
  722.    The varlist should set several values.  Clearly, the top of the label
  723. for the vertical axis must be at least the height of the graph, which
  724. means that we must obtain this information here.  Note that the
  725. `print-graph-body' function also requires this information.  There is
  726. no reason to calculate the height of the graph in two different places,
  727. so we should change for `print-graph-body' from the way we defined it
  728. earlier to take advantage of the calculation.
  729.  
  730.    Similarly, both the function for printing the X axis labels and the
  731. `print-graph-body' function need to learn the value of the width of
  732. each symbol.  We can perform the calculation here and change the
  733. definition for `print-graph-body' from the way we defined it in the
  734. previous chapter.
  735.  
  736.    The length of the label for the horizontal axis must be at least as
  737. long as the graph.  However, this information is used only in the
  738. function that prints the horizontal axis, so it does not need to be
  739. calculated here.
  740.  
  741.    These thoughts lead us directly to the following form for the varlist
  742. in the `let' for `print-graph':
  743.  
  744.      (let ((height (apply 'max numbers-list)) ; First version.
  745.            (symbol-width (length graph-blank)))
  746.  
  747. As we shall see, this expression is not quite right.
  748.  
  749. 
  750. File: emacs-lisp-intro.info,  Node: print-Y-axis,  Next: print-X-axis,  Prev: print-graph Varlist,  Up: Full Graph
  751.  
  752. The `print-Y-axis' Function
  753. ===========================
  754.  
  755.    The job of the `print-Y-axis' function is to print a label for the
  756. vertical axis that looks like this:
  757.  
  758.          10 -
  759.      
  760.      
  761.      
  762.      
  763.           5 -
  764.      
  765.      
  766.      
  767.           1 -
  768.  
  769. The function should be passed the height of the graph, and then should
  770. construct and insert the appropriate numbers and marks.
  771.  
  772.    It is easy enough to see in the figure what the Y axis label should
  773. look like; but to say in words, and then to write a function definition
  774. to do the job is another matter.  It is not quite true to say that we
  775. want a number and a tick every five lines: there are only three lines
  776. between the `1' and the `5' (lines 2, 3, and 4), but four lines between
  777. the `5' and the `10' (lines 6, 7, 8, and 9).  It is better to say that
  778. we want a number and a tick mark on the base line (number 1) and then
  779. that we want a number and a tick on the fifth line from the bottom and
  780. on every line that is a multiple of five.
  781.  
  782.    The next issue is what height the label should be.  Suppose the
  783. maximum height of tallest column of the graph is seven.  Should the
  784. highest label on the Y axis be `5 -', and should the graph stick up
  785. above the label?  Or should the highest label be `7 -', and mark the
  786. peak of the graph?  Or should the highest label be `10 -', which is a
  787. multiple of five, and be higher than the topmost value of the graph?
  788.  
  789.    The latter form is preferred.  Most graphs are drawn within
  790. rectangles whose sides are an integral number of steps long--5, 10, 15,
  791. and so on for a step distance of five.  But as soon as we decide to use
  792. a step height for the vertical axis, we discover that the simple
  793. expression in the varlist for computing the height is wrong.  The
  794. expression is `(apply 'max numbers-list)'.  This returns the precise
  795. height, not the maximum height plus whatever is necessary to round up
  796. to the nearest multiple of five.  A more complex expression is required.
  797.  
  798.    As usual in cases like this, a complex problem becomes simpler if it
  799. is divided into several smaller problems.
  800.  
  801.    First, consider the case when the highest value of the graph is an
  802. integral multiple of five--when it is 5, 10, 15 ,or some higher
  803. multiple of five.  In this case, we can use this value as the Y axis
  804. height.
  805.  
  806.    A fairly simply way to determine whether a number is a multiple of
  807. five is to divide it by five and see if the division results in a
  808. remainder.  If there is no remainder, the number is a multiple of five.
  809. Thus, seven divided by five has a remainder of two, and seven is not
  810. an integral multiple of five.  Put in slightly different language, more
  811. reminiscent of the classroom, five goes into seven once, with a
  812. remainder of two.  However, five goes into ten twice, with no
  813. remainder: ten is an integral multiple of five.
  814.  
  815. * Menu:
  816.  
  817. * Compute a Remainder::         How to compute the remainder of a division.
  818. * Y Axis Element::              Construct a line for the Y axis.
  819. * Y-axis-column::               Generate a list of Y axis labels.
  820. * print-Y-axis Final::          Print a vertical axis, final version.
  821.  
  822. 
  823. File: emacs-lisp-intro.info,  Node: Compute a Remainder,  Next: Y Axis Element,  Prev: print-Y-axis,  Up: print-Y-axis
  824.  
  825. Side Trip: Compute a Remainder
  826. ------------------------------
  827.  
  828.    In Lisp, the function for computing a remainder is `%'.  The
  829. function returns the remainder of its first argument divided by its
  830. second argument.  As it happens, `%' is a function in Emacs Lisp that
  831. you cannot discover using `apropos': you find nothing if you type `M-x
  832. apropos <RET> remainder <RET>'.  The only way to learn of the existence
  833. of `%' is to read about it in a book such as this or in the Emacs Lisp
  834. sources.  The `%' function is used in the code for
  835. `rotate-yank-pointer', which is described in an appendix.  (*Note The
  836. Body of `rotate-yank-pointer': rotate-yk-ptr body.)
  837.  
  838.    You can try the `%' function by evaluating the following two
  839. expressions:
  840.  
  841.      (% 7 5)
  842.      
  843.      (% 10 5)
  844.  
  845. The first expression returns 2 and the second expression returns 0.
  846.  
  847.    To test whether the returned value is zero or some other number, we
  848. can use the `zerop' function.  This function returns `t' if its
  849. argument, which must be a number, is zero.
  850.  
  851.      (zerop (% 7 5))
  852.           => nil
  853.      
  854.      (zerop (% 10 5))
  855.           => t
  856.  
  857.    Thus, the following expression will return `t' if the height of the
  858. graph is evenly divisible by five:
  859.  
  860.      (zerop (% height 5))
  861.  
  862. (The value of `height', of course, can be found from `(apply 'max
  863. numbers-list)'.)
  864.  
  865.    On the other hand, if the value of `height' is not a multiple of
  866. five, we want to reset the value to the next higher multiple of five.
  867. This is straightforward arithmetic using functions with which we are
  868. already familiar.  First, we divide the value of `height' by five to
  869. determine how many times five goes into the number.  Thus, five goes
  870. into twelve twice.  If we add one to this quotient and multiply by
  871. five, we will obtain the value of the next multiple of five that is
  872. larger than the height.  Five goes into twelve twice.  Add one to two,
  873. and multiply by five; the result is fifteen, with is the next multiple
  874. of five that is higher than twelve.  The Lisp expression for this is:
  875.  
  876.      (* (1+ (/ height 5)) 5)
  877.  
  878. For example, if you evaluate the following, the result is 15:
  879.  
  880.      (* (1+ (/ 12 5)) 5)
  881.  
  882.    All through this discussion, we have been using `five' as the value
  883. for spacing labels on the Y axis; but we may want to use some other
  884. value.  For generality, we should replace `five' with a variable to
  885. which we can assign a value.  The best name I can think of for this
  886. variable is `Y-axis-label-spacing'.  Using this term, and an `if'
  887. expression, we produce the following:
  888.  
  889.      (if (zerop (% height Y-axis-label-spacing))
  890.          height
  891.        ;; else
  892.        (* (1+ (/ height Y-axis-label-spacing))
  893.           Y-axis-label-spacing))
  894.  
  895. This expression returns the value of `height' itself if the height is
  896. an even multiple of the value of the `Y-axis-label-spacing' or else it
  897. computes and returns a value of `height' that is equal to the next
  898. higher multiple of the value of the `Y-axis-label-spacing'.
  899.  
  900.    We can now include this expression in the `let' expression of the
  901. `print-graph' function (after first setting the value of
  902. `Y-axis-label-spacing'):
  903.  
  904.      (defvar Y-axis-label-spacing 5
  905.        "Number of lines from one Y axis label to next.")
  906.      
  907.      ...
  908.      (let* ((height (apply 'max numbers-list))
  909.             (height-of-top-line
  910.              (if (zerop (% height Y-axis-label-spacing))
  911.                  height
  912.                ;; else
  913.                (* (1+ (/ height Y-axis-label-spacing))
  914.                   Y-axis-label-spacing)))
  915.             (symbol-width (length graph-blank))))
  916.      ...
  917.  
  918. (Note use of the  `let*' function: the initial value of height is
  919. computed once by the `(apply 'max numbers-list)' expression and then
  920. the resulting value of  `height' is used to compute its final value.
  921. *Note The `let*' expression: fwd-para let, for more about `let*'.)
  922.  
  923. 
  924. File: emacs-lisp-intro.info,  Node: Y Axis Element,  Next: Y-axis-column,  Prev: Compute a Remainder,  Up: print-Y-axis
  925.  
  926. Construct a Y Axis Element
  927. --------------------------
  928.  
  929.    When we print the vertical axis, we want to insert strings such as
  930. `5 -' and `10 - ' every five lines.  Moreover, we want the numbers and
  931. dashes to line up, so shorter numbers must be padded with leading
  932. spaces.  If some of the strings use two digit numbers, the strings with
  933. single digit numbers must include a leading blank space before the
  934. number.
  935.  
  936.    To figure out the length of the number, the `length' function is
  937. used.  But the `length' function works only with a string, not with a
  938. number.  So the number has to be converted from being a number to being
  939. a string.  This is done with the `int-to-string' function.  For example,
  940.  
  941.      (length (int-to-string 35))
  942.           => 2
  943.      
  944.      (length (int-to-string 100))
  945.           => 3
  946.  
  947.    In addition, in each label, each number is followed by a string such
  948. as ` - ', which we will call the `Y-axis-tic' marker.  This variable is
  949. defined with `defvar':
  950.  
  951.      (defvar Y-axis-tic " - "
  952.         "String that follows number in a Y axis label.")
  953.  
  954.    The length of the Y label is the sum of the length of the Y axis tick
  955. mark and the length of the number of the top of the graph.
  956.  
  957.      (length (concat (int-to-string height) Y-axis-tic)))
  958.  
  959.    This value will be calculated by the `print-graph' function in its
  960. varlist as `full-Y-label-width' and passed on.  (Note that we did not
  961. think to include this in the varlist when we first proposed it.)
  962.  
  963.    To make a complete vertical axis label, a tick mark is concatenated
  964. with a number; and the two together may be preceded by one or more
  965. spaces depending on how long the number is.  The label consists of
  966. three parts: the (optional) leading spaces, the number, and the tic
  967. mark.  The function is passed the value of the number for the specific
  968. row, and the value of the width of the top line, which is calculated
  969. (just once) by `print-graph'.
  970.  
  971.      (defun Y-axis-element (number full-Y-label-width)
  972.        "Construct a NUMBERed label element.
  973.      A numbered element looks like this `  5 - ',
  974.      and is padded as needed so all line up with
  975.      the element for the largest number."
  976.        (let* ((leading-spaces
  977.               (- full-Y-label-width
  978.                  (length
  979.                   (concat (int-to-string number)
  980.                           Y-axis-tic)))))
  981.          (concat
  982.           (make-string leading-spaces ? )
  983.           (int-to-string number)
  984.           Y-axis-tic)))
  985.  
  986.    The `Y-axis-element' function concatenates together the leading
  987. spaces, if any; the number, as a string; and the tick mark.
  988.  
  989.    To figure out how many leading spaces the label will need, the
  990. function subtracts the actual length of the label--the length of the
  991. number plus the length of the tic mark--from the desired label width.
  992.  
  993.    Blank spaces are inserted using the `make-string' function.  This
  994. function takes two arguments: the first tells it how long the string
  995. will be and the second is a symbol for the character to insert, in a
  996. special format.  In this case, the format is a question mark followed
  997. by a blank space, like this, `? '.  *Note Character Type:
  998. (elisp)Character Type, for a description of the syntax for characters.
  999.  
  1000.    The `int-to-string' function is used in the concatenation
  1001. expression, to convert the number to a string that is concatenated with
  1002. the leading spaces and the tic mark.
  1003.  
  1004. 
  1005. File: emacs-lisp-intro.info,  Node: Y-axis-column,  Next: print-Y-axis Final,  Prev: Y Axis Element,  Up: print-Y-axis
  1006.  
  1007. Create a Y Axis Column
  1008. ----------------------
  1009.  
  1010.    The preceding functions provide all the tools needed to construct a
  1011. function that generates a list of numbered and blank strings to insert
  1012. as the label for the vertical axis:
  1013.  
  1014.      (defun Y-axis-column (height width-of-label)
  1015.        "Construct list of Y axis labels and blank strings.
  1016.      For HEIGHT of line above base and WIDTH-OF-LABEL."
  1017.        (let (Y-axis)
  1018.          (while (> height 1)
  1019.            (if (zerop (% height Y-axis-label-spacing))
  1020.                ;; Insert label.
  1021.                (setq Y-axis
  1022.                      (cons
  1023.                       (Y-axis-element height width-of-label)
  1024.                       Y-axis))
  1025.              ;; Else, insert blanks.
  1026.              (setq Y-axis
  1027.                    (cons
  1028.                     (make-string width-of-label ? )
  1029.                     Y-axis)))
  1030.            (setq height (1- height)))
  1031.          ;; Insert base line.
  1032.          (setq Y-axis
  1033.                (cons (Y-axis-element 1 width-of-label) Y-axis))
  1034.          (nreverse Y-axis)))
  1035.  
  1036.    In this function, we start with the value of `height' and
  1037. repetitively subtract one from its value.  After each subtraction, we
  1038. test to see whether the value is an integral multiple of the
  1039. `Y-axis-label-spacing'.  If it is, we construct a numbered label using
  1040. the `Y-axis-element' function; if not, we construct a blank label using
  1041. the `make-string' function.  The base line consists of the number one
  1042. followed by a tic mark.
  1043.  
  1044. 
  1045. File: emacs-lisp-intro.info,  Node: print-Y-axis Final,  Prev: Y-axis-column,  Up: print-Y-axis
  1046.  
  1047. Final Version of `print-Y-axis'
  1048. -------------------------------
  1049.  
  1050.    The list constructed by the `Y-axis-column' function is passed to
  1051. the `print-Y-axis' function, which inserts the list as a column.
  1052.  
  1053.      (defun print-Y-axis
  1054.        (height full-Y-label-width &optional vertical-step)
  1055.        "Insert Y axis using HEIGHT and FULL-Y-LABEL-WIDTH.
  1056.      Height must be the  maximum height of the graph.
  1057.      Full width is the width of the highest label element.
  1058.      Optionally, print according to VERTICAL-STEP."
  1059.      ;; Value of height and full-Y-label-width
  1060.      ;; are passed by `print-graph'.
  1061.        (let ((start (point)))
  1062.          (insert-rectangle
  1063.           (Y-axis-column height full-Y-label-width vertical-step))
  1064.          ;; Place point ready for inserting graph.
  1065.          (goto-char start)
  1066.          ;; Move point forward by value of full-Y-label-width
  1067.          (forward-char full-Y-label-width)))
  1068.  
  1069.    The `print-Y-axis' uses the `insert-rectangle' function to insert
  1070. the Y axis labels created by the `Y-axis-column' function.  In
  1071. addition, it places point at the correct position for printing the body
  1072. of the graph.
  1073.  
  1074.    You can test `print-Y-axis':
  1075.  
  1076.   1. Install
  1077.  
  1078.           Y-axis-label-spacing
  1079.           Y-axis-tic
  1080.           Y-axis-element
  1081.           Y-axis-columnprint-Y-axis
  1082.  
  1083.   2. Copy the following expression:
  1084.  
  1085.           (print-Y-axis 12 5)
  1086.  
  1087.   3. Switch to the `*scratch*' buffer and place the cursor where you
  1088.      want the axis labels to start.
  1089.  
  1090.   4. Type `M-:' (`eval-expression').
  1091.  
  1092.   5. Yank the `graph-body-print' expression into the minibuffer with
  1093.      `C-y' (`yank)'.
  1094.  
  1095.   6. Press <RET> to evaluate the expression.
  1096.  
  1097.    Emacs will print labels vertically, the top one being `10 - '.  (The
  1098. `print-graph' function will pass the value of `height-of-top-line',
  1099. which in this case would be 15.)
  1100.  
  1101. 
  1102. File: emacs-lisp-intro.info,  Node: print-X-axis,  Next: Print Whole Graph,  Prev: print-Y-axis,  Up: Full Graph
  1103.  
  1104. The `print-X-axis' Function
  1105. ===========================
  1106.  
  1107.    X axis labels are much like Y axis labels, except that the tics are
  1108. on a line above the numbers.  Labels should look like this:
  1109.  
  1110.          |   |    |    |
  1111.          1   5   10   15
  1112.  
  1113.    The first tic is under the first column of the graph and is preceded
  1114. by several blank spaces.  These spaces provide room in rows above for
  1115. the Y axis labels.  The second, third, fourth, and subsequent tics are
  1116. all spaced equally, according to the value of `X-axis-label-spacing'.
  1117.  
  1118.    The second row of the X axis consists of numbers, preceded by several
  1119. blank spaces and also separated according to the value of the variable
  1120. `X-axis-label-spacing'.
  1121.  
  1122.    The value of the variable `X-axis-label-spacing' should itself be
  1123. measured in units of `symbol-width', since you may want to change the
  1124. width of the symbols that you are using to print the body of the graph
  1125. without changing the ways the graph is labeled.
  1126.  
  1127.    The `print-X-axis' function is constructed in more or less the same
  1128. fashion as the `print-Y-axis' function except that it has two lines:
  1129. the line of tic marks and the numbers.  We will write a separate
  1130. function to print each line and then combine them within the
  1131. `print-X-axis' function.
  1132.  
  1133.    This is a three step process:
  1134.  
  1135.   1. Write a function to print the X axis tic marks,
  1136.      `print-X-axis-tic-line'.
  1137.  
  1138.   2. Write a function to print the X numbers,
  1139.      `print-X-axis-numbered-line'.
  1140.  
  1141.   3. Write a function to print both lines, the `print-X-axis' function,
  1142.      using `print-X-axis-tic-line' and `print-X-axis-numbered-line'.
  1143.  
  1144. * Menu:
  1145.  
  1146. * X Axis Tic Marks::            Create tic marks for the horizontal axis.
  1147.  
  1148.