an introduction to programming in emacs lisp

314

Upload: robert-j-chassell

Post on 08-Dec-2016

222 views

Category:

Documents


5 download

TRANSCRIPT

Page 1: An Introduction to Programming in Emacs Lisp

An Introdu tion toProgramming in Ema s Lisp

Page 2: An Introduction to Programming in Emacs Lisp
Page 3: An Introduction to Programming in Emacs Lisp

An Introdu tion toProgramming in Ema s LispSe ond Editionby Robert J. Chassell

Page 4: An Introduction to Programming in Emacs Lisp

Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1997, 2001, 2002 FreeSoftware Foundation, In .Published by the Free Software Foundation, In .59 Temple Pla e, Suite 330Boston, MA 02111-1307 USAEdition 2.05, 2001 Jan 5ISBN 1-882114-43-4Permission is granted to opy, distribute and/or modify this do ument underthe terms of the GNU Free Do umentation Li ense, Version 1.1 or any laterversion published by the Free Software Foundation; there being no InvariantSe tion, with the Front-Cover Texts being \A GNU Manual", and with theBa k-Cover Texts as in (a) below. A opy of the li ense is in luded in these tion entitled \GNU Free Do umentation Li ense".(a) The FSF's Ba k-Cover Text is: \You have freedom to opy and modifythis GNUManual, like GNU software. Copies published by the Free SoftwareFoundation raise funds for GNU development."

Page 5: An Introduction to Programming in Emacs Lisp

iShort ContentsPrefa e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi1 List Pro essing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 Pra ti ing Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . 233 How To Write Fun tion De�nitions . . . . . . . . . . . . . . . . . . 294 A Few Bu�er{Related Fun tions . . . . . . . . . . . . . . . . . . . . 515 A Few More Complex Fun tions . . . . . . . . . . . . . . . . . . . . 636 Narrowing and Widening . . . . . . . . . . . . . . . . . . . . . . . . . 777 ar, dr, ons: Fundamental Fun tions . . . . . . . . . . . . . 818 Cutting and Storing Text . . . . . . . . . . . . . . . . . . . . . . . . . 899 How Lists are Implemented . . . . . . . . . . . . . . . . . . . . . . . 11310 Yanking Text Ba k . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11711 Loops and Re ursion . . . . . . . . . . . . . . . . . . . . . . . . . . . 12112 Regular Expression Sear hes . . . . . . . . . . . . . . . . . . . . . . 14913 Counting: Repetition and Regexps . . . . . . . . . . . . . . . . . . 16714 Counting Words in a defun . . . . . . . . . . . . . . . . . . . . . . 18115 Readying a Graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20316 Your `.ema s' File . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21317 Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23118 Con lusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239Appendix A The the-the Fun tion . . . . . . . . . . . . . . . . . . 241Appendix B Handling the Kill Ring . . . . . . . . . . . . . . . . . . . 243Appendix C A Graph with Labelled Axes . . . . . . . . . . . . . . . 255Appendix D GNU Free Do umentation Li ense . . . . . . . . . . . 279Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287

Page 6: An Introduction to Programming in Emacs Lisp

ii

Page 7: An Introduction to Programming in Emacs Lisp

iiiTable of ContentsPrefa e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiOn Reading this Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiFor Whom This is Written. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiiLisp History . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiiiA Note for Novi es . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiiiThank You . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiv1 List Pro essing . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1 Lisp Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1.1 Lisp Atoms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1.2 Whitespa e in Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.1.3 GNU Ema s Helps You Type Lists . . . . . . . . . . . . . . . 31.2 Run a Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41.3 Generate an Error Message . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41.4 Symbol Names and Fun tion De�nitions . . . . . . . . . . . . . . . . . . 61.5 The Lisp Interpreter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71.5.1 Byte Compiling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81.6 Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81.6.1 Evaluating Inner Lists . . . . . . . . . . . . . . . . . . . . . . . . . . 91.7 Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101.7.1 Error Message for a Symbol Without a Fun tion . . 111.7.2 Error Message for a Symbol Without a Value . . . . 111.8 Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121.8.1 Arguments' Data Types . . . . . . . . . . . . . . . . . . . . . . . . 131.8.2 An Argument as the Value of a Variable or List . . 131.8.3 Variable Number of Arguments . . . . . . . . . . . . . . . . . 141.8.4 Using the Wrong Type Obje t as an Argument . . 141.8.5 The message Fun tion . . . . . . . . . . . . . . . . . . . . . . . . . 161.9 Setting the Value of a Variable . . . . . . . . . . . . . . . . . . . . . . . . . . 171.9.1 Using set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171.9.2 Using setq . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181.9.3 Counting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191.10 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201.11 Exer ises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202 Pra ti ing Evaluation . . . . . . . . . . . . . . . . . . . . . 232.1 Bu�er Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232.2 Getting Bu�ers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252.3 Swit hing Bu�ers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262.4 Bu�er Size and the Lo ation of Point . . . . . . . . . . . . . . . . . . . . 272.5 Exer ise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

Page 8: An Introduction to Programming in Emacs Lisp

iv3 How To Write Fun tion De�nitions . . . . . . . . 293.1 The defun Spe ial Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293.2 Install a Fun tion De�nition . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313.2.1 Change a Fun tion De�nition . . . . . . . . . . . . . . . . . . . 323.3 Make a Fun tion Intera tive . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333.3.1 An Intera tive multiply-by-seven . . . . . . . . . . . . . 343.4 Di�erent Options for intera tive . . . . . . . . . . . . . . . . . . . . . . 353.5 Install Code Permanently . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363.6 let . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363.6.1 The Parts of a let Expression . . . . . . . . . . . . . . . . . . 373.6.2 Sample let Expression . . . . . . . . . . . . . . . . . . . . . . . . . 383.6.3 Uninitialized Variables in a let Statement . . . . . . . 393.7 The if Spe ial Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393.7.1 The type-of-animal Fun tion in Detail . . . . . . . . . 413.8 If{then{else Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423.9 Truth and Falsehood in Ema s Lisp . . . . . . . . . . . . . . . . . . . . . 433.10 save-ex ursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443.10.1 Template for a save-ex ursion Expression . . . . 453.11 Review . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 463.12 Exer ises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 504 A Few Bu�er{Related Fun tions . . . . . . . . . . . 514.1 Finding More Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 514.2 A Simpli�ed beginning-of-buffer De�nition . . . . . . . . . . . . 524.3 The De�nition of mark-whole-buffer . . . . . . . . . . . . . . . . . . . 544.3.1 Body of mark-whole-buffer . . . . . . . . . . . . . . . . . . . 554.4 The De�nition of append-to-buffer . . . . . . . . . . . . . . . . . . . . 564.4.1 The append-to-buffer Intera tive Expression . . . 574.4.2 The Body of append-to-buffer . . . . . . . . . . . . . . . . 574.4.3 save-ex ursion in append-to-buffer . . . . . . . . . . 584.5 Review . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 604.6 Exer ises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

Page 9: An Introduction to Programming in Emacs Lisp

v5 A Few More Complex Fun tions . . . . . . . . . . . 635.1 The De�nition of opy-to-buffer . . . . . . . . . . . . . . . . . . . . . . . 635.2 The De�nition of insert-buffer . . . . . . . . . . . . . . . . . . . . . . . . 645.2.1 The Intera tive Expression in insert-buffer . . . . 65A Read-only Bu�er . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65`b' in an Intera tive Expression . . . . . . . . . . . . . . . . . 655.2.2 The Body of the insert-buffer Fun tion . . . . . . . 655.2.3 insert-buffer With an if Instead of an or . . . . . 665.2.4 The or in the Body . . . . . . . . . . . . . . . . . . . . . . . . . . . . 675.2.5 The let Expression in insert-buffer . . . . . . . . . . 685.3 Complete De�nition of beginning-of-buffer . . . . . . . . . . . . 695.3.1 Optional Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . 705.3.2 beginning-of-buffer with an Argument . . . . . . . 71What happens in a large bu�er . . . . . . . . . . . . . . . . . 71What happens in a small bu�er . . . . . . . . . . . . . . . . 725.3.3 The Complete beginning-of-buffer . . . . . . . . . . . 735.4 Review . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 745.5 optional Argument Exer ise . . . . . . . . . . . . . . . . . . . . . . . . . . . 756 Narrowing and Widening. . . . . . . . . . . . . . . . . . 776.1 The save-restri tion Spe ial Form . . . . . . . . . . . . . . . . . . . . 776.2 what-line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 786.3 Exer ise with Narrowing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 797 ar, dr, ons: Fundamental Fun tions . . . . . 817.1 ar and dr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 817.2 ons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 837.2.1 Find the Length of a List: length . . . . . . . . . . . . . . 847.3 nth dr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 857.4 nth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 867.5 set ar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 877.6 set dr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 887.7 Exer ise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88

Page 10: An Introduction to Programming in Emacs Lisp

vi8 Cutting and Storing Text . . . . . . . . . . . . . . . . . 898.1 zap-to- har . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 908.1.1 The intera tive Expression . . . . . . . . . . . . . . . . . . . 908.1.2 The Body of zap-to- har. . . . . . . . . . . . . . . . . . . . . . 918.1.3 The sear h-forward Fun tion . . . . . . . . . . . . . . . . . 928.1.4 The progn Spe ial Form . . . . . . . . . . . . . . . . . . . . . . . 938.1.5 Summing up zap-to- har . . . . . . . . . . . . . . . . . . . . . 938.2 kill-region . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 948.2.1 ondition- ase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 958.2.2 delete-and-extra t-region . . . . . . . . . . . . . . . . . . 968.3 delete-and-extra t-region: Digressing into C . . . . . . . . . 988.4 Initializing a Variable with defvar . . . . . . . . . . . . . . . . . . . . . 1008.4.1 defvar and an asterisk . . . . . . . . . . . . . . . . . . . . . . . . 1018.5 opy-region-as-kill. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1028.5.1 The Body of opy-region-as-kill . . . . . . . . . . . . 103The kill-append fun tion . . . . . . . . . . . . . . . . . . . . 104The kill-new fun tion . . . . . . . . . . . . . . . . . . . . . . . 1058.6 Review . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1098.7 Sear hing Exer ises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1119 How Lists are Implemented . . . . . . . . . . . . . . 1139.1 Symbols as a Chest of Drawers . . . . . . . . . . . . . . . . . . . . . . . . . 1159.2 Exer ise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11610 Yanking Text Ba k . . . . . . . . . . . . . . . . . . . . . 11710.1 Kill Ring Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11710.2 The kill-ring-yank-pointer Variable . . . . . . . . . . . . . . . 11710.3 Exer ises with yank and nth dr . . . . . . . . . . . . . . . . . . . . . . . 11911 Loops and Re ursion. . . . . . . . . . . . . . . . . . . . 12111.1 while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12111.1.1 A while Loop and a List . . . . . . . . . . . . . . . . . . . . . 12211.1.2 An Example: print-elements-of-list . . . . . . 12311.1.3 A Loop with an In rementing Counter . . . . . . . . 124Example with in rementing ounter . . . . . . . . . . . 125The parts of the fun tion de�nition . . . . . . . . . . . . 126Putting the fun tion de�nition together . . . . . . . . 12711.1.4 Loop with a De rementing Counter . . . . . . . . . . . 129Example with de rementing ounter . . . . . . . . . . . 129The parts of the fun tion de�nition . . . . . . . . . . . . 130Putting the fun tion de�nition together . . . . . . . . 13011.2 Save your time: dolist and dotimes . . . . . . . . . . . . . . . . . . 131The dolist Ma ro . . . . . . . . . . . . . . . . . . . . . . . . . . . 132The dotimes Ma ro . . . . . . . . . . . . . . . . . . . . . . . . . . 133

Page 11: An Introduction to Programming in Emacs Lisp

vii11.3 Re ursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13411.3.1 Building Robots: Extending the Metaphor. . . . . 13411.3.2 The Parts of a Re ursive De�nition . . . . . . . . . . . 13511.3.3 Re ursion with a List . . . . . . . . . . . . . . . . . . . . . . . . 13611.3.4 Re ursion in Pla e of a Counter . . . . . . . . . . . . . . 137An argument of 3 or 4 . . . . . . . . . . . . . . . . . . . . . . . . 13811.3.5 Re ursion Example Using ond . . . . . . . . . . . . . . . 13911.3.6 Re ursive Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . 140Re ursive Pattern: every . . . . . . . . . . . . . . . . . . . . . 141Re ursive Pattern: a umulate . . . . . . . . . . . . . . . . 142Re ursive Pattern: keep . . . . . . . . . . . . . . . . . . . . . . 14311.3.7 Re ursion without Deferments . . . . . . . . . . . . . . . . 14311.3.8 No Deferment Solution . . . . . . . . . . . . . . . . . . . . . . . 14511.4 Looping Exer ise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14712 Regular Expression Sear hes . . . . . . . . . . . . 14912.1 The Regular Expression for senten e-end . . . . . . . . . . . . . 14912.2 The re-sear h-forward Fun tion. . . . . . . . . . . . . . . . . . . . . 15012.3 forward-senten e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151The while loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153The regular expression sear h . . . . . . . . . . . . . . . . . . . . . . . . 15412.4 forward-paragraph: a Goldmine of Fun tions . . . . . . . . . 155The let* expression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156The forward motion while loop . . . . . . . . . . . . . . . . . . . . . . 158Between paragraphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159Within paragraphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160No �ll pre�x . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160With a �ll pre�x . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16112.5 Create Your Own `TAGS' File . . . . . . . . . . . . . . . . . . . . . . . . . . 16312.6 Review . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16412.7 Exer ises with re-sear h-forward . . . . . . . . . . . . . . . . . . . . 16613 Counting: Repetition and Regexps . . . . . . 16713.1 The ount-words-region Fun tion . . . . . . . . . . . . . . . . . . . 16713.1.1 The Whitespa e Bug in ount-words-region . . 17013.2 Count Words Re ursively . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17313.3 Exer ise: Counting Pun tuation . . . . . . . . . . . . . . . . . . . . . . . 179

Page 12: An Introduction to Programming in Emacs Lisp

viii14 Counting Words in a defun . . . . . . . . . . . . . . 18114.1 What to Count? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18114.2 What Constitutes a Word or Symbol? . . . . . . . . . . . . . . . . . 18214.3 The ount-words-in-defun Fun tion . . . . . . . . . . . . . . . . . 18314.4 Count Several defuns Within a File . . . . . . . . . . . . . . . . . . . 18614.5 Find a File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18714.6 lengths-list-file in Detail . . . . . . . . . . . . . . . . . . . . . . . . . 18814.7 Count Words in defuns in Di�erent Files . . . . . . . . . . . . . . 19014.7.1 The append Fun tion . . . . . . . . . . . . . . . . . . . . . . . . 19114.8 Re ursively Count Words in Di�erent Files . . . . . . . . . . . . . 19214.9 Prepare the Data for Display in a Graph . . . . . . . . . . . . . . . 19314.9.1 Sorting Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19314.9.2 Making a List of Files . . . . . . . . . . . . . . . . . . . . . . . . 19414.9.3 Counting fun tion de�nitions . . . . . . . . . . . . . . . . . 19715 Readying a Graph . . . . . . . . . . . . . . . . . . . . . . 20315.1 The graph-body-print Fun tion . . . . . . . . . . . . . . . . . . . . . . 20815.2 The re ursive-graph-body-print Fun tion. . . . . . . . . . . 21015.3 Need for Printed Axes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21215.4 Exer ise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21216 Your `.ema s' File . . . . . . . . . . . . . . . . . . . . . . . 21316.1 Site-wide Initialization Files . . . . . . . . . . . . . . . . . . . . . . . . . . . 21316.2 Spe ifying Variables using def ustom . . . . . . . . . . . . . . . . . . 21416.3 Beginning a `.ema s' File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21616.4 Text and Auto Fill Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21716.5 Mail Aliases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21916.6 Indent Tabs Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21916.7 Some Keybindings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22016.8 Keymaps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22116.9 Loading Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22216.10 Autoloading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22316.11 A Simple Extension: line-to-top-of-window . . . . . . . . 22416.12 X11 Colors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22616.13 Mis ellaneous Settings for a `.ema s' File . . . . . . . . . . . . . 22716.14 A Modi�ed Mode Line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22817 Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23117.1 debug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23117.2 debug-on-entry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23217.3 debug-on-quit and (debug) . . . . . . . . . . . . . . . . . . . . . . . . . . 23417.4 The edebug Sour e Level Debugger . . . . . . . . . . . . . . . . . . . . 23517.5 Debugging Exer ises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237

Page 13: An Introduction to Programming in Emacs Lisp

ix18 Con lusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239Appendix A The the-the Fun tion . . . . . . . . . . 241Appendix B Handling the Kill Ring . . . . . . . . 243B.1 The rotate-yank-pointer Fun tion . . . . . . . . . . . . . . . . . . . 243B.1.1 The Body of rotate-yank-pointer . . . . . . . . . . . 244The else-part of the if expression . . . . . . . . . . . . . 245The % remainder fun tion . . . . . . . . . . . . . . . . . . . . . 247Using % in rotate-yank-pointer . . . . . . . . . . . . . 248Pointing to the last element . . . . . . . . . . . . . . . . . . . 248B.2 yank . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249Passing the argument . . . . . . . . . . . . . . . . . . . . . . . . 250Passing a negative argument . . . . . . . . . . . . . . . . . . 251B.3 yank-pop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252Appendix C A Graph with Labelled Axes . . . 255C.1 The print-graph Varlist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256C.2 The print-Y-axis Fun tion . . . . . . . . . . . . . . . . . . . . . . . . . . . 256C.2.1 Side Trip: Compute a Remainder . . . . . . . . . . . . . . 258C.2.2 Constru t a Y Axis Element . . . . . . . . . . . . . . . . . . 259C.2.3 Create a Y Axis Column . . . . . . . . . . . . . . . . . . . . . . 261C.2.4 The Not Quite Final Version of print-Y-axis . . 262C.3 The print-X-axis Fun tion . . . . . . . . . . . . . . . . . . . . . . . . . . . 263C.3.1 X Axis Ti Marks . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263C.4 Printing the Whole Graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267C.4.1 Testing print-graph . . . . . . . . . . . . . . . . . . . . . . . . . 270C.4.2 Graphing Numbers of Words and Symbols . . . . . 271C.4.3 A lambda Expression: Useful Anonymity . . . . . . . 272C.4.4 The map ar Fun tion . . . . . . . . . . . . . . . . . . . . . . . . . 274C.4.5 Another Bug . . . Most Insidious . . . . . . . . . . . . . . 274C.4.6 The Printed Graph . . . . . . . . . . . . . . . . . . . . . . . . . . . 277Appendix D GNU Free Do umentation Li ense. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287

Page 14: An Introduction to Programming in Emacs Lisp

x

Page 15: An Introduction to Programming in Emacs Lisp

On Reading this Text xiPrefa eMost of the GNU Ema s integrated environment is written in the pro-gramming language alled Ema s Lisp. The ode written in this program-ming language is the software|the sets of instru tions|that tell the om-puter what to do when you give it ommands. Ema s is designed so thatyou an write new ode in Ema s Lisp and easily install it as an extensionto the editor.(GNU Ema s is sometimes alled an \extensible editor", but it does mu hmore than provide editing apabilities. It is better to refer to Ema s asan \extensible omputing environment". However, that phrase is quite amouthful. It is easier to refer to Ema s simply as an editor. Moreover,everything you do in Ema s|�nd the Mayan date and phases of the moon,simplify polynomials, debug ode, manage �les, read letters, write books|allthese a tivities are kinds of editing in the most general sense of the word.)Although Ema s Lisp is usually thought of in asso iation only withEma s, it is a full omputer programming language. You an use Ema sLisp as you would any other programming language.Perhaps you want to understand programming; perhaps you want to ex-tend Ema s; or perhaps you want to be ome a programmer. This introdu -tion to Ema s Lisp is designed to get you started: to guide you in learningthe fundamentals of programming, and more importantly, to show you howyou an tea h yourself to go further.On Reading this TextAll through this do ument, you will see little sample programs you anrun inside of Ema s. If you read this do ument in Info inside of GNUEma s, you an run the programs as they appear. (This is easy to do andis explained when the examples are presented.) Alternatively, you an readthis introdu tion as a printed book while sitting beside a omputer runningEma s. (This is what I like to do; I like printed books.) If you don't have arunning Ema s beside you, you an still read this book, but in this ase, itis best to treat it as a novel or as a travel guide to a ountry not yet visited:interesting, but not the same as being there.Mu h of this introdu tion is dedi ated to walk-throughs or guided toursof ode used in GNU Ema s. These tours are designed for two purposes:�rst, to give you familiarity with real, working ode ( ode you use everyday); and, se ond, to give you familiarity with the way Ema s works. It isinteresting to see how a working environment is implemented. Also, I hopethat you will pi k up the habit of browsing through sour e ode. You anlearn from it and mine it for ideas. Having GNU Ema s is like having adragon's ave of treasures.In addition to learning about Ema s as an editor and Ema s Lisp asa programming language, the examples and guided tours will give you an

Page 16: An Introduction to Programming in Emacs Lisp

xii Prefa eopportunity to get a quainted with Ema s as a Lisp programming environ-ment. GNU Ema s supports programming and provides tools that you willwant to be ome omfortable using, su h as M-. (the key whi h invokes thefind-tag ommand). You will also learn about bu�ers and other obje tsthat are part of the environment. Learning about these features of Ema s islike learning new routes around your home town.Finally, I hope to onvey some of the skills for using Ema s to learnaspe ts of programming that you don't know. You an often use Ema s tohelp you understand what puzzles you or to �nd out how to do somethingnew. This self-relian e is not only a pleasure, but an advantage.For Whom This is WrittenThis text is written as an elementary introdu tion for people who are notprogrammers. If you are a programmer, you may not be satis�ed with thisprimer. The reason is that you may have be ome expert at reading referen emanuals and be put o� by the way this text is organized.An expert programmer who reviewed this text said to me:I prefer to learn from referen e manuals. I \dive into" ea h para-graph, and \ ome up for air" between paragraphs.When I get to the end of a paragraph, I assume that that subje tis done, �nished, that I know everything I need (with the possibleex eption of the ase when the next paragraph starts talking aboutit in more detail). I expe t that a well written referen e manualwill not have a lot of redundan y, and that it will have ex ellentpointers to the (one) pla e where the information I want is.This introdu tion is not written for this person!Firstly, I try to say everything at least three times: �rst, to introdu e it;se ond, to show it in ontext; and third, to show it in a di�erent ontext, orto review it.Se ondly, I hardly ever put all the information about a subje t in onepla e, mu h less in one paragraph. To my way of thinking, that imposestoo heavy a burden on the reader. Instead I try to explain only what youneed to know at the time. (Sometimes I in lude a little extra informationso you won't be surprised later when the additional information is formallyintrodu ed.)When you read this text, you are not expe ted to learn everything the �rsttime. Frequently, you need only make, as it were, a `nodding a quaintan e'with some of the items mentioned. My hope is that I have stru tured thetext and given you enough hints that you will be alert to what is important,and on entrate on it.You will need to \dive into" some paragraphs; there is no other way toread them. But I have tried to keep down the number of su h paragraphs.

Page 17: An Introduction to Programming in Emacs Lisp

A Note for Novi es xiiiThis book is intended as an approa hable hill, rather than as a dauntingmountain.This introdu tion to Programming in Ema s Lisp has a ompanion do -ument, The GNU Ema s Lisp Referen e Manual. The referen e manual hasmore detail than this introdu tion. In the referen e manual, all the infor-mation about one topi is on entrated in one pla e. You should turn to itif you are like the programmer quoted above. And, of ourse, after you haveread this Introdu tion, you will �nd the Referen e Manual useful when youare writing your own programs.Lisp HistoryLisp was �rst developed in the late 1950s at the Massa husetts Instituteof Te hnology for resear h in arti� ial intelligen e. The great power of theLisp language makes it superior for other purposes as well, su h as writingeditor ommands and integrated environments.GNU Ema s Lisp is largely inspired by Ma lisp, whi h was written atMIT in the 1960s. It is somewhat inspired by Common Lisp, whi h be amea standard in the 1980s. However, Ema s Lisp is mu h simpler than CommonLisp. (The standard Ema s distribution ontains an optional extensions �le,` l.el', that adds many Common Lisp features to Ema s Lisp.)A Note for Novi esIf you don't know GNU Ema s, you an still read this do ument prof-itably. However, I re ommend you learn Ema s, if only to learn to movearound your omputer s reen. You an tea h yourself how to use Ema swith the on-line tutorial. To use it, type C-h t. (This means you press andrelease the hCTRLi key and the h at the same time, and then press and releaset.) Also, I often refer to one of Ema s' standard ommands by listing thekeys whi h you press to invoke the ommand and then giving the name ofthe ommand in parentheses, like this: M-C-\ (indent-region). What thismeans is that the indent-region ommand is ustomarily invoked by typingM-C-\. (You an, if you wish, hange the keys that are typed to invoke the ommand; this is alled rebinding. See Se tion 16.8, \Keymaps", page 221.)The abbreviation M-C-\ means that you type your hMETAi key, hCTRLi keyand h\i key all at the same time. (On many modern keyboards the hMETAikey is labelled hALTi.) Sometimes a ombination like this is alled a key hord,sin e it is similar to the way you play a hord on a piano. If your keyboarddoes not have a hMETAi key, the hESCi key pre�x is used in pla e of it. Inthis ase, M-C-\ means that you press and release your hESCi key and thentype the hCTRLi key and the h\i key at the same time. But usually M-C-\means press the hCTRLi key along with the key that is labelled hALTi and, atthe same time, press the h\i key.

Page 18: An Introduction to Programming in Emacs Lisp

xiv Prefa eIn addition to typing a lone key hord, you an pre�x what you type withC-u, whi h is alled the `universal argument'. The C-u key hord passes anargument to the subsequent ommand. Thus, to indent a region of plaintext by 6 spa es, mark the region, and then type C-u 6 M-C-\. (If you donot spe ify a number, Ema s either passes the number 4 to the ommandor otherwise runs the ommand di�erently than it would otherwise.) Seese tion \Numeri Arguments" in The GNU Ema s Manual.If you are reading this in Info using GNU Ema s, you an read throughthis whole do ument just by pressing the spa e bar, hSPCi. (To learn aboutInfo, type C-h i and then sele t Info.)A note on terminology: when I use the word Lisp alone, I often amreferring to the various diale ts of Lisp in general, but when I speak ofEma s Lisp, I am referring to GNU Ema s Lisp in parti ular.Thank YouMy thanks to all who helped me with this book. My espe ial thanks toJim Blandy, Noah Friedman, Jim Kingdon, Roland M Grath, Frank Ritter,Randy Smith, Ri hard M. Stallman, and Melissa Weisshaus. My thanksalso go to both Philip Johnson and David Stampe for their patient en our-agement. My mistakes are my own. Robert J. Chassell

Page 19: An Introduction to Programming in Emacs Lisp

Lisp Atoms 11 List Pro essingTo the untutored eye, Lisp is a strange programming language. In Lisp ode there are parentheses everywhere. Some people even laim that thename stands for `Lots of Isolated Silly Parentheses'. But the laim is un-warranted. Lisp stands for LISt Pro essing, and the programming languagehandles lists (and lists of lists) by putting them between parentheses. Theparentheses mark the boundaries of the list. Sometimes a list is pre eded bya single apostrophe or quotation mark, `''. Lists are the basis of Lisp.1.1 Lisp ListsIn Lisp, a list looks like this: '(rose violet daisy butter up). Thislist is pre eded by a single apostrophe. It ould just as well be written asfollows, whi h looks more like the kind of list you are likely to be familiarwith:'(rosevioletdaisybutter up)The elements of this list are the names of the four di�erent owers, separatedfrom ea h other by whitespa e and surrounded by parentheses, like owersin a �eld with a stone wall around them.Lists an also have numbers in them, as in this list: (+ 2 2). This listhas a plus-sign, `+', followed by two `2's, ea h separated by whitespa e.In Lisp, both data and programs are represented the same way; that is,they are both lists of words, numbers, or other lists, separated by white-spa e and surrounded by parentheses. (Sin e a program looks like data, oneprogram may easily serve as data for another; this is a very powerful featureof Lisp.) (In identally, these two parentheti al remarks are not Lisp lists,be ause they ontain `;' and `.' as pun tuation marks.)Here is another list, this time with a list inside of it:'(this list has (a list inside of it))The omponents of this list are the words `this', `list', `has', and thelist `(a list inside of it)'. The interior list is made up of the words `a',`list', `inside', `of', `it'.1.1.1 Lisp AtomsIn Lisp, what we have been alling words are alled atoms. This term omes from the histori al meaning of the word atom, whi h means `indivis-ible'. As far as Lisp is on erned, the words we have been using in the lists annot be divided into any smaller parts and still mean the same thing aspart of a program; likewise with numbers and single hara ter symbols like

Page 20: An Introduction to Programming in Emacs Lisp

2 Chapter 1: List Pro essing`+'. On the other hand, unlike an atom, a list an be split into parts. (SeeChapter 7, \ ar dr & ons Fundamental Fun tions", page 81.)In a list, atoms are separated from ea h other by whitespa e. They anbe right next to a parenthesis.Te hni ally speaking, a list in Lisp onsists of parentheses surroundingatoms separated by whitespa e or surrounding other lists or surroundingboth atoms and other lists. A list an have just one atom in it or havenothing in it at all. A list with nothing in it looks like this: (), and is alledthe empty list. Unlike anything else, an empty list is onsidered both anatom and a list at the same time.The printed representation of both atoms and lists are alled symboli expressions or, more on isely, s-expressions. The word expression by itself an refer to either the printed representation, or to the atom or list as itis held internally in the omputer. Often, people use the term expressionindis riminately. (Also, in many texts, the word form is used as a synonymfor expression.)In identally, the atoms that make up our universe were named su h whenthey were thought to be indivisible; but it has been found that physi al atomsare not indivisible. Parts an split o� an atom or it an �ssion into two partsof roughly equal size. Physi al atoms were named prematurely, before theirtruer nature was found. In Lisp, ertain kinds of atom, su h as an array, anbe separated into parts; but the me hanism for doing this is di�erent fromthe me hanism for splitting a list. As far as list operations are on erned,the atoms of a list are unsplittable.As in English, the meanings of the omponent letters of a Lisp atom aredi�erent from the meaning the letters make as a word. For example, theword for the South Ameri an sloth, the `ai', is ompletely di�erent from thetwo words, `a', and `i'.There are many kinds of atom in nature but only a few in Lisp: forexample, numbers, su h as 37, 511, or 1729, and symbols, su h as `+', `foo',or `forward-line'. The words we have listed in the examples above areall symbols. In everyday Lisp onversation, the word \atom" is not oftenused, be ause programmers usually try to be more spe i� about what kindof atom they are dealing with. Lisp programming is mostly about symbols(and sometimes numbers) within lists. (In identally, the pre eding threeword parentheti al remark is a proper list in Lisp, sin e it onsists of atoms,whi h in this ase are symbols, separated by whitespa e and en losed byparentheses, without any non-Lisp pun tuation.)

Page 21: An Introduction to Programming in Emacs Lisp

GNU Ema s Helps You Type Lists 3In addition, text between double quotation marks|even senten es orparagraphs|is an atom. Here is an example:'(this list in ludes "text between quotation marks.")In Lisp, all of the quoted text in luding the pun tuation mark and the blankspa es is a single atom. This kind of atom is alled a string (for `stringof hara ters') and is the sort of thing that is used for messages that a omputer an print for a human to read. Strings are a di�erent kind of atomthan numbers or symbols and are used di�erently.1.1.2 Whitespa e in ListsThe amount of whitespa e in a list does not matter. From the point ofview of the Lisp language,'(this listlooks like this)is exa tly the same as this:'(this list looks like this)Both examples show what to Lisp is the same list, the list made up ofthe symbols `this', `list', `looks', `like', and `this' in that order.Extra whitespa e and newlines are designed to make a list more readableby humans. When Lisp reads the expression, it gets rid of all the extrawhitespa e (but it needs to have at least one spa e between atoms in orderto tell them apart.)Odd as it seems, the examples we have seen over almost all of whatLisp lists look like! Every other list in Lisp looks more or less like one ofthese examples, ex ept that the list may be longer and more omplex. Inbrief, a list is between parentheses, a string is between quotation marks, asymbol looks like a word, and a number looks like a number. (For ertainsituations, square bra kets, dots and a few other spe ial hara ters may beused; however, we will go quite far without them.)1.1.3 GNU Ema s Helps You Type ListsWhen you type a Lisp expression in GNU Ema s using either Lisp Intera -tion mode or Ema s Lisp mode, you have available to you several ommandsto format the Lisp expression so it is easy to read. For example, pressingthe hTABi key automati ally indents the line the ursor is on by the rightamount. A ommand to properly indent the ode in a region is ustomarilybound to M-C-\. Indentation is designed so that you an see whi h elementsof a list belongs to whi h list|elements of a sub-list are indented more thanthe elements of the en losing list.In addition, when you type a losing parenthesis, Ema s momentarilyjumps the ursor ba k to the mat hing opening parenthesis, so you an seewhi h one it is. This is very useful, sin e every list you type in Lisp must have

Page 22: An Introduction to Programming in Emacs Lisp

4 Chapter 1: List Pro essingits losing parenthesis mat h its opening parenthesis. (See se tion \MajorModes" in The GNU Ema s Manual, for more information about Ema s'modes.)1.2 Run a ProgramA list in Lisp|any list|is a program ready to run. If you run it (forwhi h the Lisp jargon is evaluate), the omputer will do one of three things:do nothing ex ept return to you the list itself; send you an error message; or,treat the �rst symbol in the list as a ommand to do something. (Usually,of ourse, it is the last of these three things that you really want!)The single apostrophe, ', that I put in front of some of the example listsin pre eding se tions is alled a quote; when it pre edes a list, it tells Lispto do nothing with the list, other than take it as it is written. But if there isno quote pre eding a list, the �rst item of the list is spe ial: it is a ommandfor the omputer to obey. (In Lisp, these ommands are alled fun tions.)The list (+ 2 2) shown above did not have a quote in front of it, so Lispunderstands that the + is an instru tion to do something with the rest of thelist: add the numbers that follow.If you are reading this inside of GNU Ema s in Info, here is how you an evaluate su h a list: pla e your ursor immediately after the right handparenthesis of the following list and then type C-x C-e:(+ 2 2)You will see the number 4 appear in the e ho area. (In the jargon, what youhave just done is \evaluate the list." The e ho area is the line at the bottomof the s reen that displays or \e hoes" text.) Now try the same thing with aquoted list: pla e the ursor right after the following list and type C-x C-e:'(this is a quoted list)You will see (this is a quoted list) appear in the e ho area.In both ases, what you are doing is giving a ommand to the programinside of GNU Ema s alled the Lisp interpreter|giving the interpreter a ommand to evaluate the expression. The name of the Lisp interpreter omesfrom the word for the task done by a human who omes up with the meaningof an expression|who \interprets" it.You an also evaluate an atom that is not part of a list|one that is notsurrounded by parentheses; again, the Lisp interpreter translates from thehumanly readable expression to the language of the omputer. But beforedis ussing this (see Se tion 1.7, \Variables", page 10), we will dis uss whatthe Lisp interpreter does when you make an error.1.3 Generate an Error MessagePartly so you won't worry if you do it a identally, we will now give a ommand to the Lisp interpreter that generates an error message. This is a

Page 23: An Introduction to Programming in Emacs Lisp

Generate an Error Message 5harmless a tivity; and indeed, we will often try to generate error messagesintentionally. On e you understand the jargon, error messages an be in-formative. Instead of being alled \error" messages, they should be alled\help" messages. They are like signposts to a traveller in a strange ountry;de iphering them an be hard, but on e understood, they an point the way.The error message is generated by a built-in GNU Ema s debugger. Wewill `enter the debugger'. You get out of the debugger by typing q.What we will do is evaluate a list that is not quoted and does not havea meaningful ommand as its �rst element. Here is a list almost exa tly thesame as the one we just used, but without the single-quote in front of it.Position the ursor right after it and type C-x C-e:(this is an unquoted list)What you see depends on whi h version of Ema s you are running. GNUEma s version 21 provides more information than version 20 and before.First, the more re ent result of generating an error; then the earlier, version20 result.In GNU Ema s version 21, a `*Ba ktra e*' window will open up and youwill see the following in it:---------- Buffer: *Ba ktra e* ----------Debugger entered--Lisp error: (void-fun tion this)(this is an unquoted list)eval((this is an unquoted list))eval-last-sexp-1(nil)eval-last-sexp(nil) all-intera tively(eval-last-sexp)---------- Buffer: *Ba ktra e* ----------Your ursor will be in this window (you may have to wait a few se ondsbefore it be omes visible). To quit the debugger and make the debuggerwindow go away, type:qPlease type q right now, so you be ome on�dent that you an get out ofthe debugger. Then, type C-x C-e again to re-enter it.Based on what we already know, we an almost read this error message.You read the `*Ba ktra e*' bu�er from the bottom up; it tells you whatEma s did. When you typed C-x C-e, you made an intera tive all to the ommand eval-last-sexp. eval is an abbreviation for `evaluate' and sexpis an abbreviation for `symboli expression'. The ommand means `evaluatelast symboli expression', whi h is the expression just before your ursor.Ea h line above tells you what the Lisp interpreter evaluated next. Themost re ent a tion is at the top. The bu�er is alled the `*Ba ktra e*'bu�er be ause it enables you to tra k Ema s ba kwards.

Page 24: An Introduction to Programming in Emacs Lisp

6 Chapter 1: List Pro essingAt the top of the `*Ba ktra e*' bu�er, you see the line:Debugger entered--Lisp error: (void-fun tion this)The Lisp interpreter tried to evaluate the �rst atom of the list, the word`this'. It is this a tion that generated the error message `void-fun tionthis'.The message ontains the words `void-fun tion' and `this'.The word `fun tion' was mentioned on e before. It is a very importantword. For our purposes, we an de�ne it by saying that a fun tion is a setof instru tions to the omputer that tell the omputer to do something.Now we an begin to understand the error message: `void-fun tionthis'. The fun tion (that is, the word `this') does not have a de�nition ofany set of instru tions for the omputer to arry out.The slightly odd word, `void-fun tion', is designed to over the wayEma s Lisp is implemented, whi h is that when a symbol does not have afun tion de�nition atta hed to it, the pla e that should ontain the instru -tions is `void'.On the other hand, sin e we were able to add 2 plus 2 su essfully, byevaluating (+ 2 2), we an infer that the symbol + must have a set of in-stru tions for the omputer to obey and those instru tions must be to addthe numbers that follow the +.In GNU Ema s version 20, and in earlier versions, you will see only oneline of error message; it will appear in the e ho area and look like this:Symbol's fun tion definition is void: this(Also, your terminal may beep at you|some do, some don't; and othersblink. This is just a devi e to get your attention.) The message goes awayas soon as you type another key, even just to move the ursor.We know the meaning of the word `Symbol'. It refers to the �rst atom ofthe list, the word `this'. The word `fun tion' refers to the instru tions thattell the omputer what to do. (Te hni ally, the symbol tells the omputerwhere to �nd the instru tions, but this is a ompli ation we an ignore forthe moment.)The error message an be understood: `Symbol's fun tion definitionis void: this'. The symbol (that is, the word `this') la ks instru tions forthe omputer to arry out.1.4 Symbol Names and Fun tion De�nitionsWe an arti ulate another hara teristi of Lisp based on what we havedis ussed so far|an important hara teristi : a symbol, like +, is not itselfthe set of instru tions for the omputer to arry out. Instead, the symbolis used, perhaps temporarily, as a way of lo ating the de�nition or set ofinstru tions. What we see is the name through whi h the instru tions anbe found. Names of people work the same way. I an be referred to as

Page 25: An Introduction to Programming in Emacs Lisp

The Lisp Interpreter 7`Bob'; however, I am not the letters `B', `o', `b' but am the ons iousness onsistently asso iated with a parti ular life-form. The name is not me, butit an be used to refer to me.In Lisp, one set of instru tions an be atta hed to several names. Forexample, the omputer instru tions for adding numbers an be linked to thesymbol plus as well as to the symbol + (and are in some diale ts of Lisp).Among humans, I an be referred to as `Robert' as well as `Bob' and byother words as well.On the other hand, a symbol an have only one fun tion de�nition at-ta hed to it at a time. Otherwise, the omputer would be onfused as towhi h de�nition to use. If this were the ase among people, only one personin the world ould be named `Bob'. However, the fun tion de�nition to whi hthe name refers an be hanged readily. (See Se tion 3.2, \Install a Fun tionDe�nition", page 31.)Sin e Ema s Lisp is large, it is ustomary to name symbols in a way thatidenti�es the part of Ema s to whi h the fun tion belongs. Thus, all thenames for fun tions that deal with Texinfo start with `texinfo-' and thosefor fun tions that deal with reading mail start with `rmail-'.1.5 The Lisp InterpreterBased on what we have seen, we an now start to �gure out what the Lispinterpreter does when we ommand it to evaluate a list. First, it looks to seewhether there is a quote before the list; if there is, the interpreter just givesus the list. On the other hand, if there is no quote, the interpreter looks atthe �rst element in the list and sees whether it has a fun tion de�nition. Ifit does, the interpreter arries out the instru tions in the fun tion de�nition.Otherwise, the interpreter prints an error message.This is how Lisp works. Simple. There are added ompli ations whi hwe will get to in a minute, but these are the fundamentals. Of ourse, towrite Lisp programs, you need to know how to write fun tion de�nitions andatta h them to names, and how to do this without onfusing either yourselfor the omputer.Now, for the �rst ompli ation. In addition to lists, the Lisp interpreter an evaluate a symbol that is not quoted and does not have parenthesesaround it. The Lisp interpreter will attempt to determine the symbol'svalue as a variable. This situation is des ribed in the se tion on variables.(See Se tion 1.7, \Variables", page 10.)The se ond ompli ation o urs be ause some fun tions are unusual anddo not work in the usual manner. Those that don't are alled spe ial forms.They are used for spe ial jobs, like de�ning a fun tion, and there are notmany of them. In the next few hapters, you will be introdu ed to severalof the more important spe ial forms.

Page 26: An Introduction to Programming in Emacs Lisp

8 Chapter 1: List Pro essingThe third and �nal ompli ation is this: if the fun tion that the Lispinterpreter is looking at is not a spe ial form, and if it is part of a list, theLisp interpreter looks to see whether the list has a list inside of it. If thereis an inner list, the Lisp interpreter �rst �gures out what it should do withthe inside list, and then it works on the outside list. If there is yet anotherlist embedded inside the inner list, it works on that one �rst, and so on.It always works on the innermost list �rst. The interpreter works on theinnermost list �rst, to evaluate the result of that list. The result may beused by the en losing expression.Otherwise, the interpreter works left to right, from one expression to thenext.1.5.1 Byte CompilingOne other aspe t of interpreting: the Lisp interpreter is able to interprettwo kinds of entity: humanly readable ode, on whi h we will fo us ex lu-sively, and spe ially pro essed ode, alled byte ompiled ode, whi h is nothumanly readable. Byte ompiled ode runs faster than humanly readable ode.You an transform humanly readable ode into byte ompiled ode byrunning one of the ompile ommands su h as byte- ompile-file. Byte ompiled ode is usually stored in a �le that ends with a `.el ' exten-sion rather than a `.el' extension. You will see both kinds of �le in the`ema s/lisp' dire tory; the �les to read are those with `.el' extensions.As a pra ti al matter, for most things you might do to ustomize orextend Ema s, you do not need to byte ompile; and I will not dis ussthe topi here. See se tion \Byte Compilation" in The GNU Ema s LispReferen e Manual, for a full des ription of byte ompilation.1.6 EvaluationWhen the Lisp interpreter works on an expression, the term for the a -tivity is alled evaluation. We say that the interpreter `evaluates the expres-sion'. I've used this term several times before. The word omes from itsuse in everyday language, `to as ertain the value or amount of; to appraise',a ording to Webster's New Collegiate Di tionary.After evaluating an expression, the Lisp interpreter will most likely returnthe value that the omputer produ es by arrying out the instru tions itfound in the fun tion de�nition, or perhaps it will give up on that fun tionand produ e an error message. (The interpreter may also �nd itself tossed,so to speak, to a di�erent fun tion or it may attempt to repeat ontinuallywhat it is doing for ever and ever in what is alled an `in�nite loop'. Thesea tions are less ommon; and we an ignore them.) Most frequently, theinterpreter returns a value.

Page 27: An Introduction to Programming in Emacs Lisp

Evaluating Inner Lists 9At the same time the interpreter returns a value, it may do somethingelse as well, su h as move a ursor or opy a �le; this other kind of a tionis alled a side e�e t. A tions that we humans think are important, su h asprinting results, are often \side e�e ts" to the Lisp interpreter. The jargon an sound pe uliar, but it turns out that it is fairly easy to learn to use sidee�e ts.In summary, evaluating a symboli expression most ommonly auses theLisp interpreter to return a value and perhaps arry out a side e�e t; or elseprodu e an error.1.6.1 Evaluating Inner ListsIf evaluation applies to a list that is inside another list, the outer list mayuse the value returned by the �rst evaluation as information when the outerlist is evaluated. This explains why inner expressions are evaluated �rst: thevalues they return are used by the outer expressions.We an investigate this pro ess by evaluating another addition example.Pla e your ursor after the following expression and type C-x C-e:(+ 2 (+ 3 3))The number 8 will appear in the e ho area.What happens is that the Lisp interpreter �rst evaluates the inner ex-pression, (+ 3 3), for whi h the value 6 is returned; then it evaluates theouter expression as if it were written (+ 2 6), whi h returns the value 8.Sin e there are no more en losing expressions to evaluate, the interpreterprints that value in the e ho area.Now it is easy to understand the name of the ommand invoked by thekeystrokes C-x C-e: the name is eval-last-sexp. The letters sexp arean abbreviation for `symboli expression', and eval is an abbreviation for`evaluate'. The ommand means `evaluate last symboli expression'.As an experiment, you an try evaluating the expression by putting the ursor at the beginning of the next line immediately following the expression,or inside the expression.Here is another opy of the expression:(+ 2 (+ 3 3))If you pla e the ursor at the beginning of the blank line that immediatelyfollows the expression and type C-x C-e, you will still get the value 8 printedin the e ho area. Now try putting the ursor inside the expression. If youput it right after the next to last parenthesis (so it appears to sit on topof the last parenthesis), you will get a 6 printed in the e ho area! This isbe ause the ommand evaluates the expression (+ 3 3).Now put the ursor immediately after a number. Type C-x C-e and youwill get the number itself. In Lisp, if you evaluate a number, you get thenumber itself|this is how numbers di�er from symbols. If you evaluate alist starting with a symbol like +, you will get a value returned that is the

Page 28: An Introduction to Programming in Emacs Lisp

10 Chapter 1: List Pro essingresult of the omputer arrying out the instru tions in the fun tion de�nitionatta hed to that name. If a symbol by itself is evaluated, something di�erenthappens, as we will see in the next se tion.1.7 VariablesIn Ema s Lisp, a symbol an have a value atta hed to it just as it anhave a fun tion de�nition atta hed to it. The two are di�erent. The fun tionde�nition is a set of instru tions that a omputer will obey. A value, on theother hand, is something, su h as number or a name, that an vary (whi his why su h a symbol is alled a variable). The value of a symbol an be anyexpression in Lisp, su h as a symbol, number, list, or string. A symbol thathas a value is often alled a variable.A symbol an have both a fun tion de�nition and a value atta hed to itat the same time. Or it an have just one or the other. The two are separate.This is somewhat similar to the way the name Cambridge an refer to the ity in Massa husetts and have some information atta hed to the name aswell, su h as \great programming enter".Another way to think about this is to imagine a symbol as being a hest ofdrawers. The fun tion de�nition is put in one drawer, the value in another,and so on. What is put in the drawer holding the value an be hangedwithout a�e ting the ontents of the drawer holding the fun tion de�nition,and vi e-versa.The variable fill- olumn illustrates a symbol with a value atta hed toit: in every GNU Ema s bu�er, this symbol is set to some value, usually 72or 70, but sometimes to some other value. To �nd the value of this symbol,evaluate it by itself. If you are reading this in Info inside of GNU Ema s,you an do this by putting the ursor after the symbol and typing C-x C-e:fill- olumnAfter I typed C-x C-e, Ema s printed the number 72 in my e ho area. Thisis the value for whi h fill- olumn is set for me as I write this. It maybe di�erent for you in your Info bu�er. Noti e that the value returned asa variable is printed in exa tly the same way as the value returned by afun tion arrying out its instru tions. From the point of view of the Lispinterpreter, a value returned is a value returned. What kind of expression it ame from eases to matter on e the value is known.A symbol an have any value atta hed to it or, to use the jargon, we anbind the variable to a value: to a number, su h as 72; to a string, "su h asthis"; to a list, su h as (spru e pine oak); we an even bind a variable toa fun tion de�nition.A symbol an be bound to a value in several ways. See Se tion 1.9,\Setting the Value of a Variable", page 17, for information about one wayto do this.

Page 29: An Introduction to Programming in Emacs Lisp

Error Message for a Symbol Without a Value 111.7.1 Error Message for a Symbol Without a Fun tionWhen we evaluated fill- olumn to �nd its value as a variable, we didnot pla e parentheses around the word. This is be ause we did not intendto use it as a fun tion name.If fill- olumnwere the �rst or only element of a list, the Lisp interpreterwould attempt to �nd the fun tion de�nition atta hed to it. But fill- olumn has no fun tion de�nition. Try evaluating this:(fill- olumn)In GNU Ema s version 21, you will reate a `*Ba ktra e*' bu�er that says:---------- Buffer: *Ba ktra e* ----------Debugger entered--Lisp error: (void-fun tion fill- olumn)(fill- olumn)eval((fill- olumn))eval-last-sexp-1(nil)eval-last-sexp(nil) all-intera tively(eval-last-sexp)---------- Buffer: *Ba ktra e* ----------(Remember, to quit the debugger and make the debugger window go away,type q in the `*Ba ktra e*' bu�er.)In GNU Ema s 20 and before, you will produ e an error message thatsays:Symbol's fun tion definition is void: fill- olumn(The message will go away away as soon as you move the ursor or typeanother key.)1.7.2 Error Message for a Symbol Without a ValueIf you attempt to evaluate a symbol that does not have a value boundto it, you will re eive an error message. You an see this by experimentingwith our 2 plus 2 addition. In the following expression, put your ursor rightafter the +, before the �rst number 2, type C-x C-e:(+ 2 2)In GNU Ema s 21, you will reate a `*Ba ktra e*' bu�er that says:---------- Buffer: *Ba ktra e* ----------Debugger entered--Lisp error: (void-variable +)eval(+)eval-last-sexp-1(nil)eval-last-sexp(nil) all-intera tively(eval-last-sexp)---------- Buffer: *Ba ktra e* ----------(As with the other times we entered the debugger, you an quit by typing qin the `*Ba ktra e*' bu�er.)

Page 30: An Introduction to Programming in Emacs Lisp

12 Chapter 1: List Pro essingThis ba ktra e is di�erent from the very �rst error message we saw,whi h said, `Debugger entered--Lisp error: (void-fun tion this)'. Inthis ase, the fun tion does not have a value as a variable; while in the othererror message, the fun tion (the word `this') did not have a de�nition.In this experiment with the +, what we did was ause the Lisp interpreterto evaluate the + and look for the value of the variable instead of the fun tionde�nition. We did this by pla ing the ursor right after the symbol ratherthan after the parenthesis of the en losing list as we did before. As a onse-quen e, the Lisp interpreter evaluated the pre eding s-expression, whi h inthis ase was the + by itself.Sin e + does not have a value bound to it, just the fun tion de�nition,the error message reported that the symbol's value as a variable was void.In GNU Ema s version 20 and before, your error message will say:Symbol's value as variable is void: +The meaning is the same as in GNU Ema s 21.1.8 ArgumentsTo see how information is passed to fun tions, let's look again at our oldstandby, the addition of two plus two. In Lisp, this is written as follows:(+ 2 2)If you evaluate this expression, the number 4 will appear in your e hoarea. What the Lisp interpreter does is add the numbers that follow the +.The numbers added by + are alled the arguments of the fun tion +.These numbers are the information that is given to or passed to the fun tion.The word `argument' omes from the way it is used in mathemati s anddoes not refer to a disputation between two people; instead it refers to theinformation presented to the fun tion, in this ase, to the +. In Lisp, thearguments to a fun tion are the atoms or lists that follow the fun tion. Thevalues returned by the evaluation of these atoms or lists are passed to thefun tion. Di�erent fun tions require di�erent numbers of arguments; somefun tions require none at all.11 It is urious to tra k the path by whi h the word `argument' ame to have two di�er-ent meanings, one in mathemati s and the other in everyday English. A ording tothe Oxford English Di tionary, the word derives from the Latin for `to make lear,prove'; thus it ame to mean, by one thread of derivation, `the eviden e o�ered asproof', whi h is to say, `the information o�ered', whi h led to its meaning in Lisp.But in the other thread of derivation, it ame to mean `to assert in a manner againstwhi h others may make ounter assertions', whi h led to the meaning of the word as adisputation. (Note here that the English word has two di�erent de�nitions atta hed toit at the same time. By ontrast, in Ema s Lisp, a symbol annot have two di�erentfun tion de�nitions at the same time.)

Page 31: An Introduction to Programming in Emacs Lisp

An Argument as the Value of a Variable or List 131.8.1 Arguments' Data TypesThe type of data that should be passed to a fun tion depends on whatkind of information it uses. The arguments to a fun tion su h as + musthave values that are numbers, sin e + adds numbers. Other fun tions usedi�erent kinds of data for their arguments.For example, the on at fun tion links together or unites two or morestrings of text to produ e a string. The arguments are strings. Con ate-nating the two hara ter strings ab , def produ es the single string ab def.This an be seen by evaluating the following:( on at "ab " "def")The value produ ed by evaluating this expression is "ab def".A fun tion su h as substring uses both a string and numbers as argu-ments. The fun tion returns a part of the string, a substring of the �rstargument. This fun tion takes three arguments. Its �rst argument is thestring of hara ters, the se ond and third arguments are numbers that in-di ate the beginning and end of the substring. The numbers are a ountof the number of hara ters (in luding spa es and pun tuations) from thebeginning of the string.For example, if you evaluate the following:(substring "The qui k brown fox jumped." 16 19)you will see "fox" appear in the e ho area. The arguments are the stringand the two numbers.Note that the string passed to substring is a single atom even thoughit is made up of several words separated by spa es. Lisp ounts everythingbetween the two quotation marks as part of the string, in luding the spa es.You an think of the substring fun tion as a kind of `atom smasher' sin e ittakes an otherwise indivisible atom and extra ts a part. However, substringis only able to extra t a substring from an argument that is a string, notfrom another type of atom su h as a number or symbol.1.8.2 An Argument as the Value of a Variable or ListAn argument an be a symbol that returns a value when it is evaluated.For example, when the symbol fill- olumn by itself is evaluated, it returnsa number. This number an be used in an addition.Position the ursor after the following expression and type C-x C-e:(+ 2 fill- olumn)The value will be a number two more than what you get by evaluatingfill- olumn alone. For me, this is 74, be ause the value of fill- olumn is72.As we have just seen, an argument an be a symbol that returns a valuewhen evaluated. In addition, an argument an be a list that returns a valuewhen it is evaluated. For example, in the following expression, the arguments

Page 32: An Introduction to Programming in Emacs Lisp

14 Chapter 1: List Pro essingto the fun tion on at are the strings "The " and " red foxes." and thelist (number-to-string (+ 2 fill- olumn)).( on at "The " (number-to-string (+ 2 fill- olumn)) " red foxes.")If you evaluate this expression|and if, as with my Ema s, fill- olumnevaluates to 72|"The 74 red foxes." will appear in the e ho area. (Notethat you must put spa es after the word `The' and before the word `red'so they will appear in the �nal string. The fun tion number-to-string onverts the integer that the addition fun tion returns to a string. number-to-string is also known as int-to-string.)1.8.3 Variable Number of ArgumentsSome fun tions, su h as on at, + or *, take any number of arguments.(The * is the symbol for multipli ation.) This an be seen by evaluatingea h of the following expressions in the usual way. What you will see in thee ho area is printed in this text after `)', whi h you may read as `evaluatesto'.In the �rst set, the fun tions have no arguments:(+) ) 0(*) ) 1In this set, the fun tions have one argument ea h:(+ 3) ) 3(* 3) ) 3In this set, the fun tions have three arguments ea h:(+ 3 4 5) ) 12(* 3 4 5) ) 601.8.4 Using the Wrong Type Obje t as an ArgumentWhen a fun tion is passed an argument of the wrong type, the Lispinterpreter produ es an error message. For example, the + fun tion expe tsthe values of its arguments to be numbers. As an experiment we an pass itthe quoted symbol hello instead of a number. Position the ursor after thefollowing expression and type C-x C-e:(+ 2 'hello)When you do this you will generate an error message. What has happened isthat + has tried to add the 2 to the value returned by 'hello, but the valuereturned by 'hello is the symbol hello, not a number. Only numbers anbe added. So + ould not arry out its addition.

Page 33: An Introduction to Programming in Emacs Lisp

Using the Wrong Type Obje t as an Argument 15In GNU Ema s version 21, you will reate and enter a `*Ba ktra e*'bu�er that says:---------- Buffer: *Ba ktra e* ----------Debugger entered--Lisp error:(wrong-type-argument number-or-marker-p hello)+(2 hello)eval((+ 2 (quote hello)))eval-last-sexp-1(nil)eval-last-sexp(nil) all-intera tively(eval-last-sexp)---------- Buffer: *Ba ktra e* ----------As usual, the error message tries to be helpful and makes sense after youlearn how to read it.The �rst part of the error message is straightforward; it says `wrong typeargument'. Next omes the mysterious jargon word `number-or-marker-p'.This word is trying to tell you what kind of argument the + expe ted.The symbol number-or-marker-p says that the Lisp interpreter is try-ing to determine whether the information presented it (the value of theargument) is a number or a marker (a spe ial obje t representing a bu�erposition). What it does is test to see whether the + is being given numbers toadd. It also tests to see whether the argument is something alled a marker,whi h is a spe i� feature of Ema s Lisp. (In Ema s, lo ations in a bu�erare re orded as markers. When the mark is set with the C-� or C-hSPCi ommand, its position is kept as a marker. The mark an be onsidered anumber|the number of hara ters the lo ation is from the beginning of thebu�er.) In Ema s Lisp, + an be used to add the numeri value of markerpositions as numbers.The `p' of number-or-marker-p is the embodiment of a pra ti e startedin the early days of Lisp programming. The `p' stands for `predi ate'. In thejargon used by the early Lisp resear hers, a predi ate refers to a fun tionto determine whether some property is true or false. So the `p' tells us thatnumber-or-marker-p is the name of a fun tion that determines whether itis true or false that the argument supplied is a number or a marker. OtherLisp symbols that end in `p' in lude zerop, a fun tion that tests whether itsargument has the value of zero, and listp, a fun tion that tests whether itsargument is a list.Finally, the last part of the error message is the symbol hello. This is thevalue of the argument that was passed to +. If the addition had been passedthe orre t type of obje t, the value passed would have been a number, su has 37, rather than a symbol like hello. But then you would not have gotthe error message.

Page 34: An Introduction to Programming in Emacs Lisp

16 Chapter 1: List Pro essingIn GNU Ema s version 20 and before, the e ho area displays an errormessage that says:Wrong type argument: number-or-marker-p, helloThis says, in di�erent words, the same as the top line of the `*Ba ktra e*'bu�er.1.8.5 The message Fun tionLike +, the message fun tion takes a variable number of arguments. It isused to send messages to the user and is so useful that we will des ribe ithere.A message is printed in the e ho area. For example, you an print amessage in your e ho area by evaluating the following list:(message "This message appears in the e ho area!")The whole string between double quotation marks is a single argumentand is printed in toto. (Note that in this example, the message itself will ap-pear in the e ho area within double quotes; that is be ause you see the valuereturned by the message fun tion. In most uses of message in programs thatyou write, the text will be printed in the e ho area as a side-e�e t, withoutthe quotes. See Se tion 3.3.1, \multiply-by-seven in detail", page 34, foran example of this.)However, if there is a `%s' in the quoted string of hara ters, the messagefun tion does not print the `%s' as su h, but looks to the argument thatfollows the string. It evaluates the se ond argument and prints the value atthe lo ation in the string where the `%s' is.You an see this by positioning the ursor after the following expressionand typing C-x C-e:(message "The name of this buffer is: %s." (buffer-name))In Info, "The name of this buffer is: *info*." will appear in the e hoarea. The fun tion buffer-name returns the name of the bu�er as a string,whi h the message fun tion inserts in pla e of %s.To print a value as an integer, use `%d' in the same way as `%s'. Forexample, to print a message in the e ho area that states the value of thefill- olumn, evaluate the following:(message "The value of fill- olumn is %d." fill- olumn)On my system, when I evaluate this list, "The value of fill- olumn is72." appears in my e ho area2.If there is more than one `%s' in the quoted string, the value of the �rstargument following the quoted string is printed at the lo ation of the �rst`%s' and the value of the se ond argument is printed at the lo ation of these ond `%s', and so on.2 A tually, you an use %s to print a number. It is non-spe i� . %d prints only the partof a number left of a de imal point, and not anything that is not a number.

Page 35: An Introduction to Programming in Emacs Lisp

Using set 17For example, if you evaluate the following,(message "There are %d %s in the offi e!"(- fill- olumn 14) "pink elephants")a rather whimsi al message will appear in your e ho area. On my system itsays, "There are 58 pink elephants in the offi e!".The expression (- fill- olumn 14) is evaluated and the resulting num-ber is inserted in pla e of the `%d'; and the string in double quotes, "pinkelephants", is treated as a single argument and inserted in pla e of the`%s'. (That is to say, a string between double quotes evaluates to itself, likea number.)Finally, here is a somewhat omplex example that not only illustratesthe omputation of a number, but also shows how you an use an expressionwithin an expression to generate the text that is substituted for `%s':(message "He saw %d %s"(- fill- olumn 34)( on at "red "(substring"The qui k brown foxes jumped." 16 21)" leaping."))In this example, message has three arguments: the string, "He saw %d%s", the expression, (- fill- olumn 32), and the expression beginning withthe fun tion on at. The value resulting from the evaluation of (- fill- olumn 32) is inserted in pla e of the `%d'; and the value returned by theexpression beginning with on at is inserted in pla e of the `%s'.When I evaluate the expression, the message "He saw 38 red foxesleaping." appears in my e ho area.1.9 Setting the Value of a VariableThere are several ways by whi h a variable an be given a value. One ofthe ways is to use either the fun tion set or the fun tion setq. Another wayis to use let (see Se tion 3.6, \let", page 36). (The jargon for this pro essis to bind a variable to a value.)The following se tions not only des ribe how set and setq work but alsoillustrate how arguments are passed.1.9.1 Using setTo set the value of the symbol flowers to the list '(rose violet daisybutter up), evaluate the following expression by positioning the ursor afterthe expression and typing C-x C-e.(set 'flowers '(rose violet daisy butter up))

Page 36: An Introduction to Programming in Emacs Lisp

18 Chapter 1: List Pro essingThe list (rose violet daisy butter up) will appear in the e ho area. Thisis what is returned by the set fun tion. As a side e�e t, the symbol flowersis bound to the list ; that is, the symbol flowers, whi h an be viewed as avariable, is given the list as its value. (This pro ess, by the way, illustrateshow a side e�e t to the Lisp interpreter, setting the value, an be the primarye�e t that we humans are interested in. This is be ause every Lisp fun tionmust return a value if it does not get an error, but it will only have a sidee�e t if it is designed to have one.)After evaluating the set expression, you an evaluate the symbol flowersand it will return the value you just set. Here is the symbol. Pla e your ursor after it and type C-x C-e.flowersWhen you evaluate flowers, the list (rose violet daisy butter up) ap-pears in the e ho area.In identally, if you evaluate 'flowers, the variable with a quote in frontof it, what you will see in the e ho area is the symbol itself, flowers. Hereis the quoted symbol, so you an try this:'flowersNote also, that when you use set, you need to quote both arguments toset, unless you want them evaluated. Sin e we do not want either argumentevaluated, neither the variable flowers nor the list (rose violet daisybutter up), both are quoted. (When you use set without quoting its �rstargument, the �rst argument is evaluated before anything else is done. Ifyou did this and flowers did not have a value already, you would get anerror message that the `Symbol's value as variable is void'; on the otherhand, if flowers did return a value after it was evaluated, the set wouldattempt to set the value that was returned. There are situations where thisis the right thing for the fun tion to do; but su h situations are rare.)1.9.2 Using setqAs a pra ti al matter, you almost always quote the �rst argument to set.The ombination of set and a quoted �rst argument is so ommon that ithas its own name: the spe ial form setq. This spe ial form is just like setex ept that the �rst argument is quoted automati ally, so you don't need totype the quote mark yourself. Also, as an added onvenien e, setq permitsyou to set several di�erent variables to di�erent values, all in one expression.To set the value of the variable arnivores to the list '(lion tigerleopard) using setq, the following expression is used:(setq arnivores '(lion tiger leopard))This is exa tly the same as using set ex ept the �rst argument is automat-i ally quoted by setq. (The `q' in setq means quote.)

Page 37: An Introduction to Programming in Emacs Lisp

Counting 19With set, the expression would look like this:(set ' arnivores '(lion tiger leopard))Also, setq an be used to assign di�erent values to di�erent variables.The �rst argument is bound to the value of the se ond argument, the thirdargument is bound to the value of the fourth argument, and so on. Forexample, you ould use the following to assign a list of trees to the symboltrees and a list of herbivores to the symbol herbivores:(setq trees '(pine fir oak maple)herbivores '(gazelle antelope zebra))(The expression ould just as well have been on one line, but it might nothave �t on a page; and humans �nd it easier to read ni ely formatted lists.)Although I have been using the term `assign', there is another way ofthinking about the workings of set and setq; and that is to say that setand setq make the symbol point to the list. This latter way of thinking isvery ommon and in forth oming hapters we shall ome upon at least onesymbol that has `pointer' as part of its name. The name is hosen be ause thesymbol has a value, spe i� ally a list, atta hed to it; or, expressed anotherway, the symbol is set to \point" to the list.1.9.3 CountingHere is an example that shows how to use setq in a ounter. You mightuse this to ount how many times a part of your program repeats itself. Firstset a variable to zero; then add one to the number ea h time the programrepeats itself. To do this, you need a variable that serves as a ounter, andtwo expressions: an initial setq expression that sets the ounter variable tozero; and a se ond setq expression that in rements the ounter ea h time itis evaluated.(setq ounter 0) ; Let's all this the initializer.(setq ounter (+ ounter 1)) ; This is the in rementer. ounter ; This is the ounter.(The text following the `;' are omments. See Se tion 3.2.1, \Change aFun tion De�nition", page 32.)If you evaluate the �rst of these expressions, the initializer, (setq ounter 0), and then evaluate the third expression, ounter, the number 0will appear in the e ho area. If you then evaluate the se ond expression, thein rementer, (setq ounter (+ ounter 1)), the ounter will get the value1. So if you again evaluate ounter, the number 1 will appear in the e hoarea. Ea h time you evaluate the se ond expression, the value of the ounterwill be in remented.When you evaluate the in rementer, (setq ounter (+ ounter 1)), theLisp interpreter �rst evaluates the innermost list; this is the addition. In

Page 38: An Introduction to Programming in Emacs Lisp

20 Chapter 1: List Pro essingorder to evaluate this list, it must evaluate the variable ounter and thenumber 1. When it evaluates the variable ounter, it re eives its urrentvalue. It passes this value and the number 1 to the + whi h adds themtogether. The sum is then returned as the value of the inner list and passedto the setq whi h sets the variable ounter to this new value. Thus, thevalue of the variable, ounter, is hanged.1.10 SummaryLearning Lisp is like limbing a hill in whi h the �rst part is the steepest.You have now limbed the most diÆ ult part; what remains be omes easieras you progress onwards.In summary,� Lisp programs are made up of expressions, whi h are lists or singleatoms.� Lists are made up of zero or more atoms or inner lists, separated bywhitespa e and surrounded by parentheses. A list an be empty.� Atoms are multi- hara ter symbols, like forward-paragraph, single hara ter symbols like +, strings of hara ters between double quota-tion marks, or numbers.� A number evaluates to itself.� A string between double quotes also evaluates to itself.� When you evaluate a symbol by itself, its value is returned.� When you evaluate a list, the Lisp interpreter looks at the �rst symbolin the list and then at the fun tion de�nition bound to that symbol.Then the instru tions in the fun tion de�nition are arried out.� A single-quote, ', tells the Lisp interpreter that it should return thefollowing expression as written, and not evaluate it as it would if thequote were not there.� Arguments are the information passed to a fun tion. The arguments toa fun tion are omputed by evaluating the rest of the elements of thelist of whi h the fun tion is the �rst element.� A fun tion always returns a value when it is evaluated (unless it getsan error); in addition, it may also arry out some a tion alled a \sidee�e t". In many ases, a fun tion's primary purpose is to reate a sidee�e t.1.11 Exer isesA few simple exer ises:� Generate an error message by evaluating an appropriate symbol that isnot within parentheses.

Page 39: An Introduction to Programming in Emacs Lisp

Exer ises 21� Generate an error message by evaluating an appropriate symbol that isbetween parentheses.� Create a ounter that in rements by two rather than one.� Write an expression that prints a message in the e ho area when evalu-ated.

Page 40: An Introduction to Programming in Emacs Lisp

22 Chapter 1: List Pro essing

Page 41: An Introduction to Programming in Emacs Lisp

Bu�er Names 232 Pra ti ing EvaluationBefore learning how to write a fun tion de�nition in Ema s Lisp, it isuseful to spend a little time evaluating various expressions that have alreadybeen written. These expressions will be lists with the fun tions as their �rst(and often only) element. Sin e some of the fun tions asso iated with bu�ersare both simple and interesting, we will start with those. In this se tion, wewill evaluate a few of these. In another se tion, we will study the ode ofseveral other bu�er-related fun tions, to see how they were written.Whenever you give an editing ommand to Ema s Lisp, su h as the om-mand to move the ursor or to s roll the s reen, you are evaluating an ex-pression, the �rst element of whi h is a fun tion. This is how Ema s works.When you type keys, you ause the Lisp interpreter to evaluate an expres-sion and that is how you get your results. Even typing plain text involvesevaluating an Ema s Lisp fun tion, in this ase, one that uses self-insert- ommand, whi h simply inserts the hara ter you typed. The fun tions youevaluate by typing keystrokes are alled intera tive fun tions, or ommands;how you make a fun tion intera tive will be illustrated in the hapter onhow to write fun tion de�nitions. See Se tion 3.3, \Making a Fun tion In-tera tive", page 33.In addition to typing keyboard ommands, we have seen a se ond wayto evaluate an expression: by positioning the ursor after a list and typingC-x C-e. This is what we will do in the rest of this se tion. There are otherways to evaluate an expression as well; these will be des ribed as we ometo them.Besides being used for pra ti ing evaluation, the fun tions shown in thenext few se tions are important in their own right. A study of these fun tionsmakes lear the distin tion between bu�ers and �les, how to swit h to abu�er, and how to determine a lo ation within it.2.1 Bu�er NamesThe two fun tions, buffer-name and buffer-file-name, show the di�er-en e between a �le and a bu�er. When you evaluate the following expression,(buffer-name), the name of the bu�er appears in the e ho area. When youevaluate (buffer-file-name), the name of the �le to whi h the bu�er refersappears in the e ho area. Usually, the name returned by (buffer-name) isthe same as the name of the �le to whi h it refers, and the name returnedby (buffer-file-name) is the full path-name of the �le.A �le and a bu�er are two di�erent entities. A �le is information re ordedpermanently in the omputer (unless you delete it). A bu�er, on the otherhand, is information inside of Ema s that will vanish at the end of the editingsession (or when you kill the bu�er). Usually, a bu�er ontains informationthat you have opied from a �le; we say the bu�er is visiting that �le. This opy is what you work on and modify. Changes to the bu�er do not hange

Page 42: An Introduction to Programming in Emacs Lisp

24 Chapter 2: Pra ti ing Evaluationthe �le, until you save the bu�er. When you save the bu�er, the bu�er is opied to the �le and is thus saved permanently.If you are reading this in Info inside of GNU Ema s, you an evaluateea h of the following expressions by positioning the ursor after it and typingC-x C-e.(buffer-name)(buffer-file-name)When I do this, `"introdu tion.texinfo"' is the value returned by eval-uating (buffer-name), and `"/gnu/work/intro/introdu tion.texinfo"'is the value returned by evaluating (buffer-file-name). The former is thename of the bu�er and the latter is the name of the �le. (In the expres-sions, the parentheses tell the Lisp interpreter to treat buffer-name andbuffer-file-name as fun tions; without the parentheses, the interpreterwould attempt to evaluate the symbols as variables. See Se tion 1.7, \Vari-ables", page 10.)In spite of the distin tion between �les and bu�ers, you will often �ndthat people refer to a �le when they mean a bu�er and vi e-versa. Indeed,most people say, \I am editing a �le," rather than saying, \I am editing abu�er whi h I will soon save to a �le." It is almost always lear from ontextwhat people mean. When dealing with omputer programs, however, it isimportant to keep the distin tion in mind, sin e the omputer is not as smartas a person.The word `bu�er', by the way, omes from the meaning of the word asa ushion that deadens the for e of a ollision. In early omputers, a bu�er ushioned the intera tion between �les and the omputer's entral pro essingunit. The drums or tapes that held a �le and the entral pro essing unitwere pie es of equipment that were very di�erent from ea h other, workingat their own speeds, in spurts. The bu�er made it possible for them to worktogether e�e tively. Eventually, the bu�er grew from being an intermediary,a temporary holding pla e, to being the pla e where work is done. Thistransformation is rather like that of a small seaport that grew into a great ity: on e it was merely the pla e where argo was warehoused temporarilybefore being loaded onto ships; then it be ame a business and ultural enterin its own right.Not all bu�ers are asso iated with �les. For example, when you startan Ema s session by typing the ommand ema s alone, without naming any�les, Ema s will start with the `*s rat h*' bu�er on the s reen. This bu�eris not visiting any �le. Similarly, a `*Help*' bu�er is not asso iated withany �le.If you swit h to the `*s rat h*' bu�er, type (buffer-name), positionthe ursor after it, and type C-x C-e to evaluate the expression, the name"*s rat h*" is returned and will appear in the e ho area. "*s rat h*"is the name of the bu�er. However, if you type (buffer-file-name) in

Page 43: An Introduction to Programming in Emacs Lisp

Getting Bu�ers 25the `*s rat h*' bu�er and evaluate that, nil will appear in the e ho area.nil is from the Latin word for `nothing'; in this ase, it means that the`*s rat h*' bu�er is not asso iated with any �le. (In Lisp, nil is also usedto mean `false' and is a synonym for the empty list, ().)In identally, if you are in the `*s rat h*' bu�er and want the valuereturned by an expression to appear in the `*s rat h*' bu�er itself ratherthan in the e ho area, type C-u C-x C-e instead of C-x C-e. This auses thevalue returned to appear after the expression. The bu�er will look like this:(buffer-name)"*s rat h*"You annot do this in Info sin e Info is read-only and it will not allow youto hange the ontents of the bu�er. But you an do this in any bu�er you an edit; and when you write ode or do umentation (su h as this book),this feature is very useful.2.2 Getting Bu�ersThe buffer-name fun tion returns the name of the bu�er; to get thebu�er itself, a di�erent fun tion is needed: the urrent-buffer fun tion. Ifyou use this fun tion in ode, what you get is the bu�er itself.A name and the obje t or entity to whi h the name refers are di�erentfrom ea h other. You are not your name. You are a person to whom othersrefer by name. If you ask to speak to George and someone hands you a ard with the letters `G', `e', `o', `r', `g', and `e' written on it, you might beamused, but you would not be satis�ed. You do not want to speak to thename, but to the person to whom the name refers. A bu�er is similar: thename of the s rat h bu�er is `*s rat h*', but the name is not the bu�er.To get a bu�er itself, you need to use a fun tion su h as urrent-buffer.However, there is a slight ompli ation: if you evaluate urrent-bufferin an expression on its own, as we will do here, what you see is a printedrepresentation of the name of the bu�er without the ontents of the bu�er.Ema s works this way for two reasons: the bu�er may be thousands of lineslong|too long to be onveniently displayed; and, another bu�er may havethe same ontents but a di�erent name, and it is important to distinguishbetween them.Here is an expression ontaining the fun tion:( urrent-buffer)If you evaluate the expression in the usual way, `#<buffer *info*>' appearsin the e ho area. The spe ial format indi ates that the bu�er itself is beingreturned, rather than just its name.In identally, while you an type a number or symbol into a program, you annot do that with the printed representation of a bu�er: the only way toget a bu�er itself is with a fun tion su h as urrent-buffer.A related fun tion is other-buffer. This returns the most re ently se-le ted bu�er other than the one you are in urrently. If you have re ently

Page 44: An Introduction to Programming in Emacs Lisp

26 Chapter 2: Pra ti ing Evaluationswit hed ba k and forth from the `*s rat h*' bu�er, other-buffer willreturn that bu�er.You an see this by evaluating the expression:(other-buffer)You should see `#<buffer *s rat h*>' appear in the e ho area, or the nameof whatever other bu�er you swit hed ba k from most re ently1.2.3 Swit hing Bu�ersThe other-buffer fun tion a tually provides a bu�er when it is usedas an argument to a fun tion that requires one. We an see this by usingother-buffer and swit h-to-buffer to swit h to a di�erent bu�er.But �rst, a brief introdu tion to the swit h-to-buffer fun tion. Whenyou swit hed ba k and forth from Info to the `*s rat h*' bu�er to evaluate(buffer-name), you most likely typed C-x b and then typed `*s rat h*'2when prompted in the minibu�er for the name of the bu�er to whi h youwanted to swit h. The keystrokes, C-x b, ause the Lisp interpreter to eval-uate the intera tive fun tion swit h-to-buffer. As we said before, this ishow Ema s works: di�erent keystrokes all or run di�erent fun tions. Forexample, C-f alls forward- har, M-e alls forward-senten e, and so on.By writing swit h-to-buffer in an expression, and giving it a bu�er toswit h to, we an swit h bu�ers just the way C-x b does.Here is the Lisp expression:(swit h-to-buffer (other-buffer))The symbol swit h-to-buffer is the �rst element of the list, so the Lispinterpreter will treat it as a fun tion and arry out the instru tions thatare atta hed to it. But before doing that, the interpreter will note thatother-buffer is inside parentheses and work on that symbol �rst. other-buffer is the �rst (and in this ase, the only) element of this list, so the Lispinterpreter alls or runs the fun tion. It returns another bu�er. Next, theinterpreter runs swit h-to-buffer, passing to it, as an argument, the otherbu�er, whi h is what Ema s will swit h to. If you are reading this in Info,try this now. Evaluate the expression. (To get ba k, type C-x b hRETi.)31 A tually, by default, if the bu�er from whi h you just swit hed is visible to you inanother window, other-buffer will hoose the most re ent bu�er that you annot see;this is a subtlety that I often forget.2 Or rather, to save typing, you probably typed just part of the name, su h as *s , andthen pressed your TAB key to ause it to expand to the full name; and then typed yourRET key.3 Remember, this expression will move you to your most re ent other bu�er that you annot see. If you really want to go to your most re ently sele ted bu�er, even if you an still see it, you need to evaluate the following more omplex expression:(swit h-to-buffer (other-buffer ( urrent-buffer) t))

Page 45: An Introduction to Programming in Emacs Lisp

Bu�er Size and the Lo ation of Point 27In the programming examples in later se tions of this do ument, you willsee the fun tion set-buffer more often than swit h-to-buffer. This isbe ause of a di�eren e between omputer programs and humans: humanshave eyes and expe t to see the bu�er on whi h they are working on their omputer terminals. This is so obvious, it almost goes without saying. How-ever, programs do not have eyes. When a omputer program works on abu�er, that bu�er does not need to be visible on the s reen.swit h-to-buffer is designed for humans and does two di�erent things:it swit hes the bu�er to whi h Ema s' attention is dire ted; and it swit hesthe bu�er displayed in the window to the new bu�er. set-buffer, on theother hand, does only one thing: it swit hes the attention of the omputerprogram to a di�erent bu�er. The bu�er on the s reen remains un hanged (of ourse, normally nothing happens there until the ommand �nishes running).Also, we have just introdu ed another jargon term, the word all. Whenyou evaluate a list in whi h the �rst symbol is a fun tion, you are allingthat fun tion. The use of the term omes from the notion of the fun tion asan entity that an do something for you if you ` all' it|just as a plumber isan entity who an �x a leak if you all him or her.2.4 Bu�er Size and the Lo ation of PointFinally, let's look at several rather simple fun tions, buffer-size, point,point-min, and point-max. These give information about the size of a bu�erand the lo ation of point within it.The fun tion buffer-size tells you the size of the urrent bu�er; thatis, the fun tion returns a ount of the number of hara ters in the bu�er.(buffer-size)You an evaluate this in the usual way, by positioning the ursor after theexpression and typing C-x C-e.In Ema s, the urrent position of the ursor is alled point. The expres-sion (point) returns a number that tells you where the ursor is lo ated asa ount of the number of hara ters from the beginning of the bu�er up topoint.You an see the hara ter ount for point in this bu�er by evaluating thefollowing expression in the usual way:(point)As I write this, the value of point is 65724. The point fun tion is frequentlyused in some of the examples later in this book.In this ase, the �rst argument to other-buffer tells it whi h bu�er to skip|the urrent one|and the se ond argument tells other-buffer it is OK to swit h to avisible bu�er. In regular use, swit h-to-buffer takes you to an invisible windowsin e you would most likely use C-x o (other-window) to go to another visible bu�er.

Page 46: An Introduction to Programming in Emacs Lisp

28 Chapter 2: Pra ti ing EvaluationThe value of point depends, of ourse, on its lo ation within the bu�er.If you evaluate point in this spot, the number will be larger:(point)For me, the value of point in this lo ation is 66043, whi h means that thereare 319 hara ters (in luding spa es) between the two expressions.The fun tion point-min is somewhat similar to point, but it returns thevalue of the minimum permissible value of point in the urrent bu�er. Thisis the number 1 unless narrowing is in e�e t. (Narrowing is a me hanismwhereby you an restri t yourself, or a program, to operations on just a partof a bu�er. See Chapter 6, \Narrowing and Widening", page 77.) Likewise,the fun tion point-max returns the value of the maximum permissible valueof point in the urrent bu�er.2.5 Exer iseFind a �le with whi h you are working and move towards its middle.Find its bu�er name, �le name, length, and your position in the �le.

Page 47: An Introduction to Programming in Emacs Lisp

The defun Spe ial Form 293 How To Write Fun tion De�nitionsWhen the Lisp interpreter evaluates a list, it looks to see whether the �rstsymbol on the list has a fun tion de�nition atta hed to it; or, put anotherway, whether the symbol points to a fun tion de�nition. If it does, the omputer arries out the instru tions in the de�nition. A symbol that has afun tion de�nition is alled, simply, a fun tion (although, properly speaking,the de�nition is the fun tion and the symbol refers to it.)All fun tions are de�ned in terms of other fun tions, ex ept for a fewprimitive fun tions that are written in the C programming language. Whenyou write fun tions' de�nitions, you will write them in Ema s Lisp and useother fun tions as your building blo ks. Some of the fun tions you will usewill themselves be written in Ema s Lisp (perhaps by you) and some will beprimitives written in C. The primitive fun tions are used exa tly like thosewritten in Ema s Lisp and behave like them. They are written in C so we an easily run GNU Ema s on any omputer that has suÆ ient power and an run C.Let me re-emphasize this: when you write ode in Ema s Lisp, you donot distinguish between the use of fun tions written in C and the use offun tions written in Ema s Lisp. The di�eren e is irrelevant. I mentionthe distin tion only be ause it is interesting to know. Indeed, unless youinvestigate, you won't know whether an already-written fun tion is writtenin Ema s Lisp or C.3.1 The defun Spe ial FormIn Lisp, a symbol su h as mark-whole-buffer has ode atta hed to it thattells the omputer what to do when the fun tion is alled. This ode is alledthe fun tion de�nition and is reated by evaluating a Lisp expression thatstarts with the symbol defun (whi h is an abbreviation for de�ne fun tion).Be ause defun does not evaluate its arguments in the usual way, it is alleda spe ial form.In subsequent se tions, we will look at fun tion de�nitions from the Ema ssour e ode, su h as mark-whole-buffer. In this se tion, we will des ribea simple fun tion de�nition so you an see how it looks. This fun tionde�nition uses arithmeti be ause it makes for a simple example. Somepeople dislike examples using arithmeti ; however, if you are su h a person,do not despair. Hardly any of the ode we will study in the remainder ofthis introdu tion involves arithmeti or mathemati s. The examples mostlyinvolve text in one way or another.A fun tion de�nition has up to �ve parts following the word defun:1. The name of the symbol to whi h the fun tion de�nition should beatta hed.2. A list of the arguments that will be passed to the fun tion. If no argu-ments will be passed to the fun tion, this is an empty list, ().

Page 48: An Introduction to Programming in Emacs Lisp

30 Chapter 3: How To Write Fun tion De�nitions3. Do umentation des ribing the fun tion. (Te hni ally optional, butstrongly re ommended.)4. Optionally, an expression to make the fun tion intera tive so you anuse it by typing M-x and then the name of the fun tion; or by typing anappropriate key or key hord.5. The ode that instru ts the omputer what to do: the body of thefun tion de�nition.It is helpful to think of the �ve parts of a fun tion de�nition as beingorganized in a template, with slots for ea h part:(defun fun tion-name (arguments...)"optional-do umentation..."(intera tive argument-passing-info) ; optionalbody...)As an example, here is the ode for a fun tion that multiplies its argumentby 7. (This example is not intera tive. See Se tion 3.3, \Making a Fun tionIntera tive", page 33, for that information.)(defun multiply-by-seven (number)"Multiply NUMBER by seven."(* 7 number))This de�nition begins with a parenthesis and the symbol defun, followedby the name of the fun tion.The name of the fun tion is followed by a list that ontains the argumentsthat will be passed to the fun tion. This list is alled the argument list. Inthis example, the list has only one element, the symbol, number. When thefun tion is used, the symbol will be bound to the value that is used as theargument to the fun tion.Instead of hoosing the word number for the name of the argument, I ould have pi ked any other name. For example, I ould have hosen theword multipli and. I pi ked the word `number' be ause it tells what kindof value is intended for this slot; but I ould just as well have hosen theword `multipli and' to indi ate the role that the value pla ed in this slotwill play in the workings of the fun tion. I ould have alled it foogle, butthat would have been a bad hoi e be ause it would not tell humans what itmeans. The hoi e of name is up to the programmer and should be hosento make the meaning of the fun tion lear.Indeed, you an hoose any name you wish for a symbol in an argumentlist, even the name of a symbol used in some other fun tion: the nameyou use in an argument list is private to that parti ular de�nition. In thatde�nition, the name refers to a di�erent entity than any use of the same nameoutside the fun tion de�nition. Suppose you have a ni k-name `Shorty' inyour family; when your family members refer to `Shorty', they mean you.But outside your family, in a movie, for example, the name `Shorty' refers tosomeone else. Be ause a name in an argument list is private to the fun tion

Page 49: An Introduction to Programming in Emacs Lisp

Install a Fun tion De�nition 31de�nition, you an hange the value of su h a symbol inside the body of afun tion without hanging its value outside the fun tion. The e�e t is similarto that produ ed by a let expression. (See Se tion 3.6, \let", page 36.)The argument list is followed by the do umentation string that des ribesthe fun tion. This is what you see when you type C-h f and the name of afun tion. In identally, when you write a do umentation string like this, youshould make the �rst line a omplete senten e sin e some ommands, su h asapropos, print only the �rst line of a multi-line do umentation string. Also,you should not indent the se ond line of a do umentation string, if you haveone, be ause that looks odd when you use C-h f (des ribe-fun tion). Thedo umentation string is optional, but it is so useful, it should be in luded inalmost every fun tion you write.The third line of the example onsists of the body of the fun tion de�ni-tion. (Most fun tions' de�nitions, of ourse, are longer than this.) In thisfun tion, the body is the list, (* 7 number), whi h says to multiply the valueof number by 7. (In Ema s Lisp, * is the fun tion for multipli ation, just as+ is the fun tion for addition.)When you use the multiply-by-seven fun tion, the argument numberevaluates to the a tual number you want used. Here is an example thatshows how multiply-by-seven is used; but don't try to evaluate this yet!(multiply-by-seven 3)The symbol number, spe i�ed in the fun tion de�nition in the next se tion,is given or \bound to" the value 3 in the a tual use of the fun tion. Notethat although number was inside parentheses in the fun tion de�nition, theargument passed to the multiply-by-seven fun tion is not in parentheses.The parentheses are written in the fun tion de�nition so the omputer an�gure out where the argument list ends and the rest of the fun tion de�nitionbegins.If you evaluate this example, you are likely to get an error message. (Goahead, try it!) This is be ause we have written the fun tion de�nition, butnot yet told the omputer about the de�nition|we have not yet installed (or`loaded') the fun tion de�nition in Ema s. Installing a fun tion is the pro essthat tells the Lisp interpreter the de�nition of the fun tion. Installation isdes ribed in the next se tion.3.2 Install a Fun tion De�nitionIf you are reading this inside of Info in Ema s, you an try out themultiply-by-seven fun tion by �rst evaluating the fun tion de�nition andthen evaluating (multiply-by-seven 3). A opy of the fun tion de�nitionfollows. Pla e the ursor after the last parenthesis of the fun tion de�nitionand type C-x C-e. When you do this, multiply-by-sevenwill appear in thee ho area. (What this means is that when a fun tion de�nition is evaluated,

Page 50: An Introduction to Programming in Emacs Lisp

32 Chapter 3: How To Write Fun tion De�nitionsthe value it returns is the name of the de�ned fun tion.) At the same time,this a tion installs the fun tion de�nition.(defun multiply-by-seven (number)"Multiply NUMBER by seven."(* 7 number))By evaluating this defun, you have just installed multiply-by-seven inEma s. The fun tion is now just as mu h a part of Ema s as forward-word or any other editing fun tion you use. (multiply-by-seven will stayinstalled until you quit Ema s. To reload ode automati ally whenever youstart Ema s, see Se tion 3.5, \Installing Code Permanently", page 36.)You an see the e�e t of installing multiply-by-seven by evaluating thefollowing sample. Pla e the ursor after the following expression and typeC-x C-e. The number 21 will appear in the e ho area.(multiply-by-seven 3)If you wish, you an read the do umentation for the fun tion by typingC-h f (des ribe-fun tion) and then the name of the fun tion, multiply-by-seven. When you do this, a `*Help*' window will appear on your s reenthat says:multiply-by-seven:Multiply NUMBER by seven.(To return to a single window on your s reen, type C-x 1.)3.2.1 Change a Fun tion De�nitionIf you want to hange the ode in multiply-by-seven, just rewrite it.To install the new version in pla e of the old one, evaluate the fun tionde�nition again. This is how you modify ode in Ema s. It is very simple.As an example, you an hange the multiply-by-seven fun tion to addthe number to itself seven times instead of multiplying the number by seven.It produ es the same answer, but by a di�erent path. At the same time, wewill add a omment to the ode; a omment is text that the Lisp interpreterignores, but that a human reader may �nd useful or enlightening. The omment is that this is the \se ond version".(defun multiply-by-seven (number) ; Se ond version."Multiply NUMBER by seven."(+ number number number number number number number))The omment follows a semi olon, `;'. In Lisp, everything on a line thatfollows a semi olon is a omment. The end of the line is the end of the omment. To stret h a omment over two or more lines, begin ea h linewith a semi olon.See Se tion 16.3, \Beginning a `.ema s' File", page 216, and se tion\Comments" in The GNU Ema s Lisp Referen e Manual, for more about omments.

Page 51: An Introduction to Programming in Emacs Lisp

Make a Fun tion Intera tive 33You an install this version of the multiply-by-seven fun tion by eval-uating it in the same way you evaluated the �rst fun tion: pla e the ursorafter the last parenthesis and type C-x C-e.In summary, this is how you write ode in Ema s Lisp: you write afun tion; install it; test it; and then make �xes or enhan ements and installit again.3.3 Make a Fun tion Intera tiveYou make a fun tion intera tive by pla ing a list that begins with thespe ial form intera tive immediately after the do umentation. A user an invoke an intera tive fun tion by typing M-x and then the name of thefun tion; or by typing the keys to whi h it is bound, for example, by typingC-n for next-line or C-x h for mark-whole-buffer.Interestingly, when you all an intera tive fun tion intera tively, the valuereturned is not automati ally displayed in the e ho area. This is be ause youoften all an intera tive fun tion for its side e�e ts, su h as moving forwardby a word or line, and not for the value returned. If the returned valuewere displayed in the e ho area ea h time you typed a key, it would be verydistra ting.Both the use of the spe ial form intera tive and one way to display avalue in the e ho area an be illustrated by reating an intera tive versionof multiply-by-seven.Here is the ode:(defun multiply-by-seven (number) ; Intera tive version."Multiply NUMBER by seven."(intera tive "p")(message "The result is %d" (* 7 number)))You an install this ode by pla ing your ursor after it and typing C-x C-e.The name of the fun tion will appear in your e ho area. Then, you an usethis ode by typing C-u and a number and then typing M-x multiply-by-seven and pressing hRETi. The phrase `The result is ...' followed by theprodu t will appear in the e ho area.Speaking more generally, you invoke a fun tion like this in either of twoways:1. By typing a pre�x argument that ontains the number to be passed,and then typing M-x and the name of the fun tion, as with C-u 3 M-xforward-senten e; or,2. By typing whatever key or key hord the fun tion is bound to, as withC-u 3 M-e.Both the examples just mentioned work identi ally to move point forwardthree senten es. (Sin e multiply-by-seven is not bound to a key, it ouldnot be used as an example of key binding.)

Page 52: An Introduction to Programming in Emacs Lisp

34 Chapter 3: How To Write Fun tion De�nitions(See Se tion 16.7, \Some Keybindings", page 220, to learn how to binda ommand to a key.)A pre�x argument is passed to an intera tive fun tion by typing thehMETAi key followed by a number, for example, M-3 M-e, or by typing C-u and then a number, for example, C-u 3 M-e (if you type C-u without anumber, it defaults to 4).3.3.1 An Intera tive multiply-by-sevenLet's look at the use of the spe ial form intera tive and then at thefun tion message in the intera tive version of multiply-by-seven. You willre all that the fun tion de�nition looks like this:(defun multiply-by-seven (number) ; Intera tive version."Multiply NUMBER by seven."(intera tive "p")(message "The result is %d" (* 7 number)))In this fun tion, the expression, (intera tive "p"), is a list of two ele-ments. The "p" tells Ema s to pass the pre�x argument to the fun tion anduse its value for the argument of the fun tion.The argument will be a number. This means that the symbol numberwill be bound to a number in the line:(message "The result is %d" (* 7 number))For example, if your pre�x argument is 5, the Lisp interpreter will evaluatethe line as if it were:(message "The result is %d" (* 7 5))(If you are reading this in GNU Ema s, you an evaluate this expressionyourself.) First, the interpreter will evaluate the inner list, whi h is (* 75). This returns a value of 35. Next, it will evaluate the outer list, passingthe values of the se ond and subsequent elements of the list to the fun tionmessage.As we have seen, message is an Ema s Lisp fun tion espe ially designedfor sending a one line message to a user. (See Se tion 1.8.5, \The messagefun tion", page 16.) In summary, the message fun tion prints its �rst argu-ment in the e ho area as is, ex ept for o urren es of `%d', `%s', or `% '. Whenit sees one of these ontrol sequen es, the fun tion looks to the se ond andsubsequent arguments and prints the value of the argument in the lo ationin the string where the ontrol sequen e is lo ated.In the intera tive multiply-by-seven fun tion, the ontrol string is `%d',whi h requires a number, and the value returned by evaluating (* 7 5) isthe number 35. Consequently, the number 35 is printed in pla e of the `%d'and the message is `The result is 35'.(Note that when you all the fun tion multiply-by-seven, the messageis printed without quotes, but when you all message, the text is printedin double quotes. This is be ause the value returned by message is what

Page 53: An Introduction to Programming in Emacs Lisp

Di�erent Options for intera tive 35appears in the e ho area when you evaluate an expression whose �rst elementis message; but when embedded in a fun tion, message prints the text as aside e�e t without quotes.)3.4 Di�erent Options for intera tiveIn the example, multiply-by-seven used "p" as the argument tointera tive. This argument told Ema s to interpret your typing eitherC-u followed by a number or hMETAi followed by a number as a ommandto pass that number to the fun tion as its argument. Ema s has more thantwenty hara ters prede�ned for use with intera tive. In almost every ase, one of these options will enable you to pass the right information in-tera tively to a fun tion. (See se tion \Code Chara ters for intera tive"in The GNU Ema s Lisp Referen e Manual.)For example, the hara ter `r' auses Ema s to pass the beginning andend of the region (the urrent values of point and mark) to the fun tion astwo separate arguments. It is used as follows:(intera tive "r")On the other hand, a `B' tells Ema s to ask for the name of a bu�er thatwill be passed to the fun tion. When it sees a `B', Ema s will ask for thename by prompting the user in the minibu�er, using a string that followsthe `B', as in "BAppend to buffer: ". Not only will Ema s prompt for thename, but Ema s will omplete the name if you type enough of it and presshTABi.A fun tion with two or more arguments an have information passedto ea h argument by adding parts to the string that follows intera tive.When you do this, the information is passed to ea h argument in the sameorder it is spe i�ed in the intera tive list. In the string, ea h part isseparated from the next part by a `\n', whi h is a newline. For example,you ould follow "BAppend to buffer: " with a `\n') and an `r'. This would ause Ema s to pass the values of point and mark to the fun tion as well asprompt you for the bu�er|three arguments in all.In this ase, the fun tion de�nition would look like the following, wherebuffer, start, and end are the symbols to whi h intera tive binds thebu�er and the urrent values of the beginning and ending of the region:(defun name-of-fun tion (buffer start end)"do umentation..."(intera tive "BAppend to buffer: \nr")body-of-fun tion...)(The spa e after the olon in the prompt makes it look better when youare prompted. The append-to-buffer fun tion looks exa tly like this. SeeSe tion 4.4, \The De�nition of append-to-buffer", page 56.)

Page 54: An Introduction to Programming in Emacs Lisp

36 Chapter 3: How To Write Fun tion De�nitionsIf a fun tion does not have arguments, then intera tive does not requireany. Su h a fun tion ontains the simple expression (intera tive). Themark-whole-buffer fun tion is like this.Alternatively, if the spe ial letter- odes are not right for your appli ation,you an pass your own arguments to intera tive as a list. See se tion\Using Intera tive" in The GNU Ema s Lisp Referen e Manual, for moreinformation about this advan ed te hnique.3.5 Install Code PermanentlyWhen you install a fun tion de�nition by evaluating it, it will stay in-stalled until you quit Ema s. The next time you start a new session ofEma s, the fun tion will not be installed unless you evaluate the fun tionde�nition again.At some point, you may want to have ode installed automati ally when-ever you start a new session of Ema s. There are several ways of doingthis:� If you have ode that is just for yourself, you an put the ode for thefun tion de�nition in your `.ema s' initialization �le. When you startEma s, your `.ema s' �le is automati ally evaluated and all the fun tionde�nitions within it are installed. See Chapter 16, \Your `.ema s' File",page 213.� Alternatively, you an put the fun tion de�nitions that you want in-stalled in one or more �les of their own and use the load fun tion to ause Ema s to evaluate and thereby install ea h of the fun tions in the�les. See Se tion 16.9, \Loading Files", page 222.� On the other hand, if you have ode that your whole site will use,it is usual to put it in a �le alled `site-init.el' that is loaded whenEma s is built. This makes the ode available to everyone who uses yourma hine. (See the `INSTALL' �le that is part of the Ema s distribution.)Finally, if you have ode that everyone who uses Ema s may want, you an post it on a omputer network or send a opy to the Free Software Foun-dation. (When you do this, please li ense the ode and its do umentationunder a li ense that permits other people to run, opy, study, modify, andredistribute the ode and whi h prote ts you from having your work takenfrom you.) If you send a opy of your ode to the Free Software Foundation,and properly prote t yourself and others, it may be in luded in the nextrelease of Ema s. In large part, this is how Ema s has grown over the pastyears, by donations.3.6 letThe let expression is a spe ial form in Lisp that you will need to use inmost fun tion de�nitions.

Page 55: An Introduction to Programming in Emacs Lisp

The Parts of a let Expression 37let is used to atta h or bind a symbol to a value in su h a way thatthe Lisp interpreter will not onfuse the variable with a variable of the samename that is not part of the fun tion.To understand why the let spe ial form is ne essary, onsider the situa-tion in whi h you own a home that you generally refer to as `the house', asin the senten e, \The house needs painting." If you are visiting a friend andyour host refers to `the house', he is likely to be referring to his house, notyours, that is, to a di�erent house.If your friend is referring to his house and you think he is referring toyour house, you may be in for some onfusion. The same thing ould happenin Lisp if a variable that is used inside of one fun tion has the same nameas a variable that is used inside of another fun tion, and the two are notintended to refer to the same value. The let spe ial form prevents this kindof onfusion.The let spe ial form prevents onfusion. let reates a name for a lo alvariable that overshadows any use of the same name outside the let ex-pression. This is like understanding that whenever your host refers to `thehouse', he means his house, not yours. (Symbols used in argument lists workthe same way. See Se tion 3.1, \The defun Spe ial Form", page 29.)Lo al variables reated by a let expression retain their value only withinthe let expression itself (and within expressions alled within the let ex-pression); the lo al variables have no e�e t outside the let expression.Another way to think about let is that it is like a setq that is temporaryand lo al. The values set by let are automati ally undone when the let is�nished. The setting only e�e ts expressions that are inside the bounds ofthe let expression. In omputer s ien e jargon, we would say \the bindingof a symbol is visible only in fun tions alled in the let form; in Ema s Lisp,s oping is dynami , not lexi al."let an reate more than one variable at on e. Also, let gives ea hvariable it reates an initial value, either a value spe i�ed by you, or nil.(In the jargon, this is alled `binding the variable to the value'.) After lethas reated and bound the variables, it exe utes the ode in the body of thelet, and returns the value of the last expression in the body, as the value ofthe whole let expression. (`Exe ute' is a jargon term that means to evaluatea list; it omes from the use of the word meaning `to give pra ti al e�e t to'(Oxford English Di tionary). Sin e you evaluate an expression to performan a tion, `exe ute' has evolved as a synonym to `evaluate'.)3.6.1 The Parts of a let ExpressionA let expression is a list of three parts. The �rst part is the symbollet. The se ond part is a list, alled a varlist, ea h element of whi h iseither a symbol by itself or a two-element list, the �rst element of whi h isa symbol. The third part of the let expression is the body of the let. Thebody usually onsists of one or more lists.

Page 56: An Introduction to Programming in Emacs Lisp

38 Chapter 3: How To Write Fun tion De�nitionsA template for a let expression looks like this:(let varlist body...)The symbols in the varlist are the variables that are given initial values bythe let spe ial form. Symbols by themselves are given the initial value ofnil; and ea h symbol that is the �rst element of a two-element list is boundto the value that is returned when the Lisp interpreter evaluates the se ondelement.Thus, a varlist might look like this: (thread (needles 3)). In this ase,in a let expression, Ema s binds the symbol thread to an initial value ofnil, and binds the symbol needles to an initial value of 3.When you write a let expression, what you do is put the appropriateexpressions in the slots of the let expression template.If the varlist is omposed of two-element lists, as is often the ase, thetemplate for the let expression looks like this:(let ((variable value)(variable value)...)body...)3.6.2 Sample let ExpressionThe following expression reates and gives initial values to the two vari-ables zebra and tiger. The body of the let expression is a list whi h allsthe message fun tion.(let ((zebra 'stripes)(tiger 'fier e))(message "One kind of animal has %s and another is %s."zebra tiger))Here, the varlist is ((zebra 'stripes) (tiger 'fier e)).The two variables are zebra and tiger. Ea h variable is the �rst elementof a two-element list and ea h value is the se ond element of its two-elementlist. In the varlist, Ema s binds the variable zebra to the value stripes, andbinds the variable tiger to the value fier e. In this example, both valuesare symbols pre eded by a quote. The values ould just as well have beenanother list or a string. The body of the let follows after the list holding thevariables. In this example, the body is a list that uses the message fun tionto print a string in the e ho area.

Page 57: An Introduction to Programming in Emacs Lisp

The if Spe ial Form 39You may evaluate the example in the usual fashion, by pla ing the ur-sor after the last parenthesis and typing C-x C-e. When you do this, thefollowing will appear in the e ho area:"One kind of animal has stripes and another is fier e."As we have seen before, the message fun tion prints its �rst argument,ex ept for `%s'. In this example, the value of the variable zebra is printedat the lo ation of the �rst `%s' and the value of the variable tiger is printedat the lo ation of the se ond `%s'.3.6.3 Uninitialized Variables in a let StatementIf you do not bind the variables in a let statement to spe i� initialvalues, they will automati ally be bound to an initial value of nil, as in thefollowing expression:(let ((bir h 3)pinefir(oak 'some))(message"Here are %d variables with %s, %s, and %s value."bir h pine fir oak))Here, the varlist is ((bir h 3) pine fir (oak 'some)).If you evaluate this expression in the usual way, the following will appearin your e ho area:"Here are 3 variables with nil, nil, and some value."In this example, Ema s binds the symbol bir h to the number 3, binds thesymbols pine and fir to nil, and binds the symbol oak to the value some.Note that in the �rst part of the let, the variables pine and fir standalone as atoms that are not surrounded by parentheses; this is be ause theyare being bound to nil, the empty list. But oak is bound to some and sois a part of the list (oak 'some). Similarly, bir h is bound to the number3 and so is in a list with that number. (Sin e a number evaluates to itself,the number does not need to be quoted. Also, the number is printed in themessage using a `%d' rather than a `%s'.) The four variables as a group areput into a list to delimit them from the body of the let.3.7 The if Spe ial FormA third spe ial form, in addition to defun and let, is the onditional if.This form is used to instru t the omputer to make de isions. You an writefun tion de�nitions without using if, but it is used often enough, and isimportant enough, to be in luded here. It is used, for example, in the odefor the fun tion beginning-of-buffer.

Page 58: An Introduction to Programming in Emacs Lisp

40 Chapter 3: How To Write Fun tion De�nitionsThe basi idea behind an if, is that \if a test is true, then an expressionis evaluated." If the test is not true, the expression is not evaluated. Forexample, you might make a de ision su h as, \if it is warm and sunny, thengo to the bea h!"An if expression written in Lisp does not use the word `then'; the testand the a tion are the se ond and third elements of the list whose �rstelement is if. Nonetheless, the test part of an if expression is often alledthe if-part and the se ond argument is often alled the then-part.Also, when an if expression is written, the true-or-false-test is usuallywritten on the same line as the symbol if, but the a tion to arry out if thetest is true, the \then-part", is written on the se ond and subsequent lines.This makes the if expression easier to read.(if true-or-false-testa tion-to- arry-out-if-test-is-true)The true-or-false-test will be an expression that is evaluated by the Lispinterpreter.Here is an example that you an evaluate in the usual manner. The test iswhether the number 5 is greater than the number 4. Sin e it is, the message`5 is greater than 4!' will be printed.(if (> 5 4) ; if-part(message "5 is greater than 4!")) ; then-part(The fun tion > tests whether its �rst argument is greater than its se ondargument and returns true if it is.)Of ourse, in a tual use, the test in an if expression will not be �xedfor all time as it is by the expression (> 5 4). Instead, at least one of thevariables used in the test will be bound to a value that is not known aheadof time. (If the value were known ahead of time, we would not need to runthe test!)For example, the value may be bound to an argument of a fun tion de�-nition. In the following fun tion de�nition, the hara ter of the animal is avalue that is passed to the fun tion. If the value bound to hara teristi is fier e, then the message, `It's a tiger!' will be printed; otherwise, nilwill be returned.(defun type-of-animal ( hara teristi )"Print message in e ho area depending on CHARACTERISTIC.If the CHARACTERISTIC is the symbol `fier e',then warn of a tiger."(if (equal hara teristi 'fier e)(message "It's a tiger!")))

Page 59: An Introduction to Programming in Emacs Lisp

The type-of-animal Fun tion in Detail 41If you are reading this inside of GNU Ema s, you an evaluate the fun tionde�nition in the usual way to install it in Ema s, and then you an evaluatethe following two expressions to see the results:(type-of-animal 'fier e)(type-of-animal 'zebra)When you evaluate (type-of-animal 'fier e), you will see the followingmessage printed in the e ho area: "It's a tiger!"; and when you evaluate(type-of-animal 'zebra) you will see nil printed in the e ho area.3.7.1 The type-of-animal Fun tion in DetailLet's look at the type-of-animal fun tion in detail.The fun tion de�nition for type-of-animal was written by �lling theslots of two templates, one for a fun tion de�nition as a whole, and a se ondfor an if expression.The template for every fun tion that is not intera tive is:(defun name-of-fun tion (argument-list)"do umentation..."body...)The parts of the fun tion that mat h this template look like this:(defun type-of-animal ( hara teristi )"Print message in e ho area depending on CHARACTERISTIC.If the CHARACTERISTIC is the symbol `fier e',then warn of a tiger."body: the if expression)The name of fun tion is type-of-animal; it is passed the value of oneargument. The argument list is followed by a multi-line do umentationstring. The do umentation string is in luded in the example be ause it is agood habit to write do umentation string for every fun tion de�nition. Thebody of the fun tion de�nition onsists of the if expression.The template for an if expression looks like this:(if true-or-false-testa tion-to- arry-out-if-the-test-returns-true)In the type-of-animal fun tion, the ode for the if looks like this:(if (equal hara teristi 'fier e)(message "It's a tiger!")))Here, the true-or-false-test is the expression:(equal hara teristi 'fier e)In Lisp, equal is a fun tion that determines whether its �rst argument isequal to its se ond argument. The se ond argument is the quoted symbol

Page 60: An Introduction to Programming in Emacs Lisp

42 Chapter 3: How To Write Fun tion De�nitions'fier e and the �rst argument is the value of the symbol hara teristi |in other words, the argument passed to this fun tion.In the �rst exer ise of type-of-animal, the argument fier e is passed totype-of-animal. Sin e fier e is equal to fier e, the expression, (equal hara teristi 'fier e), returns a value of true. When this happens, theif evaluates the se ond argument or then-part of the if: (message "It'stiger!").On the other hand, in the se ond exer ise of type-of-animal, the argu-ment zebra is passed to type-of-animal. zebra is not equal to fier e, sothe then-part is not evaluated and nil is returned by the if expression.3.8 If{then{else ExpressionsAn if expression may have an optional third argument, alled the else-part, for the ase when the true-or-false-test returns false. When this hap-pens, the se ond argument or then-part of the overall if expression is notevaluated, but the third or else-part is evaluated. You might think of thisas the loudy day alternative for the de ision `if it is warm and sunny, thengo to the bea h, else read a book!".The word \else" is not written in the Lisp ode; the else-part of an ifexpression omes after the then-part. In the written Lisp, the else-part isusually written to start on a line of its own and is indented less than thethen-part:(if true-or-false-testa tion-to- arry-out-if-the-test-returns-truea tion-to- arry-out-if-the-test-returns-false)For example, the following if expression prints the message `4 is notgreater than 5!' when you evaluate it in the usual way:(if (> 4 5) ; if-part(message "5 is greater than 4!") ; then-part(message "4 is not greater than 5!")) ; else-partNote that the di�erent levels of indentation make it easy to distinguish thethen-part from the else-part. (GNU Ema s has several ommands that au-tomati ally indent if expressions orre tly. See Se tion 1.1.3, \GNU Ema sHelps You Type Lists", page 3.)We an extend the type-of-animal fun tion to in lude an else-part bysimply in orporating an additional part to the if expression.

Page 61: An Introduction to Programming in Emacs Lisp

Truth and Falsehood in Ema s Lisp 43You an see the onsequen es of doing this if you evaluate the followingversion of the type-of-animal fun tion de�nition to install it and thenevaluate the two subsequent expressions to pass di�erent arguments to thefun tion.(defun type-of-animal ( hara teristi ) ; Se ond version."Print message in e ho area depending on CHARACTERISTIC.If the CHARACTERISTIC is the symbol `fier e',then warn of a tiger;else say it's not fier e."(if (equal hara teristi 'fier e)(message "It's a tiger!")(message "It's not fier e!")))(type-of-animal 'fier e)(type-of-animal 'zebra)When you evaluate (type-of-animal 'fier e), you will see the followingmessage printed in the e ho area: "It's a tiger!"; but when you evaluate(type-of-animal 'zebra), you will see "It's not fier e!".(Of ourse, if the hara teristi were fero ious, the message "It's notfier e!" would be printed; and it would be misleading! When you write ode, you need to take into a ount the possibility that some su h argumentwill be tested by the if and write your program a ordingly.)3.9 Truth and Falsehood in Ema s LispThere is an important aspe t to the truth test in an if expression. Sofar, we have spoken of `true' and `false' as values of predi ates as if they werenew kinds of Ema s Lisp obje ts. In fa t, `false' is just our old friend nil.Anything else|anything at all|is `true'.The expression that tests for truth is interpreted as true if the result ofevaluating it is a value that is not nil. In other words, the result of the testis onsidered true if the value returned is a number su h as 47, a string su has "hello", or a symbol (other than nil) su h as flowers, or a list, or evena bu�er!Before illustrating a test for truth, we need an explanation of nil.In Ema s Lisp, the symbol nil has two meanings. First, it means theempty list. Se ond, it means false and is the value returned when a true-or-false-test tests false. nil an be written as an empty list, (), or as nil. Asfar as the Lisp interpreter is on erned, () and nil are the same. Humans,however, tend to use nil for false and () for the empty list.In Ema s Lisp, any value that is not nil|is not the empty list|is on-sidered true. This means that if an evaluation returns something that is not

Page 62: An Introduction to Programming in Emacs Lisp

44 Chapter 3: How To Write Fun tion De�nitionsan empty list, an if expression will test true. For example, if a number isput in the slot for the test, it will be evaluated and will return itself, sin ethat is what numbers do when evaluated. In this onditional, the if expres-sion will test true. The expression tests false only when nil, an empty list,is returned by evaluating the expression.You an see this by evaluating the two expressions in the following ex-amples.In the �rst example, the number 4 is evaluated as the test in the ifexpression and returns itself; onsequently, the then-part of the expressionis evaluated and returned: `true' appears in the e ho area. In the se ondexample, the nil indi ates false; onsequently, the else-part of the expressionis evaluated and returned: `false' appears in the e ho area.(if 4'true'false)(if nil'true'false)In identally, if some other useful value is not available for a test thatreturns true, then the Lisp interpreter will return the symbol t for true. Forexample, the expression (> 5 4) returns t when evaluated, as you an seeby evaluating it in the usual way:(> 5 4)On the other hand, this fun tion returns nil if the test is false.(> 4 5)3.10 save-ex ursionThe save-ex ursion fun tion is the fourth and �nal spe ial form thatwe will dis uss in this hapter.In Ema s Lisp programs used for editing, the save-ex ursion fun tionis very ommon. It saves the lo ation of point and mark, exe utes the bodyof the fun tion, and then restores point and mark to their previous positionsif their lo ations were hanged. Its primary purpose is to keep the user frombeing surprised and disturbed by unexpe ted movement of point or mark.Before dis ussing save-ex ursion, however, it may be useful �rst toreview what point and mark are in GNU Ema s. Point is the urrent lo ationof the ursor. Wherever the ursor is, that is point. More pre isely, onterminals where the ursor appears to be on top of a hara ter, point isimmediately before the hara ter. In Ema s Lisp, point is an integer. The�rst hara ter in a bu�er is number one, the se ond is number two, andso on. The fun tion point returns the urrent position of the ursor as anumber. Ea h bu�er has its own value for point.

Page 63: An Introduction to Programming in Emacs Lisp

Template for a save-ex ursion Expression 45The mark is another position in the bu�er; its value an be set with a ommand su h as C-hSPCi (set-mark- ommand). If a mark has been set, you an use the ommand C-x C-x (ex hange-point-and-mark) to ause the ursor to jump to the mark and set the mark to be the previous positionof point. In addition, if you set another mark, the position of the previousmark is saved in the mark ring. Many mark positions an be saved this way.You an jump the ursor to a saved mark by typing C-u C-hSPCi one or moretimes.The part of the bu�er between point and mark is alled the region. Nu-merous ommands work on the region, in luding enter-region, ount-lines-region, kill-region, and print-region.The save-ex ursion spe ial form saves the lo ations of point and markand restores those positions after the ode within the body of the spe ial formis evaluated by the Lisp interpreter. Thus, if point were in the beginningof a pie e of text and some ode moved point to the end of the bu�er, thesave-ex ursion would put point ba k to where it was before, after theexpressions in the body of the fun tion were evaluated.In Ema s, a fun tion frequently moves point as part of its internal work-ings even though a user would not expe t this. For example, ount-lines-regionmoves point. To prevent the user from being bothered by jumps thatare both unexpe ted and (from the user's point of view) unne essary, save-ex ursion is often used to keep point and mark in the lo ation expe ted bythe user. The use of save-ex ursion is good housekeeping.To make sure the house stays lean, save-ex ursion restores the valuesof point and mark even if something goes wrong in the ode inside of it (or,to be more pre ise and to use the proper jargon, \in ase of abnormal exit").This feature is very helpful.In addition to re ording the values of point and mark, save-ex ursionkeeps tra k of the urrent bu�er, and restores it, too. This means you anwrite ode that will hange the bu�er and have save-ex ursion swit h youba k to the original bu�er. This is how save-ex ursion is used in append-to-buffer. (See Se tion 4.4, \The De�nition of append-to-buffer",page 56.)3.10.1 Template for a save-ex ursion ExpressionThe template for ode using save-ex ursion is simple:(save-ex ursionbody...)The body of the fun tion is one or more expressions that will be evaluatedin sequen e by the Lisp interpreter. If there is more than one expressionin the body, the value of the last one will be returned as the value of thesave-ex ursion fun tion. The other expressions in the body are evaluatedonly for their side e�e ts; and save-ex ursion itself is used only for its sidee�e t (whi h is restoring the positions of point and mark).

Page 64: An Introduction to Programming in Emacs Lisp

46 Chapter 3: How To Write Fun tion De�nitionsIn more detail, the template for a save-ex ursion expression looks likethis:(save-ex ursion�rst-expression-in-bodyse ond-expression-in-bodythird-expression-in-body...last-expression-in-body)An expression, of ourse, may be a symbol on its own or a list.In Ema s Lisp ode, a save-ex ursion expression often o urs withinthe body of a let expression. It looks like this:(let varlist(save-ex ursionbody...))3.11 ReviewIn the last few hapters we have introdu ed a fair number of fun tionsand spe ial forms. Here they are des ribed in brief, along with a few similarfun tions that have not been mentioned yet.eval-last-sexpEvaluate the last symboli expression before the urrent lo ationof point. The value is printed in the e ho area unless the fun tionis invoked with an argument; in that ase, the output is printedin the urrent bu�er. This ommand is normally bound to C-xC-e.defun De�ne fun tion. This spe ial form has up to �ve parts: thename, a template for the arguments that will be passed to thefun tion, do umentation, an optional intera tive de laration,and the body of the de�nition.For example:(defun ba k-to-indentation ()"Move point to first visible hara ter on line."(intera tive)(beginning-of-line 1)(skip- hars-forward " \t"))intera tiveDe lare to the interpreter that the fun tion an be used intera -tively. This spe ial form may be followed by a string with oneor more parts that pass the information to the arguments of thefun tion, in sequen e. These parts may also tell the interpreterto prompt for information. Parts of the string are separated bynewlines, `\n'.

Page 65: An Introduction to Programming in Emacs Lisp

Review 47Common ode hara ters are:b The name of an existing bu�er.f The name of an existing �le.p The numeri pre�x argument. (Note that this `p' islower ase.)r Point and the mark, as two numeri arguments,smallest �rst. This is the only ode letter that spe -i�es two su essive arguments rather than one.See se tion \Code Chara ters for `intera tive'" in The GNUEma s Lisp Referen e Manual, for a omplete list of ode har-a ters.let De lare that a list of variables is for use within the body of thelet and give them an initial value, either nil or a spe i�edvalue; then evaluate the rest of the expressions in the body ofthe let and return the value of the last one. Inside the bodyof the let, the Lisp interpreter does not see the values of thevariables of the same names that are bound outside of the let.For example,(let ((foo (buffer-name))(bar (buffer-size)))(message"This buffer is %s and has %d hara ters."foo bar))save-ex ursionRe ord the values of point and mark and the urrent bu�erbefore evaluating the body of this spe ial form. Restore thevalues of point and mark and bu�er afterward.For example,(message "We are %d hara ters into this buffer."(- (point)(save-ex ursion(goto- har (point-min)) (point))))if Evaluate the �rst argument to the fun tion; if it is true, evaluatethe se ond argument; else evaluate the third argument, if thereis one.The if spe ial form is alled a onditional. There are other on-ditionals in Ema s Lisp, but if is perhaps the most ommonlyused.

Page 66: An Introduction to Programming in Emacs Lisp

48 Chapter 3: How To Write Fun tion De�nitionsFor example,(if (string-equal(number-to-string 21)(substring (ema s-version) 10 12))(message "This is version 21 Ema s")(message "This is not version 21 Ema s"))equaleq Test whether two obje ts are the same. equal uses one meaningof the word `same' and eq uses another: equal returns true ifthe two obje ts have a similar stru ture and ontents, su h astwo opies of the same book. On the other hand, eq, returnstrue if both arguments are a tually the same obje t.<><=>= The < fun tion tests whether its �rst argument is smaller thanits se ond argument. A orresponding fun tion, >, tests whetherthe �rst argument is greater than the se ond. Likewise, <= testswhether the �rst argument is less than or equal to the se ondand >= tests whether the �rst argument is greater than or equalto the se ond. In all ases, both arguments must be numbers ormarkers (markers indi ate positions in bu�ers).string<string-lesspstring=string-equalThe string-lessp fun tion tests whether its �rst argument issmaller than the se ond argument. A shorter, alternative namefor the same fun tion (a defalias) is string<.The arguments to string-lessp must be strings or symbols;the ordering is lexi ographi , so ase is signi� ant. The printnames of symbols are used instead of the symbols themselves.An empty string, `""', a string with no hara ters in it, is smallerthan any string of hara ters.string-equal provides the orresponding test for equality. Itsshorter, alternative name is string=. There are no string testfun tions that orrespond to >, >=, or <=.message Print a message in the e ho area. The �rst argument is a stringthat an ontain `%s', `%d', or `% ' to print the value of argumentsthat follow the string. The argument used by `%s' must be astring or a symbol; the argument used by `%d' must be a number.The argument used by `% ' must be an as ii ode number; it willbe printed as the hara ter with that as ii ode.

Page 67: An Introduction to Programming in Emacs Lisp

Review 49setqset The setq fun tion sets the value of its �rst argument to thevalue of the se ond argument. The �rst argument is automati- ally quoted by setq. It does the same for su eeding pairs ofarguments. Another fun tion, set, takes only two argumentsand evaluates both of them before setting the value returned byits �rst argument to the value returned by its se ond argument.buffer-nameWithout an argument, return the name of the bu�er, as a string.buffer-file-nameWithout an argument, return the name of the �le the bu�er isvisiting. urrent-bufferReturn the bu�er in whi h Ema s is a tive; it may not be thebu�er that is visible on the s reen.other-bufferReturn the most re ently sele ted bu�er (other than the bu�erpassed to other-buffer as an argument and other than the urrent bu�er).swit h-to-bufferSele t a bu�er for Ema s to be a tive in and display it in the urrent window so users an look at it. Usually bound to C-x b.set-bufferSwit h Ema s' attention to a bu�er on whi h programs will run.Don't alter what the window is showing.buffer-sizeReturn the number of hara ters in the urrent bu�er.point Return the value of the urrent position of the ursor, as aninteger ounting the number of hara ters from the beginning ofthe bu�er.point-min Return the minimum permissible value of point in the urrentbu�er. This is 1, unless narrowing is in e�e t.point-max Return the value of the maximum permissible value of point inthe urrent bu�er. This is the end of the bu�er, unless narrowingis in e�e t.

Page 68: An Introduction to Programming in Emacs Lisp

50 Chapter 3: How To Write Fun tion De�nitions3.12 Exer ises� Write a non-intera tive fun tion that doubles the value of its argument,a number. Make that fun tion intera tive.� Write a fun tion that tests whether the urrent value of fill- olumnis greater than the argument passed to the fun tion, and if so, prints anappropriate message.

Page 69: An Introduction to Programming in Emacs Lisp

Finding More Information 514 A Few Bu�er{Related Fun tionsIn this hapter we study in detail several of the fun tions used in GNUEma s. This is alled a \walk-through". These fun tions are used as ex-amples of Lisp ode, but are not imaginary examples; with the ex eption ofthe �rst, simpli�ed fun tion de�nition, these fun tions show the a tual odeused in GNU Ema s. You an learn a great deal from these de�nitions. Thefun tions des ribed here are all related to bu�ers. Later, we will study otherfun tions.4.1 Finding More InformationIn this walk-through, I will des ribe ea h new fun tion as we ome to it,sometimes in detail and sometimes brie y. If you are interested, you an getthe full do umentation of any Ema s Lisp fun tion at any time by typingC-h f and then the name of the fun tion (and then hRETi). Similarly, you an get the full do umentation for a variable by typing C-h v and then thename of the variable (and then hRETi).In versions 20 and higher, when a fun tion is written in Ema s Lisp,des ribe-fun tion will also tell you the lo ation of the fun tion de�nition.If you move point over the �le name and press the hRETi key, whi h is this ase means help-follow rather than `return' or `enter', Ema s will take youdire tly to the fun tion de�nition.More generally, if you want to see a fun tion in its original sour e �le,you an use the find-tags fun tion to jump to it. find-tags works witha wide variety of languages, not just Lisp, and C, and it works with non-programming text as well. For example, find-tags will jump to the variousnodes in the Texinfo sour e �le of this do ument.The find-tags fun tion depends on `tags tables' that re ord the lo ationsof the fun tions, variables, and other items to whi h find-tags jumps.To use the find-tags ommand, type M-. (i.e., type the hMETAi key andthe period key at the same time, or else type the hESCi key and then typethe period key), and then, at the prompt, type in the name of the fun tionwhose sour e ode you want to see, su h as mark-whole-buffer, and thentype hRETi. Ema s will swit h bu�ers and display the sour e ode for thefun tion on your s reen. To swit h ba k to your urrent bu�er, type C-x bhRETi. (On some keyboards, the hMETAi key is labelled hALTi.)Depending on how the initial default values of your opy of Ema s areset, you may also need to spe ify the lo ation of your `tags table', whi his a �le alled `TAGS'. For example, if you are interested in Ema s sour es,the tags table you will most likely want, if it has already been reated foryou, will be in a subdire tory of the `/usr/lo al/share/ema s/' dire -tory; thus you would use the M-x visit-tags-table ommand and spe -ify a pathname su h as `/usr/lo al/share/ema s/21.0.100/lisp/TAGS'

Page 70: An Introduction to Programming in Emacs Lisp

52 Chapter 4: A Few Bu�er{Related Fun tionsor `/usr/lo al/sr /ema s/lisp/TAGS'. If the tags table has not alreadybeen reated, you will have to reate it yourself.To reate a `TAGS' �le in a spe i� dire tory, swit h to that dire toryin Ema s using M-x d ommand, or list the dire tory with C-x d (dired).Then run the ompile ommand, with etags *.el as the ommand to exe- ute M-x ompile RET etags *.el RETFor more information, see Se tion 12.5, \Create Your Own `TAGS' File",page 163.After you be ome more familiar with Ema s Lisp, you will �nd that youwill frequently use find-tags to navigate your way around sour e ode; andyou will reate your own `TAGS' tables.In identally, the �les that ontain Lisp ode are onventionally alledlibraries. The metaphor is derived from that of a spe ialized library, su h asa law library or an engineering library, rather than a general library. Ea hlibrary, or �le, ontains fun tions that relate to a parti ular topi or a tivity,su h as `abbrev.el' for handling abbreviations and other typing short uts,and `help.el' for on-line help. (Sometimes several libraries provide odefor a single a tivity, as the various `rmail...' �les provide ode for readingele troni mail.) In The GNU Ema s Manual, you will see senten es su h as\The C-h p ommand lets you sear h the standard Ema s Lisp libraries bytopi keywords."4.2 A Simpli�ed beginning-of-buffer De�nitionThe beginning-of-buffer ommand is a good fun tion to start withsin e you are likely to be familiar with it and it is easy to understand. Usedas an intera tive ommand, beginning-of-buffer moves the ursor to thebeginning of the bu�er, leaving the mark at the previous position. It isgenerally bound to M-<.In this se tion, we will dis uss a shortened version of the fun tion thatshows how it is most frequently used. This shortened fun tion works aswritten, but it does not ontain the ode for a omplex option. In anotherse tion, we will des ribe the entire fun tion. (See Se tion 5.3, \CompleteDe�nition of beginning-of-buffer", page 69.)Before looking at the ode, let's onsider what the fun tion de�nition hasto ontain: it must in lude an expression that makes the fun tion intera tiveso it an be alled by typing M-x beginning-of-buffer or by typing akey hord su h as C-<; it must in lude ode to leave a mark at the originalposition in the bu�er; and it must in lude ode to move the ursor to thebeginning of the bu�er.

Page 71: An Introduction to Programming in Emacs Lisp

A Simpli�ed beginning-of-buffer De�nition 53Here is the omplete text of the shortened version of the fun tion:(defun simplified-beginning-of-buffer ()"Move point to the beginning of the buffer;leave mark at previous position."(intera tive)(push-mark)(goto- har (point-min)))Like all fun tion de�nitions, this de�nition has �ve parts following thespe ial form defun:1. The name: in this example, simplified-beginning-of-buffer.2. A list of the arguments: in this example, an empty list, (),3. The do umentation string.4. The intera tive expression.5. The body.In this fun tion de�nition, the argument list is empty; this means that thisfun tion does not require any arguments. (When we look at the de�nitionfor the omplete fun tion, we will see that it may be passed an optionalargument.)The intera tive expression tells Ema s that the fun tion is intended to beused intera tively. In this example, intera tive does not have an argumentbe ause simplified-beginning-of-buffer does not require one.The body of the fun tion onsists of the two lines:(push-mark)(goto- har (point-min))The �rst of these lines is the expression, (push-mark). When this ex-pression is evaluated by the Lisp interpreter, it sets a mark at the urrentposition of the ursor, wherever that may be. The position of this mark issaved in the mark ring.The next line is (goto- har (point-min)). This expression jumps the ursor to the minimum point in the bu�er, that is, to the beginning of thebu�er (or to the beginning of the a essible portion of the bu�er if it isnarrowed. See Chapter 6, \Narrowing and Widening", page 77.)The push-mark ommand sets a mark at the pla e where the ursor waslo ated before it was moved to the beginning of the bu�er by the (goto- har (point-min)) expression. Consequently, you an, if you wish, go ba kto where you were originally by typing C-x C-x.That is all there is to the fun tion de�nition!When you are reading ode su h as this and ome upon an unfamiliarfun tion, su h as goto- har, you an �nd out what it does by using thedes ribe-fun tion ommand. To use this ommand, type C-h f and thentype in the name of the fun tion and press hRETi. The des ribe-fun tion

Page 72: An Introduction to Programming in Emacs Lisp

54 Chapter 4: A Few Bu�er{Related Fun tions ommand will print the fun tion's do umentation string in a `*Help*' win-dow. For example, the do umentation for goto- har is:One arg, a number. Set point to that number.Beginning of buffer is position (point-min),end is (point-max).(The prompt for des ribe-fun tion will o�er you the symbol under orpre eding the ursor, so you an save typing by positioning the ursor rightover or after the fun tion and then typing C-h f hRETi.)The end-of-buffer fun tion de�nition is written in the same way asthe beginning-of-buffer de�nition ex ept that the body of the fun tion ontains the expression (goto- har (point-max)) in pla e of (goto- har(point-min)).4.3 The De�nition of mark-whole-bufferThe mark-whole-buffer fun tion is no harder to understand than thesimplified-beginning-of-buffer fun tion. In this ase, however, we willlook at the omplete fun tion, not a shortened version.The mark-whole-buffer fun tion is not as ommonly used as thebeginning-of-buffer fun tion, but is useful nonetheless: it marks a wholebu�er as a region by putting point at the beginning and a mark at the endof the bu�er. It is generally bound to C-x h.In GNU Ema s 20, the ode for the omplete fun tion looks like this:(defun mark-whole-buffer ()"Put point at beginning and mark at end of buffer."(intera tive)(push-mark (point))(push-mark (point-max))(goto- har (point-min)))Like all other fun tions, the mark-whole-buffer fun tion �ts into thetemplate for a fun tion de�nition. The template looks like this:(defun name-of-fun tion (argument-list)"do umentation..."(intera tive-expression...)body...)Here is how the fun tion works: the name of the fun tion is mark-whole-buffer; it is followed by an empty argument list, `()', whi h means that thefun tion does not require arguments. The do umentation omes next.The next line is an (intera tive) expression that tells Ema s thatthe fun tion will be used intera tively. These details are similar to thesimplified-beginning-of-buffer fun tion des ribed in the previous se -tion.

Page 73: An Introduction to Programming in Emacs Lisp

Body of mark-whole-buffer 554.3.1 Body of mark-whole-bufferThe body of the mark-whole-buffer fun tion onsists of three lines of ode:(push-mark (point))(push-mark (point-max))(goto- har (point-min))The �rst of these lines is the expression, (push-mark (point)).This line does exa tly the same job as the �rst line of the body ofthe simplified-beginning-of-buffer fun tion, whi h is written (push-mark). In both ases, the Lisp interpreter sets a mark at the urrent positionof the ursor.I don't know why the expression in mark-whole-buffer is written (push-mark (point)) and the expression in beginning-of-buffer is written(push-mark). Perhaps whoever wrote the ode did not know that the ar-guments for push-mark are optional and that if push-mark is not passed anargument, the fun tion automati ally sets mark at the lo ation of point bydefault. Or perhaps the expression was written so as to parallel the stru -ture of the next line. In any ase, the line auses Ema s to determine theposition of point and set a mark there.The next line of mark-whole-buffer is (push-mark (point-max). Thisexpression sets a mark at the point in the bu�er that has the highest number.This will be the end of the bu�er (or, if the bu�er is narrowed, the end of thea essible portion of the bu�er. See Chapter 6, \Narrowing and Widening",page 77, for more about narrowing.) After this mark has been set, theprevious mark, the one set at point, is no longer set, but Ema s remembersits position, just as all other re ent marks are always remembered. Thismeans that you an, if you wish, go ba k to that position by typing C-uC-hSPCi twi e.(In GNU Ema s 21, the (push-mark (point-max) is slightly more om-pli ated than shown here. The line reads(push-mark (point-max) nil t)(The expression works nearly the same as before. It sets a mark at thehighest numbered pla e in the bu�er that it an. However, in this version,push-mark has two additional arguments. The se ond argument to push-mark is nil. This tells the fun tion it should display a message that says`Mark set' when it pushes the mark. The third argument is t. This tellspush-mark to a tivate the mark when Transient Mark mode is turned on.Transient Mark mode highlights the urrently a tive region. It is usuallyturned o�.)Finally, the last line of the fun tion is (goto- har (point-min))). Thisis written exa tly the same way as it is written in beginning-of-buffer.The expression moves the ursor to the minimum point in the bu�er, that is,to the beginning of the bu�er (or to the beginning of the a essible portion

Page 74: An Introduction to Programming in Emacs Lisp

56 Chapter 4: A Few Bu�er{Related Fun tionsof the bu�er). As a result of this, point is pla ed at the beginning of thebu�er and mark is set at the end of the bu�er. The whole bu�er is, therefore,the region.4.4 The De�nition of append-to-bufferThe append-to-buffer ommand is very nearly as simple as the mark-whole-buffer ommand. What it does is opy the region (that is, the partof the bu�er between point and mark) from the urrent bu�er to a spe i�edbu�er.The append-to-buffer ommand uses the insert-buffer-substringfun tion to opy the region. insert-buffer-substring is des ribed by itsname: it takes a string of hara ters from part of a bu�er, a \substring", andinserts them into another bu�er. Most of append-to-buffer is on ernedwith setting up the onditions for insert-buffer-substring to work: the ode must spe ify both the bu�er to whi h the text will go and the regionthat will be opied. Here is the omplete text of the fun tion:(defun append-to-buffer (buffer start end)"Append to spe ified buffer the text of the region.It is inserted into that buffer before its point.When alling from a program, give three arguments:a buffer or the name of one, and two hara ter numbersspe ifying the portion of the urrent buffer to be opied."(intera tive "BAppend to buffer: \nr")(let ((oldbuf ( urrent-buffer)))(save-ex ursion(set-buffer (get-buffer- reate buffer))(insert-buffer-substring oldbuf start end))))The fun tion an be understood by looking at it as a series of �lled-intemplates.The outermost template is for the fun tion de�nition. In this fun tion,it looks like this (with several slots �lled in):(defun append-to-buffer (buffer start end)"do umentation..."(intera tive "BAppend to buffer: \nr")body...)The �rst line of the fun tion in ludes its name and three arguments. Thearguments are the buffer to whi h the text will be opied, and the startand end of the region in the urrent bu�er that will be opied.The next part of the fun tion is the do umentation, whi h is lear and omplete.

Page 75: An Introduction to Programming in Emacs Lisp

The Body of append-to-buffer 574.4.1 The append-to-buffer Intera tive ExpressionSin e the append-to-buffer fun tion will be used intera tively, the fun -tion must have an intera tive expression. (For a review of intera tive,see Se tion 3.3, \Making a Fun tion Intera tive", page 33.) The expressionreads as follows:(intera tive "BAppend to buffer: \nr")This expression has an argument inside of quotation marks and that argu-ment has two parts, separated by `\n'.The �rst part is `BAppend to buffer: '. Here, the `B' tells Ema s to askfor the name of the bu�er that will be passed to the fun tion. Ema s willask for the name by prompting the user in the minibu�er, using the stringfollowing the `B', whi h is the string `Append to buffer: '. Ema s thenbinds the variable buffer in the fun tion's argument list to the spe i�edbu�er.The newline, `\n', separates the �rst part of the argument from the se ondpart. It is followed by an `r' that tells Ema s to bind the two argumentsthat follow the symbol buffer in the fun tion's argument list (that is, startand end) to the values of point and mark.4.4.2 The Body of append-to-bufferThe body of the append-to-buffer fun tion begins with let.As we have seen before (see Se tion 3.6, \let", page 36), the purpose ofa let expression is to reate and give initial values to one or more variablesthat will only be used within the body of the let. This means that su ha variable will not be onfused with any variable of the same name outsidethe let expression.We an see how the let expression �ts into the fun tion as a wholeby showing a template for append-to-buffer with the let expression inoutline:(defun append-to-buffer (buffer start end)"do umentation..."(intera tive "BAppend to buffer: \nr")(let ((variable value))body...)The let expression has three elements:1. The symbol let;2. A varlist ontaining, in this ase, a single two-element list, (variablevalue);3. The body of the let expression.

Page 76: An Introduction to Programming in Emacs Lisp

58 Chapter 4: A Few Bu�er{Related Fun tionsIn the append-to-buffer fun tion, the varlist looks like this:(oldbuf ( urrent-buffer))In this part of the let expression, the one variable, oldbuf, is bound to thevalue returned by the ( urrent-buffer) expression. The variable, oldbuf,is used to keep tra k of the bu�er in whi h you are working and from whi hyou will opy.The element or elements of a varlist are surrounded by a set of parenthesesso the Lisp interpreter an distinguish the varlist from the body of the let.As a onsequen e, the two-element list within the varlist is surrounded by a ir ums ribing set of parentheses. The line looks like this:(let ((oldbuf ( urrent-buffer)))... )The two parentheses before oldbuf might surprise you if you did not realizethat the �rst parenthesis before oldbuf marks the boundary of the varlistand the se ond parenthesis marks the beginning of the two-element list,(oldbuf ( urrent-buffer)).4.4.3 save-ex ursion in append-to-bufferThe body of the let expression in append-to-buffer onsists of a save-ex ursion expression.The save-ex ursion fun tion saves the lo ations of point and mark,and restores them to those positions after the expressions in the body of thesave-ex ursion omplete exe ution. In addition, save-ex ursion keepstra k of the original bu�er, and restores it. This is how save-ex ursion isused in append-to-buffer.In identally, it is worth noting here that a Lisp fun tion is normally for-matted so that everything that is en losed in a multi-line spread is indentedmore to the right than the �rst symbol. In this fun tion de�nition, the letis indented more than the defun, and the save-ex ursion is indented morethan the let, like this:(defun .........(let...(save-ex ursion...

Page 77: An Introduction to Programming in Emacs Lisp

save-ex ursion in append-to-buffer 59This formatting onvention makes it easy to see that the two lines in thebody of the save-ex ursion are en losed by the parentheses asso iatedwith save-ex ursion, just as the save-ex ursion itself is en losed by theparentheses asso iated with the let:(let ((oldbuf ( urrent-buffer)))(save-ex ursion(set-buffer (get-buffer- reate buffer))(insert-buffer-substring oldbuf start end))))The use of the save-ex ursion fun tion an be viewed as a pro ess of�lling in the slots of a template:(save-ex ursion�rst-expression-in-bodyse ond-expression-in-body...last-expression-in-body)In this fun tion, the body of the save-ex ursion ontains only two expres-sions. The body looks like this:(set-buffer (get-buffer- reate buffer))(insert-buffer-substring oldbuf start end)When the append-to-buffer fun tion is evaluated, the two expressionsin the body of the save-ex ursion are evaluated in sequen e. The value ofthe last expression is returned as the value of the save-ex ursion fun tion;the other expression is evaluated only for its side e�e ts.The �rst line in the body of the save-ex ursion uses the set-bufferfun tion to hange the urrent bu�er to the one spe i�ed in the �rst argumentto append-to-buffer. (Changing the bu�er is the side e�e t; as we havesaid before, in Lisp, a side e�e t is often the primary thing we want.) These ond line does the primary work of the fun tion.The set-buffer fun tion hanges Ema s' attention to the bu�er to whi hthe text will be opied and from whi h save-ex ursion will return.The line looks like this:(set-buffer (get-buffer- reate buffer))The innermost expression of this list is (get-buffer- reate buffer).This expression uses the get-buffer- reate fun tion, whi h either gets thenamed bu�er, or if it does not exist, reates one with the given name. Thismeans you an use append-to-buffer to put text into a bu�er that did notpreviously exist.get-buffer- reate also keeps set-buffer from getting an unne essaryerror: set-buffer needs a bu�er to go to; if you were to spe ify a bu�er thatdoes not exist, Ema s would baulk. Sin e get-buffer- reate will reate abu�er if none exists, set-buffer is always provided with a bu�er.

Page 78: An Introduction to Programming in Emacs Lisp

60 Chapter 4: A Few Bu�er{Related Fun tionsThe last line of append-to-buffer does the work of appending the text:(insert-buffer-substring oldbuf start end)The insert-buffer-substring fun tion opies a string from the bu�erspe i�ed as its �rst argument and inserts the string into the present bu�er.In this ase, the argument to insert-buffer-substring is the value of thevariable reated and bound by the let, namely the value of oldbuf, whi hwas the urrent bu�er when you gave the append-to-buffer ommand.After insert-buffer-substring has done its work, save-ex ursionwill restore the a tion to the original bu�er and append-to-buffer willhave done its job.Written in skeletal form, the workings of the body look like this:(let (bind-oldbuf-to-value-of- urrent-buffer)(save-ex ursion ; Keep tra k of bu�er. hange-bu�erinsert-substring-from-oldbuf-into-bu�er) hange-ba k-to-original-bu�er-when-�nishedlet-the-lo al-meaning-of-oldbuf-disappear-when-�nishedIn summary, append-to-bufferworks as follows: it saves the value of the urrent bu�er in the variable alled oldbuf. It gets the new bu�er, reatingone if need be, and swit hes Ema s to it. Using the value of oldbuf, itinserts the region of text from the old bu�er into the new bu�er; and thenusing save-ex ursion, it brings you ba k to your original bu�er.In looking at append-to-buffer, you have explored a fairly omplexfun tion. It shows how to use let and save-ex ursion, and how to hangeto and ome ba k from another bu�er. Many fun tion de�nitions use let,save-ex ursion, and set-buffer this way.4.5 ReviewHere is a brief summary of the various fun tions dis ussed in this hapter.des ribe-fun tiondes ribe-variablePrint the do umentation for a fun tion or variable. Convention-ally bound to C-h f and C-h v.find-tag Find the �le ontaining the sour e for a fun tion or variable andswit h bu�ers to it, positioning point at the beginning of theitem. Conventionally bound to M-. (that's a period followingthe hMETAi key).

Page 79: An Introduction to Programming in Emacs Lisp

Exer ises 61save-ex ursionSave the lo ation of point and mark and restore their values afterthe arguments to save-ex ursion have been evaluated. Also,remember the urrent bu�er and return to it.push-mark Set mark at a lo ation and re ord the value of the previous markon the mark ring. The mark is a lo ation in the bu�er that willkeep its relative position even if text is added to or removedfrom the bu�er.goto- har Set point to the lo ation spe i�ed by the value of the argument,whi h an be a number, a marker, or an expression that returnsthe number of a position, su h as (point-min).insert-buffer-substringCopy a region of text from a bu�er that is passed to the fun tionas an argument and insert the region into the urrent bu�er.mark-whole-bufferMark the whole bu�er as a region. Normally bound to C-x h.set-bufferSwit h the attention of Ema s to another bu�er, but do not hange the window being displayed. Used when the programrather than a human is to work on a di�erent bu�er.get-buffer- reateget-bufferFind a named bu�er or reate one if a bu�er of that name doesnot exist. The get-buffer fun tion returns nil if the namedbu�er does not exist.4.6 Exer ises� Write your own simplified-end-of-buffer fun tion de�nition; thentest it to see whether it works.� Use if and get-buffer to write a fun tion that prints a message tellingyou whether a bu�er exists.� Using find-tag, �nd the sour e for the opy-to-buffer fun tion.

Page 80: An Introduction to Programming in Emacs Lisp

62 Chapter 4: A Few Bu�er{Related Fun tions

Page 81: An Introduction to Programming in Emacs Lisp

The De�nition of opy-to-buffer 635 A Few More Complex Fun tionsIn this hapter, we build on what we have learned in previous hapters bylooking at more omplex fun tions. The opy-to-buffer fun tion illustratesuse of two save-ex ursion expressions in one de�nition, while the insert-buffer fun tion illustrates use of an asterisk in an intera tive expression,use of or, and the important distin tion between a name and the obje t towhi h the name refers.5.1 The De�nition of opy-to-bufferAfter understanding how append-to-buffer works, it is easy to under-stand opy-to-buffer. This fun tion opies text into a bu�er, but in-stead of adding to the se ond bu�er, it repla es the previous text in these ond bu�er. The ode for the opy-to-buffer fun tion is almost thesame as the ode for append-to-buffer, ex ept that erase-buffer anda se ond save-ex ursion are used. (See Se tion 4.4, \The De�nition ofappend-to-buffer", page 56, for the des ription of append-to-buffer.)The body of opy-to-buffer looks like this...(intera tive "BCopy to buffer: \nr")(let ((oldbuf ( urrent-buffer)))(save-ex ursion(set-buffer (get-buffer- reate buffer))(erase-buffer)(save-ex ursion(insert-buffer-substring oldbuf start end)))))This ode is similar to the ode in append-to-buffer: it is only after hanging to the bu�er to whi h the text will be opied that the de�nitionfor this fun tion diverges from the de�nition for append-to-buffer: the opy-to-buffer fun tion erases the bu�er's former ontents. (This is whatis meant by `repla ement'; to repla e text, Ema s erases the previous textand then inserts new text.) After erasing the previous ontents of the bu�er,save-ex ursion is used for a se ond time and the new text is inserted.Why is save-ex ursion used twi e? Consider again what the fun tiondoes.In outline, the body of opy-to-buffer looks like this:(let (bind-oldbuf-to-value-of- urrent-buffer)(save-ex ursion ; First use of save-ex ursion. hange-bu�er(erase-buffer)(save-ex ursion ; Se ond use of save-ex ursion.insert-substring-from-oldbuf-into-bu�er)))

Page 82: An Introduction to Programming in Emacs Lisp

64 Chapter 5: A Few More Complex Fun tionsThe �rst use of save-ex ursion returns Ema s to the bu�er from whi hthe text is being opied. That is lear, and is just like its use in append-to-buffer. Why the se ond use? The reason is that insert-buffer-substring always leaves point at the end of the region being inserted. These ond save-ex ursion auses Ema s to leave point at the beginning of thetext being inserted. In most ir umstan es, users prefer to �nd point at thebeginning of inserted text. (Of ourse, the opy-to-buffer fun tion returnsthe user to the original bu�er when done|but if the user then swit hes tothe opied-to bu�er, point will go to the beginning of the text. Thus, thisuse of a se ond save-ex ursion is a little ni ety.)5.2 The De�nition of insert-bufferinsert-buffer is yet another bu�er-related fun tion. This ommand opies another bu�er into the urrent bu�er. It is the reverse of append-to-buffer or opy-to-buffer, sin e they opy a region of text from the urrent bu�er to another bu�er.In addition, this ode illustrates the use of intera tive with a bu�erthat might be read-only and the important distin tion between the name ofan obje t and the obje t a tually referred to.Here is the ode:(defun insert-buffer (buffer)"Insert after point the ontents of BUFFER.Puts mark after the inserted text.BUFFER may be a buffer or a buffer name."(intera tive "*bInsert buffer: ")(or (bufferp buffer)(setq buffer (get-buffer buffer)))(let (start end newmark)(save-ex ursion(save-ex ursion(set-buffer buffer)(setq start (point-min) end (point-max)))(insert-buffer-substring buffer start end)(setq newmark (point)))(push-mark newmark)))As with other fun tion de�nitions, you an use a template to see anoutline of the fun tion:(defun insert-buffer (buffer)"do umentation..."(intera tive "*bInsert buffer: ")body...)

Page 83: An Introduction to Programming in Emacs Lisp

The Body of the insert-buffer Fun tion 655.2.1 The Intera tive Expression in insert-bufferIn insert-buffer, the argument to the intera tive de laration hastwo parts, an asterisk, `*', and `bInsert buffer: '.A Read-only Bu�erThe asterisk is for the situation when the bu�er is a read-only bu�er|a bu�er that annot be modi�ed. If insert-buffer is alled on a bu�erthat is read-only, a message to this e�e t is printed in the e ho area andthe terminal may beep or blink at you; you will not be permitted to insertanything into urrent bu�er. The asterisk does not need to be followed by anewline to separate it from the next argument.`b' in an Intera tive ExpressionThe next argument in the intera tive expression starts with a lower ase`b'. (This is di�erent from the ode for append-to-buffer, whi h uses anupper- ase `B'. See Se tion 4.4, \The De�nition of append-to-buffer",page 56.) The lower- ase `b' tells the Lisp interpreter that the argument forinsert-buffer should be an existing bu�er or else its name. (The upper- ase `B' option provides for the possibility that the bu�er does not exist.)Ema s will prompt you for the name of the bu�er, o�ering you a defaultbu�er, with name ompletion enabled. If the bu�er does not exist, youre eive a message that says \No mat h"; your terminal may beep at you aswell.5.2.2 The Body of the insert-buffer Fun tionThe body of the insert-buffer fun tion has two major parts: an orexpression and a let expression. The purpose of the or expression is toensure that the argument buffer is bound to a bu�er and not just the nameof a bu�er. The body of the let expression ontains the ode whi h opiesthe other bu�er into the urrent bu�er.In outline, the two expressions �t into the insert-buffer fun tion likethis:(defun insert-buffer (buffer)"do umentation..."(intera tive "*bInsert buffer: ")(or ......(let (varlist)body-of-let... )

Page 84: An Introduction to Programming in Emacs Lisp

66 Chapter 5: A Few More Complex Fun tionsTo understand how the or expression ensures that the argument bufferis bound to a bu�er and not to the name of a bu�er, it is �rst ne essary tounderstand the or fun tion.Before doing this, let me rewrite this part of the fun tion using if so thatyou an see what is done in a manner that will be familiar.5.2.3 insert-buffer With an if Instead of an orThe job to be done is to make sure the value of buffer is a bu�er itselfand not the name of a bu�er. If the value is the name, then the bu�er itselfmust be got.You an imagine yourself at a onferen e where an usher is wanderingaround holding a list with your name on it and looking for you: the usher is\bound" to your name, not to you; but when the usher �nds you and takesyour arm, the usher be omes \bound" to you.In Lisp, you might des ribe this situation like this:(if (not (holding-on-to-guest))(find-and-take-arm-of-guest))We want to do the same thing with a bu�er|if we do not have the bu�eritself, we want to get it.Using a predi ate alled bufferp that tells us whether we have a bu�er(rather than its name), we an write the ode like this:(if (not (bufferp buffer)) ; if-part(setq buffer (get-buffer buffer))) ; then-partHere, the true-or-false-test of the if expression is (not (bufferp buffer));and the then-part is the expression (setq buffer (get-buffer buffer)).In the test, the fun tion bufferp returns true if its argument is a bu�er|but false if its argument is the name of the bu�er. (The last hara ter ofthe fun tion name bufferp is the hara ter `p'; as we saw earlier, su h useof `p' is a onvention that indi ates that the fun tion is a predi ate, whi h isa term that means that the fun tion will determine whether some propertyis true or false. See Se tion 1.8.4, \Using the Wrong Type Obje t as anArgument", page 14.)The fun tion not pre edes the expression (bufferp buffer), so the true-or-false-test looks like this:(not (bufferp buffer))not is a fun tion that returns true if its argument is false and false if itsargument is true. So if (bufferp buffer) returns true, the not expressionreturns false and vi e-versa: what is \not true" is false and what is \notfalse" is true.Using this test, the if expression works as follows: when the value ofthe variable buffer is a tually a bu�er rather then its name, the true-or-false-test returns false and the if expression does not evaluate the then-part.

Page 85: An Introduction to Programming in Emacs Lisp

The or in the Body 67This is �ne, sin e we do not need to do anything to the variable buffer if itreally is a bu�er.On the other hand, when the value of buffer is not a bu�er itself, butthe name of a bu�er, the true-or-false-test returns true and the then-partof the expression is evaluated. In this ase, the then-part is (setq buffer(get-buffer buffer)). This expression uses the get-buffer fun tion toreturn an a tual bu�er itself, given its name. The setq then sets the variablebuffer to the value of the bu�er itself, repla ing its previous value (whi hwas the name of the bu�er).5.2.4 The or in the BodyThe purpose of the or expression in the insert-buffer fun tion is toensure that the argument buffer is bound to a bu�er and not just to thename of a bu�er. The previous se tion shows how the job ould have beendone using an if expression. However, the insert-buffer fun tion a tuallyuses or. To understand this, it is ne essary to understand how or works.An or fun tion an have any number of arguments. It evaluates ea hargument in turn and returns the value of the �rst of its arguments that isnot nil. Also, and this is a ru ial feature of or, it does not evaluate anysubsequent arguments after returning the �rst non-nil value.The or expression looks like this:(or (bufferp buffer)(setq buffer (get-buffer buffer)))The �rst argument to or is the expression (bufferp buffer). This expres-sion returns true (a non-nil value) if the bu�er is a tually a bu�er, andnot just the name of a bu�er. In the or expression, if this is the ase,the or expression returns this true value and does not evaluate the nextexpression|and this is �ne with us, sin e we do not want to do anything tothe value of buffer if it really is a bu�er.On the other hand, if the value of (bufferp buffer) is nil, whi h it willbe if the value of buffer is the name of a bu�er, the Lisp interpreter evaluatesthe next element of the or expression. This is the expression (setq buffer(get-buffer buffer)). This expression returns a non-nil value, whi h isthe value to whi h it sets the variable buffer|and this value is a bu�eritself, not the name of a bu�er.The result of all this is that the symbol buffer is always bound to a bu�eritself rather than to the name of a bu�er. All this is ne essary be ause theset-buffer fun tion in a following line only works with a bu�er itself, notwith the name to a bu�er.

Page 86: An Introduction to Programming in Emacs Lisp

68 Chapter 5: A Few More Complex Fun tionsIn identally, using or, the situation with the usher would be written likethis:(or (holding-on-to-guest) (find-and-take-arm-of-guest))5.2.5 The let Expression in insert-bufferAfter ensuring that the variable buffer refers to a bu�er itself and notjust to the name of a bu�er, the insert-buffer fun tion ontinues with alet expression. This spe i�es three lo al variables, start, end, and newmarkand binds them to the initial value nil. These variables are used inside theremainder of the let and temporarily hide any other o urren e of variablesof the same name in Ema s until the end of the let.The body of the let ontains two save-ex ursion expressions. First, wewill look at the inner save-ex ursion expression in detail. The expressionlooks like this:(save-ex ursion(set-buffer buffer)(setq start (point-min) end (point-max)))The expression (set-buffer buffer) hanges Ema s' attention from the urrent bu�er to the one from whi h the text will opied. In that bu�er,the variables start and end are set to the beginning and end of the bu�er,using the ommands point-min and point-max. Note that we have here anillustration of how setq is able to set two variables in the same expression.The �rst argument of setq is set to the value of its se ond, and its thirdargument is set to the value of its fourth.After the body of the inner save-ex ursion is evaluated, the save-ex ursion restores the original bu�er, but start and end remain set to thevalues of the beginning and end of the bu�er from whi h the text will be opied.The outer save-ex ursion expression looks like this:(save-ex ursion(inner-save-ex ursion-expression(go-to-new-bu�er-and-set-start-and-end)(insert-buffer-substring buffer start end)(setq newmark (point)))The insert-buffer-substring fun tion opies the text into the urrentbu�er from the region indi ated by start and end in buffer. Sin e thewhole of the se ond bu�er lies between start and end, the whole of these ond bu�er is opied into the bu�er you are editing. Next, the value ofpoint, whi h will be at the end of the inserted text, is re orded in the variablenewmark.After the body of the outer save-ex ursion is evaluated, point and markare relo ated to their original pla es.

Page 87: An Introduction to Programming in Emacs Lisp

Optional Arguments 69However, it is onvenient to lo ate a mark at the end of the newly insertedtext and lo ate point at its beginning. The newmark variable re ords the endof the inserted text. In the last line of the let expression, the (push-marknewmark) expression fun tion sets a mark to this lo ation. (The previouslo ation of the mark is still a essible; it is re orded on the mark ring andyou an go ba k to it with C-u C-hSPCi.) Meanwhile, point is lo ated at thebeginning of the inserted text, whi h is where it was before you alled theinsert fun tion.The whole let expression looks like this:(let (start end newmark)(save-ex ursion(save-ex ursion(set-buffer buffer)(setq start (point-min) end (point-max)))(insert-buffer-substring buffer start end)(setq newmark (point)))(push-mark newmark))Like the append-to-buffer fun tion, the insert-buffer fun tion useslet, save-ex ursion, and set-buffer. In addition, the fun tion illustratesone way to use or. All these fun tions are building blo ks that we will �ndand use again and again.5.3 Complete De�nition of beginning-of-bufferThe basi stru ture of the beginning-of-buffer fun tion has alreadybeen dis ussed. (See Se tion 4.2, \A Simpli�ed beginning-of-buffer Def-inition", page 52.) This se tion des ribes the omplex part of the de�nition.As previously des ribed, when invoked without an argument, beginning-of-buffer moves the ursor to the beginning of the bu�er, leaving the markat the previous position. However, when the ommand is invoked with anumber between one and ten, the fun tion onsiders that number to be afra tion of the length of the bu�er, measured in tenths, and Ema s movesthe ursor that fra tion of the way from the beginning of the bu�er. Thus,you an either all this fun tion with the key ommand M-<, whi h will movethe ursor to the beginning of the bu�er, or with a key ommand su h asC-u 7 M-< whi h will move the ursor to a point 70% of the way through thebu�er. If a number bigger than ten is used for the argument, it moves tothe end of the bu�er.The beginning-of-buffer fun tion an be alled with or without anargument. The use of the argument is optional.

Page 88: An Introduction to Programming in Emacs Lisp

70 Chapter 5: A Few More Complex Fun tions5.3.1 Optional ArgumentsUnless told otherwise, Lisp expe ts that a fun tion with an argument inits fun tion de�nition will be alled with a value for that argument. If thatdoes not happen, you get an error and a message that says `Wrong numberof arguments'.However, optional arguments are a feature of Lisp: a keyword may beused to tell the Lisp interpreter that an argument is optional. The keywordis &optional. (The `&' in front of `optional' is part of the keyword.) In afun tion de�nition, if an argument follows the keyword &optional, a valuedoes not need to be passed to that argument when the fun tion is alled.The �rst line of the fun tion de�nition of beginning-of-buffer thereforelooks like this:(defun beginning-of-buffer (&optional arg)In outline, the whole fun tion looks like this:(defun beginning-of-buffer (&optional arg)"do umentation..."(intera tive "P")(push-mark)(goto- har(if-there-is-an-argument�gure-out-where-to-goelse-go-to(point-min))))The fun tion is similar to the simplified-beginning-of-buffer fun -tion ex ept that the intera tive expression has "P" as an argument andthe goto- har fun tion is followed by an if-then-else expression that �guresout where to put the ursor if there is an argument.The "P" in the intera tive expression tells Ema s to pass a pre�xargument, if there is one, to the fun tion. A pre�x argument is made bytyping the hMETAi key followed by a number, or by typing C-u and then anumber (if you don't type a number, C-u defaults to 4).The true-or-false-test of the if expression is simple: it is simply theargument arg. If arg has a value that is not nil, whi h will be the ase ifbeginning-of-buffer is alled with an argument, then this true-or-false-test will return true and the then-part of the if expression will be evaluated.On the other hand, if beginning-of-buffer is not alled with an argument,the value of arg will be nil and the else-part of the if expression will beevaluated. The else-part is simply point-min, and when this is the out ome,the whole goto- har expression is (goto- har (point-min)), whi h is howwe saw the beginning-of-buffer fun tion in its simpli�ed form.

Page 89: An Introduction to Programming in Emacs Lisp

What happens in a large bu�er 715.3.2 beginning-of-buffer with an ArgumentWhen beginning-of-buffer is alled with an argument, an expression isevaluated whi h al ulates what value to pass to goto- har. This expressionis rather ompli ated at �rst sight. It in ludes an inner if expression andmu h arithmeti . It looks like this:(if (> (buffer-size) 10000);; Avoid over ow for large bu�er sizes!(* (prefix-numeri -value arg) (/ (buffer-size) 10))(/(+ 10(*(buffer-size) (prefix-numeri -value arg))) 10))Like other omplex-looking expressions, the onditional expression withinbeginning-of-buffer an be disentangled by looking at it as parts of atemplate, in this ase, the template for an if-then-else expression. In skeletalform, the expression looks like this:(if (bu�er-is-largedivide-bu�er-size-by-10-and-multiply-by-argelse-use-alternate- al ulationThe true-or-false-test of this inner if expression he ks the size of thebu�er. The reason for this is that the old Version 18 Ema s used numbersthat are no bigger than eight million or so and in the omputation thatfollowed, the programmer feared that Ema s might try to use over-largenumbers if the bu�er were large. The term `over ow', mentioned in the omment, means numbers that are over large. Version 21 Ema s uses largernumbers, but this ode has not been tou hed, if only be ause people nowlook at bu�ers that are far, far larger than ever before.There are two ases: if the bu�er is large and if it is not.What happens in a large bu�erIn beginning-of-buffer, the inner if expression tests whether the sizeof the bu�er is greater than 10,000 hara ters. To do this, it uses the >fun tion and the buffer-size fun tion.The line looks like this:(if (> (buffer-size) 10000)When the bu�er is large, the then-part of the if expression is evaluated. Itreads like this (after formatting for easy reading):(*(prefix-numeri -value arg)(/ (buffer-size) 10))This expression is a multipli ation, with two arguments to the fun tion *.

Page 90: An Introduction to Programming in Emacs Lisp

72 Chapter 5: A Few More Complex Fun tionsThe �rst argument is (prefix-numeri -value arg). When "P" is usedas the argument for intera tive, the value passed to the fun tion as itsargument is passed a \raw pre�x argument", and not a number. (It is anumber in a list.) To perform the arithmeti , a onversion is ne essary, andprefix-numeri -value does the job.The se ond argument is (/ (buffer-size) 10). This expression dividesthe numeri value of the bu�er by ten. This produ es a number that tellshow many hara ters make up one tenth of the bu�er size. (In Lisp, / isused for division, just as * is used for multipli ation.)In the multipli ation expression as a whole, this amount is multiplied bythe value of the pre�x argument|the multipli ation looks like this:(* numeri -value-of-pre�x-argnumber-of- hara ters-in-one-tenth-of-the-bu�er)If, for example, the pre�x argument is `7', the one-tenth value will be mul-tiplied by 7 to give a position 70% of the way through the bu�er.The result of all this is that if the bu�er is large, the goto- har expressionreads like this:(goto- har (* (prefix-numeri -value arg)(/ (buffer-size) 10)))This puts the ursor where we want it.What happens in a small bu�erIf the bu�er ontains fewer than 10,000 hara ters, a slightly di�erent omputation is performed. You might think this is not ne essary, sin ethe �rst omputation ould do the job. However, in a small bu�er, the�rst method may not put the ursor on exa tly the desired line; the se ondmethod does a better job.The ode looks like this:(/ (+ 10 (* (buffer-size) (prefix-numeri -value arg))) 10))This is ode in whi h you �gure out what happens by dis overing how thefun tions are embedded in parentheses. It is easier to read if you reformatit with ea h expression indented more deeply than its en losing expression:(/(+ 10(*(buffer-size)(prefix-numeri -value arg)))10))

Page 91: An Introduction to Programming in Emacs Lisp

The Complete beginning-of-buffer 73Looking at parentheses, we see that the innermost operation is (prefix-numeri -value arg), whi h onverts the raw argument to a number. Thisnumber is multiplied by the bu�er size in the following expression:(* (buffer-size) (prefix-numeri -value arg)This multipli ation reates a number that may be larger than the size ofthe bu�er|seven times larger if the argument is 7, for example. Ten isthen added to this number and �nally the large number is divided by ten toprovide a value that is one hara ter larger than the per entage position inthe bu�er.The number that results from all this is passed to goto- har and the ursor is moved to that point.5.3.3 The Complete beginning-of-bufferHere is the omplete text of the beginning-of-buffer fun tion:(defun beginning-of-buffer (&optional arg)"Move point to the beginning of the buffer;leave mark at previous position.With arg N, put point N/10 of the wayfrom the true beginning.Don't use this in Lisp programs!\(goto- har (point-min)) is fasterand does not set the mark."(intera tive "P")(push-mark)(goto- har(if arg(if (> (buffer-size) 10000);; Avoid over ow for large bu�er sizes!(* (prefix-numeri -value arg)(/ (buffer-size) 10))(/ (+ 10 (* (buffer-size)(prefix-numeri -value arg)))10))(point-min)))(if arg (forward-line 1)))Ex ept for two small points, the previous dis ussion shows how this fun tionworks. The �rst point deals with a detail in the do umentation string, andthe se ond point on erns the last line of the fun tion.In the do umentation string, there is referen e to an expression:\(goto- har (point-min))A `\' is used before the �rst parenthesis of this expression. This `\' tellsthe Lisp interpreter that the expression should be printed as shown in the

Page 92: An Introduction to Programming in Emacs Lisp

74 Chapter 5: A Few More Complex Fun tionsdo umentation rather than evaluated as a symboli expression, whi h is whatit looks like.Finally, the last line of the beginning-of-buffer ommand says to movepoint to the beginning of the next line if the ommand is invoked with anargument:(if arg (forward-line 1)))This puts the ursor at the beginning of the �rst line after the appropriatetenths position in the bu�er. This is a ourish that means that the ursor isalways lo ated at least the requested tenths of the way through the bu�er,whi h is a ni ety that is, perhaps, not ne essary, but whi h, if it did noto ur, would be sure to draw omplaints.5.4 ReviewHere is a brief summary of some of the topi s overed in this hapter.or Evaluate ea h argument in sequen e, and return the value ofthe �rst argument that is not nil; if none return a value thatis not nil, return nil. In brief, return the �rst true value ofthe arguments; return a true value if one or any of the other aretrue.and Evaluate ea h argument in sequen e, and if any are nil, returnnil; if none are nil, return the value of the last argument. Inbrief, return a true value only if all the arguments are true;return a true value if one and ea h of the others is true.&optional A keyword used to indi ate that an argument to a fun tion de�-nition is optional; this means that the fun tion an be evaluatedwithout the argument, if desired.prefix-numeri -valueConvert the `raw pre�x argument' produ ed by (intera tive"P") to a numeri value.forward-lineMove point forward to the beginning of the next line, or if theargument is greater than one, forward that many lines. If it an't move as far forward as it is supposed to, forward-linegoes forward as far as it an and then returns a ount of thenumber of additional lines it was supposed to move but ouldn't.erase-bufferDelete the entire ontents of the urrent bu�er.bufferp Return t if its argument is a bu�er; otherwise return nil.

Page 93: An Introduction to Programming in Emacs Lisp

optional Argument Exer ise 755.5 optional Argument Exer iseWrite an intera tive fun tion with an optional argument that testswhether its argument, a number, is greater or less than the value of fill- olumn, and tells you whi h, in a message. However, if you do not pass anargument to the fun tion, use 56 as a default value.

Page 94: An Introduction to Programming in Emacs Lisp

76 Chapter 5: A Few More Complex Fun tions

Page 95: An Introduction to Programming in Emacs Lisp

The save-restri tion Spe ial Form 776 Narrowing and WideningNarrowing is a feature of Ema s that makes it possible for you to fo uson a spe i� part of a bu�er, and work without a identally hanging otherparts. Narrowing is normally disabled sin e it an onfuse novi es.With narrowing, the rest of a bu�er is made invisible, as if it weren'tthere. This is an advantage if, for example, you want to repla e a word inone part of a bu�er but not in another: you narrow to the part you wantand the repla ement is arried out only in that se tion, not in the rest ofthe bu�er. Sear hes will only work within a narrowed region, not outside ofone, so if you are �xing a part of a do ument, you an keep yourself froma identally �nding parts you do not need to �x by narrowing just to theregion you want. (The key binding for narrow-to-region is C-x n n.)However, narrowing does make the rest of the bu�er invisible, whi h ans are people who inadvertently invoke narrowing and think they have deleteda part of their �le. Moreover, the undo ommand (whi h is usually boundto C-x u) does not turn o� narrowing (nor should it), so people an be omequite desperate if they do not know that they an return the rest of a bu�erto visibility with the widen ommand. (The key binding for widen is C-x nw.) Narrowing is just as useful to the Lisp interpreter as to a human. Often,an Ema s Lisp fun tion is designed to work on just part of a bu�er; or onversely, an Ema s Lisp fun tion needs to work on all of a bu�er thathas been narrowed. The what-line fun tion, for example, removes thenarrowing from a bu�er, if it has any narrowing and when it has �nished itsjob, restores the narrowing to what it was. On the other hand, the ount-lines fun tion, whi h is alled by what-line, uses narrowing to restri titself to just that portion of the bu�er in whi h it is interested and thenrestores the previous situation.6.1 The save-restri tion Spe ial FormIn Ema s Lisp, you an use the save-restri tion spe ial form to keeptra k of whatever narrowing is in e�e t, if any. When the Lisp interpretermeets with save-restri tion, it exe utes the ode in the body of the save-restri tion expression, and then undoes any hanges to narrowing that the ode aused. If, for example, the bu�er is narrowed and the ode that followssave-restri tion gets rid of the narrowing, save-restri tion returns thebu�er to its narrowed region afterwards. In the what-line ommand, anynarrowing the bu�er may have is undone by the widen ommand that im-mediately follows the save-restri tion ommand. Any original narrowingis restored just before the ompletion of the fun tion.

Page 96: An Introduction to Programming in Emacs Lisp

78 Chapter 6: Narrowing and WideningThe template for a save-restri tion expression is simple:(save-restri tionbody... )The body of the save-restri tion is one or more expressions that will beevaluated in sequen e by the Lisp interpreter.Finally, a point to note: when you use both save-ex ursion and save-restri tion, one right after the other, you should use save-ex ursion out-ermost. If you write them in reverse order, you may fail to re ord narrowingin the bu�er to whi h Ema s swit hes after alling save-ex ursion. Thus,when written together, save-ex ursion and save-restri tion should bewritten like this:(save-ex ursion(save-restri tionbody...))In other ir umstan es, when not written together, the save-ex ursionand save-restri tion spe ial forms must be written in the order appro-priate to the fun tion.For example,(save-restri tion(widen)(save-ex ursionbody...))6.2 what-lineThe what-line ommand tells you the number of the line in whi h the ursor is lo ated. The fun tion illustrates the use of the save-restri tionand save-ex ursion ommands. Here is the text of the fun tion in full:(defun what-line ()"Print the urrent line number (in the buffer) of point."(intera tive)(save-restri tion(widen)(save-ex ursion(beginning-of-line)(message "Line %d"(1+ ( ount-lines 1 (point)))))))The fun tion has a do umentation line and is intera tive, as you wouldexpe t. The next two lines use the fun tions save-restri tion and widen.The save-restri tion spe ial form notes whatever narrowing is in ef-fe t, if any, in the urrent bu�er and restores that narrowing after the odein the body of the save-restri tion has been evaluated.

Page 97: An Introduction to Programming in Emacs Lisp

Exer ise with Narrowing 79The save-restri tion spe ial form is followed by widen. This fun tionundoes any narrowing the urrent bu�er may have had when what-linewas alled. (The narrowing that was there is the narrowing that save-restri tion remembers.) This widening makes it possible for the line ounting ommands to ount from the beginning of the bu�er. Otherwise,they would have been limited to ounting within the a essible region. Anyoriginal narrowing is restored just before the ompletion of the fun tion bythe save-restri tion spe ial form.The all to widen is followed by save-ex ursion, whi h saves the lo a-tion of the ursor (i.e., of point) and of the mark, and restores them afterthe ode in the body of the save-ex ursion uses the beginning-of-linefun tion to move point.(Note that the (widen) expression omes between the save-restri tionand save-ex ursion spe ial forms. When you write the two save- ...expressions in sequen e, write save-ex ursion outermost.)The last two lines of the what-line fun tion are fun tions to ount thenumber of lines in the bu�er and then print the number in the e ho area.(message "Line %d"(1+ ( ount-lines 1 (point)))))))The message fun tion prints a one-line message at the bottom of theEma s s reen. The �rst argument is inside of quotation marks and is printedas a string of hara ters. However, it may ontain `%d', `%s', or `% ' to printarguments that follow the string. `%d' prints the argument as a de imal, sothe message will say something su h as `Line 243'.The number that is printed in pla e of the `%d' is omputed by the lastline of the fun tion:(1+ ( ount-lines 1 (point)))What this does is ount the lines from the �rst position of the bu�er, indi- ated by the 1, up to (point), and then add one to that number. (The 1+fun tion adds one to its argument.) We add one to it be ause line 2 has onlyone line before it, and ount-lines ounts only the lines before the urrentline.After ount-lines has done its job, and the message has been printed inthe e ho area, the save-ex ursion restores point and mark to their originalpositions; and save-restri tion restores the original narrowing, if any.6.3 Exer ise with NarrowingWrite a fun tion that will display the �rst 60 hara ters of the urrentbu�er, even if you have narrowed the bu�er to its latter half so that the �rstline is ina essible. Restore point, mark, and narrowing. For this exer ise,you need to use save-restri tion, widen, goto- har, point-min, buffer-substring, message, and other fun tions, a whole potpourri.

Page 98: An Introduction to Programming in Emacs Lisp

80 Chapter 6: Narrowing and Widening

Page 99: An Introduction to Programming in Emacs Lisp

ar and dr 817 ar, dr, ons: Fundamental Fun tionsIn Lisp, ar, dr, and ons are fundamental fun tions. The ons fun tionis used to onstru t lists, and the ar and dr fun tions are used to takethem apart.In the walk through of the opy-region-as-kill fun tion, we will see ons as well as two variants on dr, namely, set dr and nth dr. (SeeSe tion 8.5, \ opy-region-as-kill", page 102.)The name of the ons fun tion is not unreasonable: it is an abbreviationof the word ` onstru t'. The origins of the names for ar and dr, on theother hand, are esoteri : ar is an a ronym from the phrase `Contents ofthe Address part of the Register'; and dr (pronoun ed ` ould-er') is ana ronym from the phrase `Contents of the De rement part of the Register'.These phrases refer to spe i� pie es of hardware on the very early omputeron whi h the original Lisp was developed. Besides being obsolete, the phraseshave been ompletely irrelevant for more than 25 years to anyone thinkingabout Lisp. Nonetheless, although a few brave s holars have begun to usemore reasonable names for these fun tions, the old terms are still in use. Inparti ular, sin e the terms are used in the Ema s Lisp sour e ode, we willuse them in this introdu tion.7.1 ar and drThe ar of a list is, quite simply, the �rst item in the list. Thus the arof the list (rose violet daisy butter up) is rose.If you are reading this in Info in GNU Ema s, you an see this by evalu-ating the following:( ar '(rose violet daisy butter up))After evaluating the expression, rose will appear in the e ho area.Clearly, a more reasonable name for the ar fun tion would be firstand this is often suggested. ar does not remove the �rst item from the list; it only reports what itis. After ar has been applied to a list, the list is still the same as it was. Inthe jargon, ar is `non-destru tive'. This feature turns out to be important.The dr of a list is the rest of the list, that is, the dr fun tion returnsthe part of the list that follows the �rst item. Thus, while the ar of thelist '(rose violet daisy butter up) is rose, the rest of the list, the valuereturned by the dr fun tion, is (violet daisy butter up).

Page 100: An Introduction to Programming in Emacs Lisp

82 Chapter 7: ar, dr, ons: Fundamental Fun tionsYou an see this by evaluating the following in the usual way:( dr '(rose violet daisy butter up))When you evaluate this, (violet daisy butter up) will appear in the e hoarea.Like ar, dr does not remove any elements from the list|it just returnsa report of what the se ond and subsequent elements are.In identally, in the example, the list of owers is quoted. If it were not, theLisp interpreter would try to evaluate the list by alling rose as a fun tion.In this example, we do not want to do that.Clearly, a more reasonable name for dr would be rest.(There is a lesson here: when you name new fun tions, onsider very arefully what you are doing, sin e you may be stu k with the names for farlonger than you expe t. The reason this do ument perpetuates these namesis that the Ema s Lisp sour e ode uses them, and if I did not use them,you would have a hard time reading the ode; but do, please, try to avoidusing these terms yourself. The people who ome after you will be gratefulto you.)When ar and dr are applied to a list made up of symbols, su h as thelist (pine fir oak maple), the element of the list returned by the fun tion ar is the symbol pine without any parentheses around it. pine is the �rstelement in the list. However, the dr of the list is a list itself, (fir oakmaple), as you an see by evaluating the following expressions in the usualway:( ar '(pine fir oak maple))( dr '(pine fir oak maple))On the other hand, in a list of lists, the �rst element is itself a list. arreturns this �rst element as a list. For example, the following list ontainsthree sub-lists, a list of arnivores, a list of herbivores and a list of seamammals:( ar '((lion tiger heetah)(gazelle antelope zebra)(whale dolphin seal)))In this example, the �rst element or ar of the list is the list of arnivores,(lion tiger heetah), and the rest of the list is ((gazelle antelopezebra) (whale dolphin seal)).( dr '((lion tiger heetah)(gazelle antelope zebra)(whale dolphin seal)))It is worth saying again that ar and dr are non-destru tive|that is,they do not modify or hange lists to whi h they are applied. This is veryimportant for how they are used.

Page 101: An Introduction to Programming in Emacs Lisp

ons 83Also, in the �rst hapter, in the dis ussion about atoms, I said that inLisp, \ ertain kinds of atom, su h as an array, an be separated into parts;but the me hanism for doing this is di�erent from the me hanism for splittinga list. As far as Lisp is on erned, the atoms of a list are unsplittable."(See Se tion 1.1.1, \Lisp Atoms", page 1.) The ar and dr fun tions areused for splitting lists and are onsidered fundamental to Lisp. Sin e they annot split or gain a ess to the parts of an array, an array is onsidered anatom. Conversely, the other fundamental fun tion, ons, an put togetheror onstru t a list, but not an array. (Arrays are handled by array-spe i� fun tions. See se tion \Arrays" in The GNU Ema s Lisp Referen e Manual.)7.2 onsThe ons fun tion onstru ts lists; it is the inverse of ar and dr. Forexample, ons an be used to make a four element list from the three elementlist, (fir oak maple):( ons 'pine '(fir oak maple))After evaluating this list, you will see(pine fir oak maple)appear in the e ho area. ons puts a new element at the beginning of a list;it atta hes or pushes elements onto the list. ons must have a list to atta h to.1 You annot start from absolutelynothing. If you are building a list, you need to provide at least an emptylist at the beginning. Here is a series of ons expressions that build up a listof owers. If you are reading this in Info in GNU Ema s, you an evaluateea h of the expressions in the usual way; the value is printed in this textafter `)', whi h you may read as `evaluates to'.( ons 'butter up ())) (butter up)( ons 'daisy '(butter up))) (daisy butter up)( ons 'violet '(daisy butter up))) (violet daisy butter up)( ons 'rose '(violet daisy butter up))) (rose violet daisy butter up)In the �rst example, the empty list is shown as () and a list made upof butter up followed by the empty list is onstru ted. As you an see,the empty list is not shown in the list that was onstru ted. All that yousee is (butter up). The empty list is not ounted as an element of a list1 A tually, you an ons an element to an atom to produ e a dotted pair. Dotted pairsare not dis ussed here; see se tion \Dotted Pair Notation" in The GNU Ema s LispReferen e Manual.

Page 102: An Introduction to Programming in Emacs Lisp

84 Chapter 7: ar, dr, ons: Fundamental Fun tionsbe ause there is nothing in an empty list. Generally speaking, an empty listis invisible.The se ond example, ( ons 'daisy '(butter up)) onstru ts a new,two element list by putting daisy in front of butter up; and the thirdexample onstru ts a three element list by putting violet in front of daisyand butter up.7.2.1 Find the Length of a List: lengthYou an �nd out how many elements there are in a list by using the Lispfun tion length, as in the following examples:(length '(butter up))) 1(length '(daisy butter up))) 2(length ( ons 'violet '(daisy butter up)))) 3In the third example, the ons fun tion is used to onstru t a three elementlist whi h is then passed to the length fun tion as its argument.We an also use length to ount the number of elements in an emptylist: (length ())) 0As you would expe t, the number of elements in an empty list is zero.An interesting experiment is to �nd out what happens if you try to �ndthe length of no list at all; that is, if you try to all length without givingit an argument, not even an empty list:(length )What you see, if you evaluate this, is the error messageWrong number of arguments: #<subr length>, 0This means that the fun tion re eives the wrong number of arguments, zero,when it expe ts some other number of arguments. In this ase, one argumentis expe ted, the argument being a list whose length the fun tion is measuring.(Note that one list is one argument, even if the list has many elements insideit.)The part of the error message that says `#<subr length>' is the name ofthe fun tion. This is written with a spe ial notation, `#<subr', that indi atesthat the fun tion length is one of the primitive fun tions written in C ratherthan in Ema s Lisp. (`subr' is an abbreviation for `subroutine'.) See se tion\What Is a Fun tion?" in The GNU Ema s Lisp Referen e Manual, for moreabout subroutines.

Page 103: An Introduction to Programming in Emacs Lisp

nth dr 857.3 nth drThe nth dr fun tion is asso iated with the dr fun tion. What it doesis take the dr of a list repeatedly.If you take the dr of the list (pine fir oak maple), you will be returnedthe list (fir oak maple). If you repeat this on what was returned, youwill be returned the list (oak maple). (Of ourse, repeated dring on theoriginal list will just give you the original dr sin e the fun tion does not hange the list. You need to evaluate the dr of the dr and so on.) If you ontinue this, eventually you will be returned an empty list, whi h in this ase, instead of being shown as () is shown as nil.For review, here is a series of repeated drs, the text following the `)'shows what is returned.( dr '(pine fir oak maple)))(fir oak maple)( dr '(fir oak maple))) (oak maple)( dr '(oak maple)))(maple)( dr '(maple))) nil( dr 'nil)) nil( dr ())) nilYou an also do several drs without printing the values in between, likethis:( dr ( dr '(pine fir oak maple)))) (oak maple)In this example, the Lisp interpreter evaluates the innermost list �rst. Theinnermost list is quoted, so it just passes the list as it is to the innermost dr.This dr passes a list made up of the se ond and subsequent elements of thelist to the outermost dr, whi h produ es a list omposed of the third andsubsequent elements of the original list. In this example, the dr fun tion isrepeated and returns a list that onsists of the original list without its �rsttwo elements.The nth dr fun tion does the same as repeating the all to dr. In thefollowing example, the argument 2 is passed to the fun tion nth dr, alongwith the list, and the value returned is the list without its �rst two items,whi h is exa tly the same as repeating dr twi e on the list:(nth dr 2 '(pine fir oak maple))) (oak maple)

Page 104: An Introduction to Programming in Emacs Lisp

86 Chapter 7: ar, dr, ons: Fundamental Fun tionsUsing the original four element list, we an see what happens when variousnumeri arguments are passed to nth dr, in luding 0, 1, and 5:;; Leave the list as it was.(nth dr 0 '(pine fir oak maple))) (pine fir oak maple);; Return a opy without the �rst element.(nth dr 1 '(pine fir oak maple))) (fir oak maple);; Return a opy of the list without three elements.(nth dr 3 '(pine fir oak maple))) (maple);; Return a opy la king all four elements.(nth dr 4 '(pine fir oak maple))) nil;; Return a opy la king all elements.(nth dr 5 '(pine fir oak maple))) nil7.4 nthThe nth dr fun tion takes the dr of a list repeatedly. The nth fun tiontakes the ar of the result returned by nth dr. It returns the Nth elementof the list.Thus, if it were not de�ned in C for speed, the de�nition of nth wouldbe: (defun nth (n list)"Returns the Nth element of LIST.N ounts from zero. If LIST is not that long, nil is returned."( ar (nth dr n list)))(Originally, nth was de�ned in Ema s Lisp in `subr.el', but its de�nitionwas redone in C in the 1980s.)The nth fun tion returns a single element of a list. This an be very onvenient.Note that the elements are numbered from zero, not one. That is tosay, the �rst element of a list, its ar is the zeroth element. This is alled`zero-based' ounting and often bothers people who are a ustomed to the�rst element in a list being number one, whi h is `one-based'.

Page 105: An Introduction to Programming in Emacs Lisp

set dr 87For example:(nth 0 '("one" "two" "three"))) "one"(nth 1 '("one" "two" "three"))) "two"It is worth mentioning that nth, like nth dr and dr, does not hangethe original list|the fun tion is non-destru tive. This is in sharp ontrastto the set ar and set dr fun tions.7.5 set arAs you might guess from their names, the set ar and set dr fun tionsset the ar or the dr of a list to a new value. They a tually hange theoriginal list, unlike ar and dr whi h leave the original list as it was. Oneway to �nd out how this works is to experiment. We will start with theset ar fun tion.First, we an make a list and then set the value of a variable to the list,using the setq fun tion. Here is a list of animals:(setq animals '(antelope giraffe lion tiger))If you are reading this in Info inside of GNU Ema s, you an evaluate thisexpression in the usual fashion, by positioning the ursor after the expressionand typing C-x C-e. (I'm doing this right here as I write this. This isone of the advantages of having the interpreter built into the omputingenvironment.)When we evaluate the variable animals, we see that it is bound to thelist (antelope giraffe lion tiger):animals) (antelope giraffe lion tiger)Put another way, the variable animals points to the list (antelope giraffelion tiger).Next, evaluate the fun tion set ar while passing it two arguments, thevariable animals and the quoted symbol hippopotamus; this is done bywriting the three element list (set ar animals 'hippopotamus) and thenevaluating it in the usual fashion:(set ar animals 'hippopotamus)After evaluating this expression, evaluate the variable animals again. Youwill see that the list of animals has hanged:animals) (hippopotamus giraffe lion tiger)The �rst element on the list, antelope is repla ed by hippopotamus.

Page 106: An Introduction to Programming in Emacs Lisp

88 Chapter 7: ar, dr, ons: Fundamental Fun tionsSo we an see that set ar did not add a new element to the list as onswould have; it repla ed giraffe with hippopotamus; it hanged the list.7.6 set drThe set dr fun tion is similar to the set ar fun tion, ex ept that thefun tion repla es the se ond and subsequent elements of a list rather thanthe �rst element.To see how this works, set the value of the variable to a list of domesti- ated animals by evaluating the following expression:(setq domesti ated-animals '(horse ow sheep goat))If you now evaluate the list, you will be returned the list (horse ow sheepgoat):domesti ated-animals) (horse ow sheep goat)Next, evaluate set dr with two arguments, the name of the variablewhi h has a list as its value, and the list to whi h the dr of the �rst listwill be set;(set dr domesti ated-animals '( at dog))If you evaluate this expression, the list ( at dog) will appear in the e hoarea. This is the value returned by the fun tion. The result we are inter-ested in is the \side e�e t", whi h we an see by evaluating the variabledomesti ated-animals:domesti ated-animals) (horse at dog)Indeed, the list is hanged from (horse ow sheep goat) to (horse atdog). The dr of the list is hanged from ( ow sheep goat) to ( at dog).7.7 Exer iseConstru t a list of four birds by evaluating several expressions with ons.Find out what happens when you ons a list onto itself. Repla e the �rstelement of the list of four birds with a �sh. Repla e the rest of that list witha list of other �sh.

Page 107: An Introduction to Programming in Emacs Lisp

zap-to- har 898 Cutting and Storing TextWhenever you ut or lip text out of a bu�er with a `kill' ommand inGNU Ema s, it is stored in a list and you an bring it ba k with a `yank' ommand.(The use of the word `kill' in Ema s for pro esses whi h spe i� ally donot destroy the values of the entities is an unfortunate histori al a ident.A mu h more appropriate word would be ` lip' sin e that is what the kill ommands do; they lip text out of a bu�er and put it into storage fromwhi h it an be brought ba k. I have often been tempted to repla e globallyall o urren es of `kill' in the Ema s sour es with ` lip' and all o urren esof `killed' with ` lipped'.)When text is ut out of a bu�er, it is stored on a list. Su essive pie esof text are stored on the list su essively, so the list might look like this:("a pie e of text" "previous pie e")The fun tion ons an be used to add a pie e of text to the list, like this:( ons "another pie e"'("a pie e of text" "previous pie e"))If you evaluate this expression, a list of three elements will appear in thee ho area:("another pie e" "a pie e of text" "previous pie e")With the ar and nth dr fun tions, you an retrieve whi hever pie e oftext you want. For example, in the following ode, nth dr 1 ... returnsthe list with the �rst item removed; and the ar returns the �rst element ofthat remainder|the se ond element of the original list:( ar (nth dr 1 '("another pie e""a pie e of text""previous pie e")))) "a pie e of text"The a tual fun tions in Ema s are more omplex than this, of ourse.The ode for utting and retrieving text has to be written so that Ema s an �gure out whi h element in the list you want|the �rst, se ond, third,or whatever. In addition, when you get to the end of the list, Ema s shouldgive you the �rst element of the list, rather than nothing at all.The list that holds the pie es of text is alled the kill ring. This hapterleads up to a des ription of the kill ring and how it is used by �rst tra ing howthe zap-to- har fun tion works. This fun tion uses (or ` alls') a fun tionthat invokes a fun tion that manipulates the kill ring. Thus, before rea hingthe mountains, we limb the foothills.A subsequent hapter des ribes how text that is ut from the bu�er isretrieved. See Chapter 10, \Yanking Text Ba k", page 117.

Page 108: An Introduction to Programming in Emacs Lisp

90 Chapter 8: Cutting and Storing Text8.1 zap-to- harThe zap-to- har fun tion barely hanged between GNU Ema s version19 and GNU Ema s version 21. However, zap-to- har alls another fun -tion, kill-region, whi h enjoyed a major rewrite on the way to version21.The kill-region fun tion in Ema s 19 is omplex, but does not use odethat is important at this time. We will skip it.The kill-region fun tion in Ema s 21 is easier to read than the samefun tion in Ema s 19 and introdu es a very important on ept, that of errorhandling. We will walk through the fun tion.But �rst, let us look at the intera tive zap-to- har fun tion.The GNU Ema s version 19 and version 21 implementations of the zap-to- har fun tion are nearly identi al in form, and they work alike. Thefun tion removes the text in the region between the lo ation of the ursor(i.e., of point) up to and in luding the next o urren e of a spe i�ed hara -ter. The text that zap-to- har removes is put in the kill ring; and it an beretrieved from the kill ring by typing C-y (yank). If the ommand is givenan argument, it removes text through that number of o urren es. Thus, ifthe ursor were at the beginning of this senten e and the hara ter were `s',`Thus' would be removed. If the argument were two, `Thus, if the urs'would be removed, up to and in luding the `s' in ` ursor'.If the spe i�ed hara ter is not found, zap-to- har will say \Sear hfailed", tell you the hara ter you typed, and not remove any text.In order to determine how mu h text to remove, zap-to- har uses asear h fun tion. Sear hes are used extensively in ode that manipulates text,and we will fo us attention on them as well as on the deletion ommand.Here is the omplete text of the version 19 implementation of the fun tion:(defun zap-to- har (arg har) ; version 19 implementation"Kill up to and in luding ARG'th o urren e of CHAR.Goes ba kward if ARG is negative; error if CHAR not found."(intera tive "*p\n Zap to har: ")(kill-region (point)(progn(sear h-forward( har-to-string har) nil nil arg)(point))))8.1.1 The intera tive ExpressionThe intera tive expression in the zap-to- har ommand looks like this:(intera tive "*p\n Zap to har: ")The part within quotation marks, "*p\n Zap to har: ", spe i�es threedi�erent things. First, and most simply, the asterisk, `*', auses an error to

Page 109: An Introduction to Programming in Emacs Lisp

The sear h-forward Fun tion 91be signalled if the bu�er is read-only. This means that if you try zap-to- har in a read-only bu�er you will not be able to remove text, and you willre eive a message that says \Bu�er is read-only"; your terminal may beepat you as well.The version 21 implementation does not have the asterisk, `*'. The fun -tion works the same as in version 19: in both ases, it annot remove textfrom a read-only bu�er but the fun tion does opy the text that would havebeen removed to the kill ring. Also, in both ases, you see an error message.However, the version 19 implementation opies text from a read-onlybu�er only be ause of a mistake in the implementation of intera tive.A ording to the do umentation for intera tive, the asterisk, `*', shouldprevent the zap-to- har fun tion from doing anything at all when the bu�eris read only. The fun tion should not opy the text to the kill ring. It is abug that it does.In version 21, intera tive is implemented orre tly. So the asterisk, `*',had to be removed from the intera tive spe i� ation. If you insert an `*' andevaluate the fun tion de�nition, then the next time you run the zap-to- harfun tion on a read-only bu�er, you will not opy any text.That hange aside, and a hange to the do umentation, the two versionsof the zap-to- har fun tion are identi al.Let us ontinue with the intera tive spe i� ation.The se ond part of "*p\n Zap to har: " is the `p'. This part is sepa-rated from the next part by a newline, `\n'. The `p' means that the �rstargument to the fun tion will be passed the value of a `pro essed pre�x'.The pre�x argument is passed by typing C-u and a number, or M- and anumber. If the fun tion is alled intera tively without a pre�x, 1 is passedto this argument.The third part of "*p\n Zap to har: " is ` Zap to har: '. In this part,the lower ase ` ' indi ates that intera tive expe ts a prompt and that theargument will be a hara ter. The prompt follows the ` ' and is the string`Zap to har: ' (with a spa e after the olon to make it look good).What all this does is prepare the arguments to zap-to- har so they areof the right type, and give the user a prompt.8.1.2 The Body of zap-to- harThe body of the zap-to- har fun tion ontains the ode that kills (thatis, removes) the text in the region from the urrent position of the ursorup to and in luding the spe i�ed hara ter. The �rst part of the ode lookslike this:(kill-region (point) ...(point) is the urrent position of the ursor.The next part of the ode is an expression using progn. The body of theprogn onsists of alls to sear h-forward and point.

Page 110: An Introduction to Programming in Emacs Lisp

92 Chapter 8: Cutting and Storing TextIt is easier to understand how progn works after learning about sear h-forward, so we will look at sear h-forward and then at progn.8.1.3 The sear h-forward Fun tionThe sear h-forward fun tion is used to lo ate the zapped-for- hara terin zap-to- har. If the sear h is su essful, sear h-forward leaves pointimmediately after the last hara ter in the target string. (In zap-to- har,the target string is just one hara ter long.) If the sear h is ba kwards,sear h-forward leaves point just before the �rst hara ter in the target.Also, sear h-forward returns t for true. (Moving point is therefore a `sidee�e t'.)In zap-to- har, the sear h-forward fun tion looks like this:(sear h-forward ( har-to-string har) nil nil arg)The sear h-forward fun tion takes four arguments:1. The �rst argument is the target, what is sear hed for. This must be astring, su h as `"z"'.As it happens, the argument passed to zap-to- har is a single hara -ter. Be ause of the way omputers are built, the Lisp interpreter maytreat a single hara ter as being di�erent from a string of hara ters.Inside the omputer, a single hara ter has a di�erent ele troni formatthan a string of one hara ter. (A single hara ter an often be re ordedin the omputer using exa tly one byte; but a string may be longer, andthe omputer needs to be ready for this.) Sin e the sear h-forwardfun tion sear hes for a string, the hara ter that the zap-to- har fun -tion re eives as its argument must be onverted inside the omputerfrom one format to the other; otherwise the sear h-forward fun tionwill fail. The har-to-string fun tion is used to make this onversion.2. The se ond argument bounds the sear h; it is spe i�ed as a position inthe bu�er. In this ase, the sear h an go to the end of the bu�er, sono bound is set and the se ond argument is nil.3. The third argument tells the fun tion what it should do if the sear hfails|it an signal an error (and print a message) or it an return nil.A nil as the third argument auses the fun tion to signal an error whenthe sear h fails.4. The fourth argument to sear h-forward is the repeat ount|howmany o urren es of the string to look for. This argument is optionaland if the fun tion is alled without a repeat ount, this argument ispassed the value 1. If this argument is negative, the sear h goes ba k-wards.

Page 111: An Introduction to Programming in Emacs Lisp

Summing up zap-to- har 93In template form, a sear h-forward expression looks like this:(sear h-forward "target-string"limit-of-sear hwhat-to-do-if-sear h-failsrepeat- ount)We will look at progn next.8.1.4 The progn Spe ial Formprogn is a spe ial form that auses ea h of its arguments to be evaluatedin sequen e and then returns the value of the last one. The pre eding ex-pressions are evaluated only for the side e�e ts they perform. The valuesprodu ed by them are dis arded.The template for a progn expression is very simple:(prognbody...)In zap-to- har, the progn expression has to do two things: put pointin exa tly the right position; and return the lo ation of point so that kill-region will know how far to kill to.The �rst argument to the progn is sear h-forward. When sear h-forward �nds the string, the fun tion leaves point immediately after thelast hara ter in the target string. (In this ase the target string is just one hara ter long.) If the sear h is ba kwards, sear h-forward leaves pointjust before the �rst hara ter in the target. The movement of point is a sidee�e t.The se ond and last argument to progn is the expression (point). Thisexpression returns the value of point, whi h in this ase will be the lo ationto whi h it has been moved by sear h-forward. This value is returnedby the progn expression and is passed to kill-region as kill-region'sse ond argument.8.1.5 Summing up zap-to- harNow that we have seen how sear h-forward and progn work, we ansee how the zap-to- har fun tion works as a whole.The �rst argument to kill-region is the position of the ursor when thezap-to- har ommand is given|the value of point at that time. Withinthe progn, the sear h fun tion then moves point to just after the zapped-to- hara ter and point returns the value of this lo ation. The kill-regionfun tion puts together these two values of point, the �rst one as the beginningof the region and the se ond one as the end of the region, and removes theregion.The progn spe ial form is ne essary be ause the kill-region ommandtakes two arguments; and it would fail if sear h-forward and point ex-

Page 112: An Introduction to Programming in Emacs Lisp

94 Chapter 8: Cutting and Storing Textpressions were written in sequen e as two additional arguments. The prognexpression is a single argument to kill-region and returns the one valuethat kill-region needs for its se ond argument.8.2 kill-regionThe zap-to- har fun tion uses the kill-region fun tion. This fun tion lips text from a region and opies that text to the kill ring, from whi h itmay be retrieved.The Ema s 21 version of that fun tion uses ondition- ase and opy-region-as-kill, both of whi h we will explain. ondition- ase is animportant spe ial form.In essen e, the kill-region fun tion alls ondition- ase, whi h takesthree arguments. In this fun tion, the �rst argument does nothing. These ond argument ontains the ode that does the work when all goes well.The third argument ontains the ode that is alled in the event of an error.We will go through the ondition- ase ode in a moment. First, let uslook at the omplete de�nition of kill-region, with omments added:(defun kill-region (beg end)"Kill between point and mark.The text is deleted but saved in the kill ring."(intera tive "r");; 1. ` ondition- ase' takes three arguments.;; If the first argument is nil, as it is here,;; information about the error signal is not;; stored for use by another fun tion.( ondition- ase nil;; 2. The se ond argument to ` ondition- ase';; tells the Lisp interpreter what to do when all goes well.;; The `delete-and-extra t-region' fun tion usually does the;; work. If the beginning and ending of the region are both;; the same, then the variable `string' will be empty, or nil(let ((string (delete-and-extra t-region beg end)));; `when' is an `if' lause that annot take an `else-part'.;; Ema s normally sets the value of `last- ommand' to the;; previous ommand.

Page 113: An Introduction to Programming in Emacs Lisp

ondition- ase 95;; `kill-append' on atenates the new string and the old.;; `kill-new' inserts text into a new item in the kill ring.(when string(if (eq last- ommand 'kill-region);; if true, prepend string(kill-append string (< end beg))(kill-new string)))(setq this- ommand 'kill-region));; 3. The third argument to ` ondition- ase' tells the interpreter;; what to do with an error.;; The third argument has a onditions part and a body part.;; If the onditions are met (in this ase,;; if text or buffer is read-only);; then the body is exe uted.((buffer-read-only text-read-only) ;; this is the if-part;; then...( opy-region-as-kill beg end)(if kill-read-only-ok ;; usually this variable is nil(message "Read only text opied to kill ring");; or else, signal an error if the buffer is read-only;(barf-if-buffer-read-only);; and, in any ase, signal that the text is read-only.(signal 'text-read-only (list ( urrent-buffer)))))))8.2.1 ondition- aseAs we have seen earlier (see Se tion 1.3, \Generate an Error Message",page 4), when the Ema s Lisp interpreter has trouble evaluating an expres-sion, it provides you with help; in the jargon, this is alled \signaling anerror". Usually, the omputer stops the program and shows you a message.However, some programs undertake ompli ated a tions. They should notsimply stop on an error. In the kill-region fun tion, the most likely erroris that you will try to kill text that is read-only and annot be removed. Sothe kill-region fun tion ontains ode to handle this ir umstan e. This ode, whi h makes up the body of the kill-region fun tion, is inside of a ondition- ase spe ial form.The template for ondition- ase looks like this:( ondition- asevarbodyformerror-handler...)The se ond argument, bodyform, is straightforward. The ondition- ase spe ial form auses the Lisp interpreter to evaluate the ode in body-

Page 114: An Introduction to Programming in Emacs Lisp

96 Chapter 8: Cutting and Storing Textform. If no error o urs, the spe ial form returns the ode's value andprodu es the side-e�e ts, if any.In short, the bodyform part of a ondition- ase expression determineswhat should happen when everything works orre tly.However, if an error o urs, among its other a tions, the fun tion gener-ating the error signal will de�ne one or more error ondition names.An error handler is the third argument to ondition ase. An errorhandler has two parts, a ondition-name and a body. If the ondition-namepart of an error handler mat hes a ondition name generated by an error,then the body part of the error handler is run.As you will expe t, the ondition-name part of an error handler may beeither a single ondition name or a list of ondition names.Also, a omplete ondition- ase expression may ontain more than oneerror handler. When an error o urs, the �rst appli able handler is run.Lastly, the �rst argument to the ondition- ase expression, the varargument, is sometimes bound to a variable that ontains information aboutthe error. However, if that argument is nil, as is the ase in kill-region,that information is dis arded.In brief, in the kill-region fun tion, the ode ondition- ase workslike this:If no errors, run only this odebut, if errors, run this other ode.8.2.2 delete-and-extra t-regionA ondition- ase expression has two parts, a part that is evaluated inthe expe tation that all will go well, but whi h may generate an error; anda part that is evaluated when there is an error.First, let us look at the ode in kill-region that is run in the expe tationthat all goes well. This is the ore of the fun tion. The ode looks like this:(let ((string (delete-and-extra t-region beg end)))(when string(if (eq last- ommand 'kill-region)(kill-append string (< end beg))(kill-new string)))(setq this- ommand 'kill-region))It looks ompli ated be ause we have the new fun tions delete-and-extra t-region, kill-append, and kill-new as well as the new variables,last- ommand and this- ommand.The delete-and-extra t-region fun tion is straightforward. It is abuilt-in fun tion that deletes the text in a region (a side e�e t) and alsoreturns that text. This is the fun tion that a tually removes the text. (Andif it annot do that, it signals the error.)

Page 115: An Introduction to Programming in Emacs Lisp

delete-and-extra t-region: Digressing into C 97In this let expression, the text that delete-and-extra t-region re-turns is pla ed in the lo al variable alled `string'. This is the text that isremoved from the bu�er. (To be more pre ise, the variable is set to pointto the address of the extra ted text; to say it is `pla ed in' the variable issimply a shorthand.)If the variable `string' does point to text, that text is added to the killring. The variable will have a nil value if no text was removed.The ode uses when to determine whether the variable `string' pointsto text. A when statement is simply a programmers' onvenien e. A whenstatement is an if statement without the possibility of an else lause. Inyour mind, you an repla e when with if and understand what goes on.That is what the Lisp interpreter does.Te hni ally speaking, when is a Lisp ma ro. A Lisp ma ro enables you tode�ne new ontrol onstru ts and other language features. It tells the inter-preter how to ompute another Lisp expression whi h will in turn omputethe value. In this ase, the `other expression' is an if expression. For moreabout Lisp ma ros, see se tion \Ma ros" in The GNU Ema s Lisp Referen eManual. The C programming language also provides ma ros. These aredi�erent, but also useful. We will brie y look at C ma ros in Se tion 8.3,\delete-and-extra t-region: Digressing into C", page 98.If the string has ontent, then another onditional expression is exe uted.This is an if with both a then-part and an else-part.(if (eq last- ommand 'kill-region)(kill-append string (< end beg))(kill-new string)))The then-part is evaluated if the previous ommand was another all tokill-region; if not, the else-part is evaluated.last- ommand is a variable that omes with Ema s that we have not seenbefore. Normally, whenever a fun tion is exe uted, Ema s sets the value oflast- ommand to the previous ommand.In this segment of the de�nition, the if expression he ks whether theprevious ommand was kill-region. If it was,(kill-append string (< end beg)) on atenates a opy of the newly lipped text to the just previously lippedtext in the kill ring. (If the (< end beg)) expression is true, kill-appendprepends the string to the just previously lipped text. For a detailed dis- ussion, see \The kill-append fun tion", page 104.)If you then yank ba k the text, i.e., `paste' it, you get both pie es oftext at on e. That way, if you delete two words in a row, and then yankthem ba k, you get both words, in their proper order, with one yank. (The(< end beg)) expression makes sure the order is orre t.)

Page 116: An Introduction to Programming in Emacs Lisp

98 Chapter 8: Cutting and Storing TextOn the other hand, if the previous ommand is not kill-region, thenthe kill-new fun tion is alled, whi h adds the text to the kill ring as thelatest item, and sets the kill-ring-yank-pointer variable to point to it.8.3 delete-and-extra t-region: Digressing into CThe zap-to- har ommand uses the delete-and-extra t-region fun -tion, whi h in turn uses two other fun tions, opy-region-as-kill anddel_range_1. The opy-region-as-kill fun tion will be des ribed in afollowing se tion; it puts a opy of the region in the kill ring so it an beyanked ba k. (See Se tion 8.5, \ opy-region-as-kill", page 102.)The delete-and-extra t-region fun tion removes the ontents of aregion and you annot get them ba k.Unlike the other ode dis ussed here, delete-and-extra t-region isnot written in Ema s Lisp; it is written in C and is one of the primitives ofthe GNU Ema s system. Sin e it is very simple, I will digress brie y fromLisp and des ribe it here.Like many of the other Ema s primitives, delete-and-extra t-regionis written as an instan e of a C ma ro, a ma ro being a template for ode.The omplete ma ro looks like this:DEFUN ("delete-and-extra t-region", Fdelete_and_extra t_region,Sdelete_and_extra t_region, 2, 2, 0,"Delete the text between START and END and return it.")(start, end)Lisp_Obje t start, end;{ validate_region (&start, &end);return del_range_1 (XINT (start), XINT (end), 1, 1);}Without going into the details of the ma ro writing pro ess, let me pointout that this ma ro starts with the word DEFUN. The word DEFUN was hosensin e the ode serves the same purpose as defun does in Lisp. The wordDEFUN is followed by seven parts inside of parentheses:� The �rst part is the name given to the fun tion in Lisp, delete-and-extra t-region.� The se ond part is the name of the fun tion in C, Fdelete_and_extra t_region. By onvention, it starts with `F'. Sin e C does notuse hyphens in names, unders ores are used instead.� The third part is the name for the C onstant stru ture that re ordsinformation on this fun tion for internal use. It is the name of thefun tion in C but begins with an `S' instead of an `F'.� The fourth and �fth parts spe ify the minimum and maximum numberof arguments the fun tion an have. This fun tion demands exa tly 2arguments.

Page 117: An Introduction to Programming in Emacs Lisp

delete-and-extra t-region: Digressing into C 99� The sixth part is nearly like the argument that follows the intera tivede laration in a fun tion written in Lisp: a letter followed, perhaps, bya prompt. The only di�eren e from the Lisp is when the ma ro is alledwith no arguments. Then you write a 0 (whi h is a `null string'), as inthis ma ro.If you were to spe ify arguments, you would pla e them between quo-tation marks. The C ma ro for goto- har in ludes "NGoto har: " inthis position to indi ate that the fun tion expe ts a raw pre�x, in this ase, a numeri al lo ation in a bu�er, and provides a prompt.� The seventh part is a do umentation string, just like the one for a fun -tion written in Ema s Lisp, ex ept that every newline must be writtenexpli itly as `\n' followed by a ba kslash and arriage return.Thus, the �rst two lines of do umentation for goto- har are writtenlike this:"Set point to POSITION, a number or marker.\n\Beginning of buffer is position (point-min), end is (point-max).In a C ma ro, the formal parameters ome next, with a statement ofwhat kind of obje t they are, followed by what might be alled the `body'of the ma ro. For delete-and-extra t-region the `body' onsists of thefollowing two lines:validate_region (&start, &end);return del_range_1 (XINT (start), XINT (end), 1, 1);The �rst fun tion, validate_region he ks whether the values passedas the beginning and end of the region are the proper type and are withinrange. The se ond fun tion, del_range_1, a tually deletes the text.del_range_1 is a omplex fun tion we will not look into. It updates thebu�er and does other things.However, it is worth looking at the two arguments passed to del_range.These are XINT (start) and XINT (end).As far as the C language is on erned, start and end are two integersthat mark the beginning and end of the region to be deleted1.In early versions of Ema s, these two numbers were thirty-two bits long,but the ode is slowly being generalized to handle other lengths. Three ofthe available bits are used to spe ify the type of information and a fourthbit is used for handling the omputer's memory; the remaining bits are usedas ` ontent'.`XINT' is a C ma ro that extra ts the relevant number from the longer olle tion of bits; the four other bits are dis arded.1 More pre isely, and requiring more expert knowledge to understand, the two integersare of type `Lisp Obje t', whi h an also be a C union instead of an integer type.

Page 118: An Introduction to Programming in Emacs Lisp

100 Chapter 8: Cutting and Storing TextThe ommand in delete-and-extra t-region looks like this:del_range_1 (XINT (start), XINT (end), 1, 1);It deletes the region between the beginning position, start, and the endingposition, end.From the point of view of the person writing Lisp, Ema s is all verysimple; but hidden underneath is a great deal of omplexity to make it allwork.8.4 Initializing a Variable with defvarUnlike the delete-and-extra t-region fun tion, the opy-region-as-kill fun tion is written in Ema s Lisp. Two fun tions within it, kill-append and kill-new, opy a region in a bu�er and save it in a variable alled the kill-ring. This se tion des ribes how the kill-ring variable is reated and initialized using the defvar spe ial form.(Again we note that the term kill-ring is a misnomer. The text thatis lipped out of the bu�er an be brought ba k; it is not a ring of orpses,but a ring of resurre table text.)In Ema s Lisp, a variable su h as the kill-ring is reated and given aninitial value by using the defvar spe ial form. The name omes from \de�nevariable".The defvar spe ial form is similar to setq in that it sets the value of avariable. It is unlike setq in two ways: �rst, it only sets the value of thevariable if the variable does not already have a value. If the variable alreadyhas a value, defvar does not override the existing value. Se ond, defvarhas a do umentation string.(Another spe ial form, def ustom, is designed for variables that people ustomize. It has more features than defvar. (See Se tion 16.2, \SettingVariables with def ustom", page 214.)You an see the urrent value of a variable, any variable, by using thedes ribe-variable fun tion, whi h is usually invoked by typing C-h v. Ifyou type C-h v and then kill-ring (followed by hRETi) when prompted, youwill see what is in your urrent kill ring|this may be quite a lot! Conversely,if you have been doing nothing this Ema s session ex ept read this do ument,you may have nothing in it. Also, you will see the do umentation for kill-ring:Do umentation:List of killed text sequen es.Sin e the kill ring is supposed to intera t ni ely with ut-and-pastefa ilities offered by window systems, use of this variable should

Page 119: An Introduction to Programming in Emacs Lisp

opy-region-as-kill 101intera t ni ely with `interprogram- ut-fun tion' and`interprogram-paste-fun tion'. The fun tions `kill-new',`kill-append', and ` urrent-kill' are supposed to implement thisintera tion; you may want to use them instead of manipulating the killring dire tly.The kill ring is de�ned by a defvar in the following way:(defvar kill-ring nil"List of killed text sequen es....")In this variable de�nition, the variable is given an initial value of nil, whi hmakes sense, sin e if you have saved nothing, you want nothing ba k if yougive a yank ommand. The do umentation string is written just like thedo umentation string of a defun. As with the do umentation string of thedefun, the �rst line of the do umentation should be a omplete senten e,sin e some ommands, like apropos, print only the �rst line of do umenta-tion. Su eeding lines should not be indented; otherwise they look odd whenyou use C-h v (des ribe-variable).8.4.1 defvar and an asteriskIn the past, Ema s used the defvar spe ial form both for internal vari-ables that you would not expe t a user to hange and for variables that youdo expe t a user to hange. Although you an still use defvar for user us-tomizable variables, please use def ustom instead, sin e that spe ial formprovides a path into the Customization ommands. (See Se tion 16.2, \Set-ting Variables with def ustom", page 214.)When you spe i�ed a variable using the defvar spe ial form, you oulddistinguish a readily settable variable from others by typing an asterisk, `*',in the �rst olumn of its do umentation string. For example:(defvar shell- ommand-default-error-buffer nil"*Buffer name for `shell- ommand' ... error output.... ")This means that you ould (and still an) use the edit-options ommandto hange the value of shell- ommand-default-error-buffer temporarily.However, options set using edit-options are set only for the durationof your editing session. The new values are not saved between sessions.Ea h time Ema s starts, it reads the original value, unless you hange thevalue within your `.ema s' �le, either by setting it manually or by using ustomize. See Chapter 16, \Your `.ema s' File", page 213.For me, the major use of the edit-options ommand is to suggest vari-ables that I might want to set in my `.ema s' �le. I urge you to look throughthe list. (See se tion \Editing Variable Values" in The GNU Ema s Manual.)

Page 120: An Introduction to Programming in Emacs Lisp

102 Chapter 8: Cutting and Storing Text8.5 opy-region-as-killThe opy-region-as-kill fun tion opies a region of text from a bu�erand (via either kill-append or kill-new) saves it in the kill-ring.If you all opy-region-as-kill immediately after a kill-region om-mand, Ema s appends the newly opied text to the previously opied text.This means that if you yank ba k the text, you get it all, from both this andthe previous operation. On the other hand, if some other ommand pre edesthe opy-region-as-kill, the fun tion opies the text into a separate entryin the kill ring.Here is the omplete text of the version 21 opy-region-as-kill fun -tion:(defun opy-region-as-kill (beg end)"Save the region as if killed, but don't kill it.In Transient Mark mode, dea tivate the mark.If `interprogram- ut-fun tion' is non-nil, also savethe text for a window system ut and paste."(intera tive "r")(if (eq last- ommand 'kill-region)(kill-append (buffer-substring beg end) (< end beg))(kill-new (buffer-substring beg end)))(if transient-mark-mode(setq dea tivate-mark t))nil)As usual, this fun tion an be divided into its omponent parts:(defun opy-region-as-kill (argument-list)"do umentation..."(intera tive "r")body...)The arguments are beg and end and the fun tion is intera tive with "r",so the two arguments must refer to the beginning and end of the region.If you have been reading though this do ument from the beginning, under-standing these parts of a fun tion is almost be oming routine.The do umentation is somewhat onfusing unless you remember that theword `kill' has a meaning di�erent from its usual meaning. The `TransientMark' and interprogram- ut-fun tion omments explain ertain side-e�e ts.After you on e set a mark, a bu�er always ontains a region. If youwish, you an use Transient Mark mode to highlight the region temporarily.(No one wants to highlight the region all the time, so Transient Mark modehighlights it only at appropriate times. Many people turn o� Transient Markmode, so the region is never highlighted.)

Page 121: An Introduction to Programming in Emacs Lisp

The Body of opy-region-as-kill 103Also, a windowing system allows you to opy, ut, and paste among di�er-ent programs. In the X windowing system, for example, the interprogram- ut-fun tion fun tion is x-sele t-text, whi h works with the windowingsystem's equivalent of the Ema s kill ring.The body of the opy-region-as-kill fun tion starts with an if lause. What this lause does is distinguish between two di�erent situa-tions: whether or not this ommand is exe uted immediately after a previ-ous kill-region ommand. In the �rst ase, the new region is appendedto the previously opied text. Otherwise, it is inserted into the beginning ofthe kill ring as a separate pie e of text from the previous pie e.The last two lines of the fun tion prevent the region from lighting up ifTransient Mark mode is turned on.The body of opy-region-as-kill merits dis ussion in detail.8.5.1 The Body of opy-region-as-killThe opy-region-as-kill fun tion works in mu h the same way as thekill-region fun tion (see Se tion 8.2, \kill-region", page 94). Both arewritten so that two or more kills in a row ombine their text into a singleentry. If you yank ba k the text from the kill ring, you get it all in one pie e.Moreover, kills that kill forward from the urrent position of the ursor areadded to the end of the previously opied text and ommands that opy textba kwards add it to the beginning of the previously opied text. This way,the words in the text stay in the proper order.Like kill-region, the opy-region-as-kill fun tion makes use of thelast- ommand variable that keeps tra k of the previous Ema s ommand.Normally, whenever a fun tion is exe uted, Ema s sets the value of this- ommand to the fun tion being exe uted (whi h in this ase would be opy-region-as-kill). At the same time, Ema s sets the value of last- ommandto the previous value of this- ommand.In the �rst part of the body of the opy-region-as-kill fun tion, an ifexpression determines whether the value of last- ommand is kill-region.If so, the then-part of the if expression is evaluated; it uses the kill-appendfun tion to on atenate the text opied at this all to the fun tion with thetext already in the �rst element (the ar) of the kill ring. On the otherhand, if the value of last- ommand is not kill-region, then the opy-region-as-kill fun tion atta hes a new element to the kill ring using thekill-new fun tion.

Page 122: An Introduction to Programming in Emacs Lisp

104 Chapter 8: Cutting and Storing TextThe if expression reads as follows; it uses eq, whi h is a fun tion we havenot yet seen:(if (eq last- ommand 'kill-region);; then-part(kill-append (buffer-substring beg end) (< end beg));; else-part(kill-new (buffer-substring beg end)))The eq fun tion tests whether its �rst argument is the same Lisp obje t asits se ond argument. The eq fun tion is similar to the equal fun tion inthat it is used to test for equality, but di�ers in that it determines whethertwo representations are a tually the same obje t inside the omputer, butwith di�erent names. equal determines whether the stru ture and ontentsof two expressions are the same.If the previous ommand was kill-region, then the Ema s Lisp inter-preter alls the kill-append fun tionThe kill-append fun tionThe kill-append fun tion looks like this:(defun kill-append (string before-p)"Append STRING to the end of the latest kill in the kill ring.If BEFORE-P is non-nil, prepend STRING to the kill.If `interprogram- ut-fun tion' is set, pass the resulting kill toit."(kill-new (if before-p( on at string ( ar kill-ring))( on at ( ar kill-ring) string))t))The kill-append fun tion is fairly straightforward. It uses the kill-newfun tion, whi h we will dis uss in more detail in a moment.First, let us look at the onditional that is one of the two arguments tokill-new. It uses on at to on atenate the new text to the ar of the killring. Whether it prepends or appends the text depends on the results of anif expression:(if before-p ; if-part( on at string ( ar kill-ring)) ; then-part( on at ( ar kill-ring) string)) ; else-partIf the region being killed is before the region that was killed in the last ommand, then it should be prepended before the material that was savedin the previous kill; and onversely, if the killed text follows what was justkilled, it should be appended after the previous text. The if expressiondepends on the predi ate before-p to de ide whether the newly saved textshould be put before or after the previously saved text.

Page 123: An Introduction to Programming in Emacs Lisp

The kill-new fun tion 105The symbol before-p is the name of one of the arguments to kill-append. When the kill-append fun tion is evaluated, it is bound to thevalue returned by evaluating the a tual argument. In this ase, this is the ex-pression (< end beg). This expression does not dire tly determine whetherthe killed text in this ommand is lo ated before or after the kill text of thelast ommand; what is does is determine whether the value of the variableend is less than the value of the variable beg. If it is, it means that theuser is most likely heading towards the beginning of the bu�er. Also, theresult of evaluating the predi ate expression, (< end beg), will be true andthe text will be prepended before the previous text. On the other hand, ifthe value of the variable end is greater than the value of the variable beg,the text will be appended after the previous text.When the newly saved text will be prepended, then the string with thenew text will be on atenated before the old text:( on at string ( ar kill-ring))But if the text will be appended, it will be on atenated after the old text:( on at ( ar kill-ring) string))To understand how this works, we �rst need to review the on at fun -tion. The on at fun tion links together or unites two strings of text. Theresult is a string. For example:( on at "ab " "def")) "ab def"( on at "new "( ar '("first element" "se ond element")))) "new first element"( on at ( ar'("first element" "se ond element")) " modified")) "first element modified"We an now make sense of kill-append: it modi�es the ontents of thekill ring. The kill ring is a list, ea h element of whi h is saved text. Thekill-append fun tion uses the kill-new fun tion whi h in turn uses theset ar fun tion.The kill-new fun tionThe kill-new fun tion looks like this:(defun kill-new (string &optional repla e)"Make STRING the latest kill in the kill ring.Set the kill-ring-yank pointer to point to it.If `interprogram- ut-fun tion' is non-nil, apply it to STRING.Optional se ond argument REPLACE non-nil means that STRING will repla ethe front of the kill ring, rather than being added to the list."

Page 124: An Introduction to Programming in Emacs Lisp

106 Chapter 8: Cutting and Storing Text(and (fboundp 'menu-bar-update-yank-menu)(menu-bar-update-yank-menu string (and repla e ( ar kill-ring))))(if (and repla e kill-ring)(set ar kill-ring string)(setq kill-ring ( ons string kill-ring))(if (> (length kill-ring) kill-ring-max)(set dr (nth dr (1- kill-ring-max) kill-ring) nil)))(setq kill-ring-yank-pointer kill-ring)(if interprogram- ut-fun tion(fun all interprogram- ut-fun tion string (not repla e))))As usual, we an look at this fun tion in parts.The �rst line of the do umentation makes sense:Make STRING the latest kill in the kill ring.Let's skip over the rest of the do umentation for the moment.Also, let's skip over the �rst two lines of ode, those involving menu-bar-update-yank-menu. We will explain them below.The riti al lines are these:(if (and repla e kill-ring);; then(set ar kill-ring string);; else(setq kill-ring ( ons string kill-ring))(if (> (length kill-ring) kill-ring-max);; avoid overly long kill ring(set dr (nth dr (1- kill-ring-max) kill-ring) nil)))(setq kill-ring-yank-pointer kill-ring)(if interprogram- ut-fun tion(fun all interprogram- ut-fun tion string (not repla e))))The onditional test is (and repla e kill-ring). This will be true whentwo onditions are met: the kill ring has something in it, and the repla evariable is true.The kill-append fun tion sets repla e to be true; then, when the killring has at least one item in it, the set ar expression is exe uted:(set ar kill-ring string)The set ar fun tion a tually hanges the �rst element of the kill-ringlist to the value of string. It repla es the �rst element.On the other hand, if the kill ring is empty, or repla e is false, the else-partof the ondition is exe uted:(setq kill-ring ( ons string kill-ring))(if (> (length kill-ring) kill-ring-max)(set dr (nth dr (1- kill-ring-max) kill-ring) nil))

Page 125: An Introduction to Programming in Emacs Lisp

The kill-new fun tion 107This expression �rst onstru ts a new version of the kill ring by prependingstring to the existing kill ring as a new element. Then it exe utes a se ondif lause. This se ond if lause keeps the kill ring from growing too long.Let's look at these two expressions in order.The setq line of the else-part sets the new value of the kill ring to whatresults from adding the string being killed to the old kill ring.We an see how this works with an example:(setq example-list '("here is a lause" "another lause"))After evaluating this expression with C-x C-e, you an evaluate example-list and see what it returns:example-list) ("here is a lause" "another lause")Now, we an add a new element on to this list by evaluating the followingexpression:(setq example-list ( ons "a third lause" example-list))When we evaluate example-list, we �nd its value is:example-list) ("a third lause" "here is a lause" "another lause")Thus, the third lause was added to the list by ons.This is exa tly similar to what the setq and ons do in the fun tion.Here is the line again:(setq kill-ring ( ons string kill-ring))Now for the se ond part of the if lause. This expression keeps the killring from growing too long. It looks like this:(if (> (length kill-ring) kill-ring-max)(set dr (nth dr (1- kill-ring-max) kill-ring) nil))The ode he ks whether the length of the kill ring is greater than themaximum permitted length. This is the value of kill-ring-max (whi h is60, by default). If the length of the kill ring is too long, then this ode setsthe last element of the kill ring to nil. It does this by using two fun tions,nth dr and set dr.We looked at set dr earlier (see Se tion 7.6, \set dr", page 88). It setsthe dr of a list, just as set ar sets the ar of a list. In this ase, however,set dr will not be setting the dr of the whole kill ring; the nth dr fun tionis used to ause it to set the dr of the next to last element of the kill ring|this means that sin e the dr of the next to last element is the last elementof the kill ring, it will set the last element of the kill ring.The nth dr fun tion works by repeatedly taking the dr of a list|ittakes the dr of the dr of the dr . . . It does this N times and returnsthe results.

Page 126: An Introduction to Programming in Emacs Lisp

108 Chapter 8: Cutting and Storing TextThus, if we had a four element list that was supposed to be three elementslong, we ould set the dr of the next to last element to nil, and therebyshorten the list.You an see this by evaluating the following three expressions in turn.First set the value of trees to (maple oak pine bir h), then set the drof its se ond dr to nil and then �nd the value of trees:(setq trees '(maple oak pine bir h))) (maple oak pine bir h)(set dr (nth dr 2 trees) nil)) niltrees) (maple oak pine)(The value returned by the set dr expression is nil sin e that is what the dr is set to.)To repeat, in kill-new, the nth dr fun tion takes the dr a number oftimes that is one less than the maximum permitted size of the kill ring andsets the dr of that element (whi h will be the rest of the elements in thekill ring) to nil. This prevents the kill ring from growing too long.The next to last expression in the kill-new fun tion is(setq kill-ring-yank-pointer kill-ring)The kill-ring-yank-pointer is a global variable that is set to be thekill-ring.Even though the kill-ring-yank-pointer is alled a `pointer', it isa variable just like the kill ring. However, the name has been hosen tohelp humans understand how the variable is used. The variable is used infun tions su h as yank and yank-pop (see Chapter 10, \Yanking Text Ba k",page 117).Now, to return to the �rst two lines in the body of the fun tion:(and (fboundp 'menu-bar-update-yank-menu)(menu-bar-update-yank-menu string (and repla e ( ar kill-ring))))This is an expression whose �rst element is the fun tion and.The and spe ial form evaluates ea h of its arguments until one of thearguments returns a value of nil, in whi h ase the and expression returnsnil; however, if none of the arguments returns a value of nil, the valueresulting from evaluating the last argument is returned. (Sin e su h a valueis not nil, it is onsidered true in Ema s Lisp.) In other words, an andexpression returns a true value only if all its arguments are true.In this ase, the expression tests �rst to see whether menu-bar-update-yank-menu exists as a fun tion, and if so, alls it. The fboundp fun tionreturns true if the symbol it is testing has a fun tion de�nition that `is notvoid'. If the symbol's fun tion de�nition were void, we would re eive an error

Page 127: An Introduction to Programming in Emacs Lisp

Review 109message, as we did when we reated errors intentionally (see Se tion 1.3,\Generate an Error Message", page 4).Essentially, the and is an if expression that reads like this:if the-menu-bar-fun tion-existsthen exe ute-itmenu-bar-update-yank-menu is one of the fun tions that make it possi-ble to use the `Sele t and Paste' menu in the Edit item of a menu bar; usinga mouse, you an look at the various pie es of text you have saved and sele tone pie e to paste.Finally, the last expression in the kill-new fun tion adds the newly opied string to whatever fa ility exists for opying and pasting among dif-ferent programs running in a windowing system. In the X Windowing sys-tem, for example, the x-sele t-text fun tion takes the string and storesit in memory operated by X. You an paste the string in another program,su h as an Xterm.The expression looks like this:(if interprogram- ut-fun tion(fun all interprogram- ut-fun tion string (not repla e))))If an interprogram- ut-fun tion exists, then Ema s exe utes fun all,whi h in turn alls its �rst argument as a fun tion and passes the remainingarguments to it. (In identally, as far as I an see, this if expression ouldbe repla ed by an and expression similar to the one in the �rst part of thefun tion.)We are not going to dis uss windowing systems and other programs fur-ther, but merely note that this is a me hanism that enables GNU Ema s towork easily and well with other programs.This ode for pla ing text in the kill ring, either on atenated with anexisting element or as a new element, leads us to the ode for bringing ba ktext that has been ut out of the bu�er|the yank ommands. However,before dis ussing the yank ommands, it is better to learn how lists areimplemented in a omputer. This will make lear su h mysteries as the useof the term `pointer'.8.6 ReviewHere is a brief summary of some re ently introdu ed fun tions. ar dr ar returns the �rst element of a list; dr returns the se ondand subsequent elements of a list.

Page 128: An Introduction to Programming in Emacs Lisp

110 Chapter 8: Cutting and Storing TextFor example:( ar '(1 2 3 4 5 6 7))) 1( dr '(1 2 3 4 5 6 7))) (2 3 4 5 6 7) ons ons onstru ts a list by prepending its �rst argument to itsse ond argument.For example:( ons 1 '(2 3 4))) (1 2 3 4)nth dr Return the result of taking dr `n' times on a list. The nth dr.The `rest of the rest', as it were.For example:(nth dr 3 '(1 2 3 4 5 6 7))) (4 5 6 7)set arset dr set ar hanges the �rst element of a list; set dr hanges these ond and subsequent elements of a list.For example:(setq triple '(1 2 3))(set ar triple '37)triple) (37 2 3)(set dr triple '("foo" "bar"))triple) (37 "foo" "bar")progn Evaluate ea h argument in sequen e and then return the valueof the last.For example:(progn 1 2 3 4)) 4save-restri tionRe ord whatever narrowing is in e�e t in the urrent bu�er, ifany, and restore that narrowing after evaluating the arguments.sear h-forwardSear h for a string, and if the string is found, move point.

Page 129: An Introduction to Programming in Emacs Lisp

Sear hing Exer ises 111Takes four arguments:1. The string to sear h for.2. Optionally, the limit of the sear h.3. Optionally, what to do if the sear h fails, return nil or anerror message.4. Optionally, how many times to repeat the sear h; if nega-tive, the sear h goes ba kwards.kill-regiondelete-region opy-region-as-killkill-region uts the text between point and mark from thebu�er and stores that text in the kill ring, so you an get it ba kby yanking.delete-and-extra t-region removes the text between pointand mark from the bu�er and throws it away. You annot getit ba k. opy-region-as-kill opies the text between point and markinto the kill ring, from whi h you an get it by yanking. Thefun tion does not ut or remove the text from the bu�er.8.7 Sear hing Exer ises� Write an intera tive fun tion that sear hes for a string. If the sear h�nds the string, leave point after it and display a message that says\Found!". (Do not use sear h-forward for the name of this fun tion;if you do, you will overwrite the existing version of sear h-forwardthat omes with Ema s. Use a name su h as test-sear h instead.)� Write a fun tion that prints the third element of the kill ring in the e hoarea, if any; if the kill ring does not ontain a third element, print anappropriate message.

Page 130: An Introduction to Programming in Emacs Lisp

112 Chapter 8: Cutting and Storing Text

Page 131: An Introduction to Programming in Emacs Lisp

How Lists are Implemented 1139 How Lists are ImplementedIn Lisp, atoms are re orded in a straightforward fashion; if the implemen-tation is not straightforward in pra ti e, it is, nonetheless, straightforwardin theory. The atom `rose', for example, is re orded as the four ontiguousletters `r', `o', `s', `e'. A list, on the other hand, is kept di�erently. Theme hanism is equally simple, but it takes a moment to get used to the idea.A list is kept using a series of pairs of pointers. In the series, the �rst pointerin ea h pair points to an atom or to another list, and the se ond pointer inea h pair points to the next pair, or to the symbol nil, whi h marks the endof the list.A pointer itself is quite simply the ele troni address of what is pointedto. Hen e, a list is kept as a series of ele troni addresses.For example, the list (rose violet butter up) has three elements,`rose', `violet', and `butter up'. In the omputer, the ele troni addressof `rose' is re orded in a segment of omputer memory along with the ad-dress that gives the ele troni address of where the atom `violet' is lo ated;and that address (the one that tells where `violet' is lo ated) is kept alongwith an address that tells where the address for the atom `butter up' islo ated.This sounds more ompli ated than it is and is easier seen in a diagram:rose violet buttercup

nil

In the diagram, ea h box represents a word of omputer memory that holdsa Lisp obje t, usually in the form of a memory address. The boxes, i.e.the addresses, are in pairs. Ea h arrow points to what the address is theaddress of, either an atom or another pair of addresses. The �rst box is theele troni address of `rose' and the arrow points to `rose'; the se ond boxis the address of the next pair of boxes, the �rst part of whi h is the addressof `violet' and the se ond part of whi h is the address of the next pair. Thevery last box points to the symbol nil, whi h marks the end of the list.When a variable is set to a list with a fun tion su h as setq, it stores theaddress of the �rst box in the variable. Thus, evaluation of the expression(setq bouquet '(rose violet butter up))

Page 132: An Introduction to Programming in Emacs Lisp

114 Chapter 9: How Lists are Implemented reates a situation like this:bouquet

rose violet buttercup

nil

In this example, the symbol bouquet holds the address of the �rst pair ofboxes.This same list an be illustrated in a di�erent sort of box notation likethis:bouquet

car

rose

cdr car

violet

cdr car

butter-cup

cdr

nil(Symbols onsist of more than pairs of addresses, but the stru ture ofa symbol is made up of addresses. Indeed, the symbol bouquet onsists ofa group of address-boxes, one of whi h is the address of the printed word`bouquet', a se ond of whi h is the address of a fun tion de�nition atta hedto the symbol, if any, a third of whi h is the address of the �rst pair ofaddress-boxes for the list (rose violet butter up), and so on. Here weare showing that the symbol's third address-box points to the �rst pair ofaddress-boxes for the list.)If a symbol is set to the dr of a list, the list itself is not hanged; thesymbol simply has an address further down the list. (In the jargon, ar and dr are `non-destru tive'.) Thus, evaluation of the following expression(setq flowers ( dr bouquet))produ es this:rose violet buttercup

nil

flowersbouquet

Page 133: An Introduction to Programming in Emacs Lisp

Symbols as a Chest of Drawers 115The value of flowers is (violet butter up), whi h is to say, the symbolflowers holds the address of the pair of address-boxes, the �rst of whi hholds the address of violet, and the se ond of whi h holds the address ofbutter up.A pair of address-boxes is alled a ons ell or dotted pair. See se tion\List Type " in The GNU Ema s Lisp Referen e Manual, and se tion \Dot-ted Pair Notation" in The GNU Ema s Lisp Referen e Manual, for moreinformation about ons ells and dotted pairs.The fun tion ons adds a new pair of addresses to the front of a series ofaddresses like that shown above. For example, evaluating the expression(setq bouquet ( ons 'lily bouquet))produ es:violet

flowers

nil

buttercup

roselily

bouquet

However, this does not hange the value of the symbol flowers, as you ansee by evaluating the following,(eq ( dr ( dr bouquet)) flowers)whi h returns t for true.Until it is reset, flowers still has the value (violet butter up); thatis, it has the address of the ons ell whose �rst address is of violet. Also,this does not alter any of the pre-existing ons ells; they are all still there.Thus, in Lisp, to get the dr of a list, you just get the address of thenext ons ell in the series; to get the ar of a list, you get the address ofthe �rst element of the list; to ons a new element on a list, you add a new ons ell to the front of the list. That is all there is to it! The underlyingstru ture of Lisp is brilliantly simple!And what does the last address in a series of ons ells refer to? It is theaddress of the empty list, of nil.In summary, when a Lisp variable is set to a value, it is provided withthe address of the list to whi h the variable refers.9.1 Symbols as a Chest of DrawersIn an earlier se tion, I suggested that you might imagine a symbol asbeing a hest of drawers. The fun tion de�nition is put in one drawer, the

Page 134: An Introduction to Programming in Emacs Lisp

116 Chapter 9: How Lists are Implementedvalue in another, and so on. What is put in the drawer holding the value anbe hanged without a�e ting the ontents of the drawer holding the fun tionde�nition, and vi e-versa.A tually, what is put in ea h drawer is the address of the value or fun tionde�nition. It is as if you found an old hest in the atti , and in one of itsdrawers you found a map giving you dire tions to where the buried treasurelies.(In addition to its name, symbol de�nition, and variable value, a symbolhas a `drawer' for a property list whi h an be used to re ord other infor-mation. Property lists are not dis ussed here; see se tion \Property Lists"in The GNU Ema s Lisp Referen e Manual.)Here is a fan iful representation:symbol name

Chest of Drawers Contents of Drawers

bouquet

[none]

(rose violet buttercup)

[not described here]

directions to map to

map to

symbol definitiondirections to

variable namedirections to

property listdirections to

9.2 Exer iseSet flowers to violet and butter up. Cons two more owers on to thislist and set this new list to more-flowers. Set the ar of flowers to a �sh.What does the more-flowers list now ontain?

Page 135: An Introduction to Programming in Emacs Lisp

The kill-ring-yank-pointer Variable 11710 Yanking Text Ba kWhenever you ut text out of a bu�er with a `kill' ommand in GNUEma s, you an bring it ba k with a `yank' ommand. The text that is utout of the bu�er is put in the kill ring and the yank ommands insert theappropriate ontents of the kill ring ba k into a bu�er (not ne essarily theoriginal bu�er).A simple C-y (yank) ommand inserts the �rst item from the kill ring intothe urrent bu�er. If the C-y ommand is followed immediately by M-y, the�rst element is repla ed by the se ond element. Su essive M-y ommandsrepla e the se ond element with the third, fourth, or �fth element, and soon. When the last element in the kill ring is rea hed, it is repla ed by the�rst element and the y le is repeated. (Thus the kill ring is alled a `ring'rather than just a `list'. However, the a tual data stru ture that holds thetext is a list. See Appendix B, \Handling the Kill Ring", page 243, for thedetails of how the list is handled as a ring.)10.1 Kill Ring OverviewThe kill ring is a list of textual strings. This is what it looks like:("some text" "a different pie e of text" "yet more text")If this were the ontents of my kill ring and I pressed C-y, the stringof hara ters saying `some text' would be inserted in this bu�er where my ursor is lo ated.The yank ommand is also used for dupli ating text by opying it. The opied text is not ut from the bu�er, but a opy of it is put on the kill ringand is inserted by yanking it ba k.Three fun tions are used for bringing text ba k from the kill ring: yank,whi h is usually bound to C-y; yank-pop, whi h is usually bound to M-y;and rotate-yank-pointer, whi h is used by the two other fun tions.These fun tions refer to the kill ring through a variable alled the kill-ring-yank-pointer. Indeed, the insertion ode for both the yank and yank-pop fun tions is:(insert ( ar kill-ring-yank-pointer))To begin to understand how yank and yank-pop work, it is �rst ne essaryto look at the kill-ring-yank-pointer variable and the rotate-yank-pointer fun tion.10.2 The kill-ring-yank-pointer Variablekill-ring-yank-pointer is a variable, just as kill-ring is a variable.It points to something by being bound to the value of what it points to, likeany other Lisp variable.

Page 136: An Introduction to Programming in Emacs Lisp

118 Chapter 10: Yanking Text Ba kThus, if the value of the kill ring is:("some text" "a different pie e of text" "yet more text")and the kill-ring-yank-pointer points to the se ond lause, the value ofkill-ring-yank-pointer is:("a different pie e of text" "yet more text")As explained in the previous hapter (see Chapter 9, \List Implementa-tion", page 113), the omputer does not keep two di�erent opies of the textbeing pointed to by both the kill-ring and the kill-ring-yank-pointer.The words \a di�erent pie e of text" and \yet more text" are not dupli ated.Instead, the two Lisp variables point to the same pie es of text. Here is adiagram:a different piece of text

kill-ring-yank-pointer

nil

yet more text

some text

kill-ring

Both the variable kill-ring and the variable kill-ring-yank-pointerare pointers. But the kill ring itself is usually des ribed as if it were a tuallywhat it is omposed of. The kill-ring is spoken of as if it were the listrather than that it points to the list. Conversely, the kill-ring-yank-pointer is spoken of as pointing to a list.These two ways of talking about the same thing sound onfusing at �rstbut make sense on re e tion. The kill ring is generally thought of as the omplete stru ture of data that holds the information of what has re entlybeen ut out of the Ema s bu�ers. The kill-ring-yank-pointer on theother hand, serves to indi ate|that is, to `point to'|that part of the killring of whi h the �rst element (the ar) will be inserted.The rotate-yank-pointer fun tion hanges the element in the kill ringto whi h the kill-ring-yank-pointer points; when the pointer is set topoint to the next element beyond the end of the kill ring, it automati allysets it to point to the �rst element of the kill ring. This is how the listis transformed into a ring. The rotate-yank-pointer fun tion itself is notdiÆ ult, but ontains many details. It and the mu h simpler yank and yank-pop fun tions are des ribed in an appendix. See Appendix B, \Handling theKill Ring", page 243.

Page 137: An Introduction to Programming in Emacs Lisp

Exer ises with yank and nth dr 11910.3 Exer ises with yank and nth dr� Using C-h v (des ribe-variable), look at the value of your kill ring.Add several items to your kill ring; look at its value again. Using M-y(yank-pop), move all the way around the kill ring. How many itemswere in your kill ring? Find the value of kill-ring-max. Was your killring full, or ould you have kept more blo ks of text within it?� Using nth dr and ar, onstru t a series of expressions to return the�rst, se ond, third, and fourth elements of a list.

Page 138: An Introduction to Programming in Emacs Lisp

120 Chapter 10: Yanking Text Ba k

Page 139: An Introduction to Programming in Emacs Lisp

while 12111 Loops and Re ursionEma s Lisp has two primary ways to ause an expression, or a seriesof expressions, to be evaluated repeatedly: one uses a while loop, and theother uses re ursion.Repetition an be very valuable. For example, to move forward foursenten es, you need only write a program that will move forward one senten eand then repeat the pro ess four times. Sin e a omputer does not get boredor tired, su h repetitive a tion does not have the deleterious e�e ts thatex essive or the wrong kinds of repetition an have on humans.People mostly write Ema s Lisp fun tions using while loops and theirkin; but you an use re ursion, whi h provides a very powerful way to thinkabout and then to solve problems1.11.1 whileThe while spe ial form tests whether the value returned by evaluatingits �rst argument is true or false. This is similar to what the Lisp interpreterdoes with an if; what the interpreter does next, however, is di�erent.In a while expression, if the value returned by evaluating the �rst argu-ment is false, the Lisp interpreter skips the rest of the expression (the bodyof the expression) and does not evaluate it. However, if the value is true, theLisp interpreter evaluates the body of the expression and then again testswhether the �rst argument to while is true or false. If the value returnedby evaluating the �rst argument is again true, the Lisp interpreter againevaluates the body of the expression.The template for a while expression looks like this:(while true-or-false-testbody...)So long as the true-or-false-test of the while expression returns a truevalue when it is evaluated, the body is repeatedly evaluated. This pro essis alled a loop sin e the Lisp interpreter repeats the same thing again andagain, like an airplane doing a loop. When the result of evaluating the true-or-false-test is false, the Lisp interpreter does not evaluate the rest of thewhile expression and `exits the loop'.Clearly, if the value returned by evaluating the �rst argument to whileis always true, the body following will be evaluated again and again . . .and again . . . forever. Conversely, if the value returned is never true, the1 You an write re ursive fun tions to be frugal or wasteful of mental or omputerresour es; as it happens, methods that people �nd easy|that are frugal of `mentalresour es'|sometimes use onsiderable omputer resour es. Ema s was designed torun on ma hines that we now onsider limited and its default settings are onservative.You may want to in rease the values of max-spe pdl-size and max-lisp-eval-depth.In my `.ema s' �le, I set them to 15 and 30 times their default value.

Page 140: An Introduction to Programming in Emacs Lisp

122 Chapter 11: Loops and Re ursionexpressions in the body will never be evaluated. The raft of writing a whileloop onsists of hoosing a me hanism su h that the true-or-false-test returnstrue just the number of times that you want the subsequent expressions tobe evaluated, and then have the test return false.The value returned by evaluating a while is the value of the true-or-false-test. An interesting onsequen e of this is that a while loop that evaluateswithout error will return nil or false regardless of whether it has looped 1 or100 times or none at all. A while expression that evaluates su essfully neverreturns a true value! What this means is that while is always evaluated forits side e�e ts, whi h is to say, the onsequen es of evaluating the expressionswithin the body of the while loop. This makes sense. It is not the mere a tof looping that is desired, but the onsequen es of what happens when theexpressions in the loop are repeatedly evaluated.11.1.1 A while Loop and a ListA ommon way to ontrol a while loop is to test whether a list has anyelements. If it does, the loop is repeated; but if it does not, the repetition isended. Sin e this is an important te hnique, we will reate a short exampleto illustrate it.A simple way to test whether a list has elements is to evaluate the list:if it has no elements, it is an empty list and will return the empty list, (),whi h is a synonym for nil or false. On the other hand, a list with elementswill return those elements when it is evaluated. Sin e Ema s Lisp onsidersas true any value that is not nil, a list that returns elements will test truein a while loop.For example, you an set the variable empty-list to nil by evaluatingthe following setq expression:(setq empty-list ())After evaluating the setq expression, you an evaluate the variable empty-list in the usual way, by pla ing the ursor after the symbol and typingC-x C-e; nil will appear in your e ho area:empty-listOn the other hand, if you set a variable to be a list with elements, thelist will appear when you evaluate the variable, as you an see by evaluatingthe following two expressions:(setq animals '(gazelle giraffe lion tiger))animalsThus, to reate a while loop that tests whether there are any items inthe list animals, the �rst part of the loop will be written like this:(while animals...

Page 141: An Introduction to Programming in Emacs Lisp

An Example: print-elements-of-list 123When the while tests its �rst argument, the variable animals is evaluated.It returns a list. So long as the list has elements, the while onsiders theresults of the test to be true; but when the list is empty, it onsiders theresults of the test to be false.To prevent the while loop from running forever, some me hanism needsto be provided to empty the list eventually. An oft-used te hnique is to haveone of the subsequent forms in the while expression set the value of the listto be the dr of the list. Ea h time the dr fun tion is evaluated, the listwill be made shorter, until eventually only the empty list will be left. Atthis point, the test of the while loop will return false, and the arguments tothe while will no longer be evaluated.For example, the list of animals bound to the variable animals an beset to be the dr of the original list with the following expression:(setq animals ( dr animals))If you have evaluated the previous expressions and then evaluate this ex-pression, you will see (giraffe lion tiger) appear in the e ho area. If youevaluate the expression again, (lion tiger) will appear in the e ho area. Ifyou evaluate it again and yet again, (tiger) appears and then the emptylist, shown by nil.A template for a while loop that uses the dr fun tion repeatedly to ause the true-or-false-test eventually to test false looks like this:(while test-whether-list-is-emptybody...set-list-to- dr-of-list)This test and use of dr an be put together in a fun tion that goesthrough a list and prints ea h element of the list on a line of its own.11.1.2 An Example: print-elements-of-listThe print-elements-of-list fun tion illustrates a while loop with alist.The fun tion requires several lines for its output. If you are reading thisin Ema s 21 or a later version, you an evaluate the following expressioninside of Info, as usual.If you are using an earlier version of Ema s, you need to opy the ne es-sary expressions to your `*s rat h*' bu�er and evaluate them there. Thisis be ause the e ho area had only one line in the earlier versions.You an opy the expressions by marking the beginning of the region withC-hSPCi (set-mark- ommand), moving the ursor to the end of the regionand then opying the region using M-w ( opy-region-as-kill). In the`*s rat h*' bu�er, you an yank the expressions ba k by typing C-y (yank).After you have opied the expressions to the `*s rat h*' bu�er, evaluateea h expression in turn. Be sure to evaluate the last expression, (print-elements-of-list animals), by typing C-u C-x C-e, that is, by giving an

Page 142: An Introduction to Programming in Emacs Lisp

124 Chapter 11: Loops and Re ursionargument to eval-last-sexp. This will ause the result of the evalua-tion to be printed in the `*s rat h*' bu�er instead of being printed inthe e ho area. (Otherwise you will see something like this in your e hoarea: ^Jgiraffe^J^Jgazelle^J^Jlion^J^Jtiger^Jnil, in whi h ea h `^J'stands for a `newline'.)If you are using Ema s 21 or later, you an evaluate these expressionsdire tly in the Info bu�er, and the e ho area will grow to show the results.(setq animals '(gazelle giraffe lion tiger))(defun print-elements-of-list (list)"Print ea h element of LIST on a line of its own."(while list(print ( ar list))(setq list ( dr list))))(print-elements-of-list animals)When you evaluate the three expressions in sequen e, you will see this:giraffegazelleliontigernilEa h element of the list is printed on a line of its own (that is what thefun tion print does) and then the value returned by the fun tion is printed.Sin e the last expression in the fun tion is the while loop, and sin e whileloops always return nil, a nil is printed after the last element of the list.11.1.3 A Loop with an In rementing CounterA loop is not useful unless it stops when it ought. Besides ontrollinga loop with a list, a ommon way of stopping a loop is to write the �rstargument as a test that returns false when the orre t number of repetitionsare omplete. This means that the loop must have a ounter|an expressionthat ounts how many times the loop repeats itself.The test an be an expression su h as (< ount desired-number) whi hreturns t for true if the value of ount is less than the desired-number ofrepetitions and nil for false if the value of ount is equal to or is greaterthan the desired-number. The expression that in rements the ount anbe a simple setq su h as (setq ount (1+ ount)), where 1+ is a built-in fun tion in Ema s Lisp that adds 1 to its argument. (The expression

Page 143: An Introduction to Programming in Emacs Lisp

Example with in rementing ounter 125(1+ ount) has the same result as (+ ount 1), but is easier for a humanto read.)The template for a while loop ontrolled by an in rementing ounterlooks like this:set- ount-to-initial-value(while (< ount desired-number) ; true-or-false-testbody...(setq ount (1+ ount))) ; in rementerNote that you need to set the initial value of ount; usually it is set to 1.Example with in rementing ounterSuppose you are playing on the bea h and de ide to make a triangle ofpebbles, putting one pebble in the �rst row, two in the se ond row, three inthe third row and so on, like this:�� �� � �� � � �(About 2500 years ago, Pythagoras and others developed the beginnings ofnumber theory by onsidering questions su h as this.)Suppose you want to know how many pebbles you will need to make atriangle with 7 rows?Clearly, what you need to do is add up the numbers from 1 to 7. Thereare two ways to do this; start with the smallest number, one, and add upthe list in sequen e, 1, 2, 3, 4 and so on; or start with the largest numberand add the list going down: 7, 6, 5, 4 and so on. Be ause both me hanismsillustrate ommon ways of writing while loops, we will reate two examples,one ounting up and the other ounting down. In this �rst example, we willstart with 1 and add 2, 3, 4 and so on.If you are just adding up a short list of numbers, the easiest way to do itis to add up all the numbers at on e. However, if you do not know ahead oftime how many numbers your list will have, or if you want to be preparedfor a very long list, then you need to design your addition so that what youdo is repeat a simple pro ess many times instead of doing a more omplexpro ess on e.For example, instead of adding up all the pebbles all at on e, what you an do is add the number of pebbles in the �rst row, 1, to the number in these ond row, 2, and then add the total of those two rows to the third row, 3.Then you an add the number in the fourth row, 4, to the total of the �rstthree rows; and so on.

Page 144: An Introduction to Programming in Emacs Lisp

126 Chapter 11: Loops and Re ursionThe riti al hara teristi of the pro ess is that ea h repetitive a tion issimple. In this ase, at ea h step we add only two numbers, the number ofpebbles in the row and the total already found. This pro ess of adding twonumbers is repeated again and again until the last row has been added tothe total of all the pre eding rows. In a more omplex loop the repetitivea tion might not be so simple, but it will be simpler than doing everythingall at on e.The parts of the fun tion de�nitionThe pre eding analysis gives us the bones of our fun tion de�nition: �rst,we will need a variable that we an all total that will be the total numberof pebbles. This will be the value returned by the fun tion.Se ond, we know that the fun tion will require an argument: this ar-gument will be the total number of rows in the triangle. It an be allednumber-of-rows.Finally, we need a variable to use as a ounter. We ould all this vari-able ounter, but a better name is row-number. That is be ause whatthe ounter does is ount rows, and a program should be written to be asunderstandable as possible.When the Lisp interpreter �rst starts evaluating the expressions in thefun tion, the value of total should be set to zero, sin e we have not addedanything to it. Then the fun tion should add the number of pebbles in the�rst row to the total, and then add the number of pebbles in the se ond tothe total, and then add the number of pebbles in the third row to the total,and so on, until there are no more rows left to add.Both total and row-number are used only inside the fun tion, so they an be de lared as lo al variables with let and given initial values. Clearly,the initial value for total should be 0. The initial value of row-numbershould be 1, sin e we start with the �rst row. This means that the letstatement will look like this:(let ((total 0)(row-number 1))body...)After the internal variables are de lared and bound to their initial values,we an begin the while loop. The expression that serves as the test shouldreturn a value of t for true so long as the row-number is less than or equalto the number-of-rows. (If the expression tests true only so long as therow number is less than the number of rows in the triangle, the last row willnever be added to the total; hen e the row number has to be either less thanor equal to the number of rows.)

Page 145: An Introduction to Programming in Emacs Lisp

Putting the fun tion de�nition together 127Lisp provides the <= fun tion that returns true if the value of its �rstargument is less than or equal to the value of its se ond argument and falseotherwise. So the expression that the while will evaluate as its test shouldlook like this:(<= row-number number-of-rows)The total number of pebbles an be found by repeatedly adding the num-ber of pebbles in a row to the total already found. Sin e the number ofpebbles in the row is equal to the row number, the total an be found byadding the row number to the total. (Clearly, in a more omplex situation,the number of pebbles in the row might be related to the row number ina more ompli ated way; if this were the ase, the row number would berepla ed by the appropriate expression.)(setq total (+ total row-number))What this does is set the new value of total to be equal to the sum ofadding the number of pebbles in the row to the previous total.After setting the value of total, the onditions need to be established forthe next repetition of the loop, if there is one. This is done by in rementingthe value of the row-number variable, whi h serves as a ounter. Afterthe row-number variable has been in remented, the true-or-false-test at thebeginning of the while loop tests whether its value is still less than or equalto the value of the number-of-rows and if it is, adds the new value of therow-number variable to the total of the previous repetition of the loop.The built-in Ema s Lisp fun tion 1+ adds 1 to a number, so the row-number variable an be in remented with this expression:(setq row-number (1+ row-number))Putting the fun tion de�nition togetherWe have reated the parts for the fun tion de�nition; now we need to putthem together.First, the ontents of the while expression:(while (<= row-number number-of-rows) ; true-or-false-test(setq total (+ total row-number))(setq row-number (1+ row-number))) ; in rementerAlong with the let expression varlist, this very nearly ompletes the bodyof the fun tion de�nition. However, it requires one �nal element, the needfor whi h is somewhat subtle.The �nal tou h is to pla e the variable total on a line by itself after thewhile expression. Otherwise, the value returned by the whole fun tion isthe value of the last expression that is evaluated in the body of the let, andthis is the value returned by the while, whi h is always nil.This may not be evident at �rst sight. It almost looks as if the in re-menting expression is the last expression of the whole fun tion. But that

Page 146: An Introduction to Programming in Emacs Lisp

128 Chapter 11: Loops and Re ursionexpression is part of the body of the while; it is the last element of the listthat starts with the symbol while. Moreover, the whole of the while loopis a list within the body of the let.In outline, the fun tion will look like this:(defun name-of-fun tion (argument-list)"do umentation..."(let (varlist)(while (true-or-false-test)body-of-while... )... ) ; Need �nal expression here.The result of evaluating the let is what is going to be returned by thedefun sin e the let is not embedded within any ontaining list, ex ept forthe defun as a whole. However, if the while is the last element of the letexpression, the fun tion will always return nil. This is not what we want!Instead, what we want is the value of the variable total. This is returnedby simply pla ing the symbol as the last element of the list starting withlet. It gets evaluated after the pre eding elements of the list are evaluated,whi h means it gets evaluated after it has been assigned the orre t valuefor the total.It may be easier to see this by printing the list starting with let all on oneline. This format makes it evident that the varlist and while expressions arethe se ond and third elements of the list starting with let, and the totalis the last element:(let (varlist) (while (true-or-false-test) body-of-while... ) total)Putting everything together, the triangle fun tion de�nition looks likethis:(defun triangle (number-of-rows) ; Version with; in rementing ounter."Add up the number of pebbles in a triangle.The first row has one pebble, the se ond row two pebbles,the third row three pebbles, and so on.The argument is NUMBER-OF-ROWS."(let ((total 0)(row-number 1))(while (<= row-number number-of-rows)(setq total (+ total row-number))(setq row-number (1+ row-number)))total))

Page 147: An Introduction to Programming in Emacs Lisp

Example with de rementing ounter 129After you have installed triangle by evaluating the fun tion, you antry it out. Here are two examples:(triangle 4)(triangle 7)The sum of the �rst four numbers is 10 and the sum of the �rst seven numbersis 28.11.1.4 Loop with a De rementing CounterAnother ommon way to write a while loop is to write the test so thatit determines whether a ounter is greater than zero. So long as the ounteris greater than zero, the loop is repeated. But when the ounter is equal toor less than zero, the loop is stopped. For this to work, the ounter has tostart out greater than zero and then be made smaller and smaller by a formthat is evaluated repeatedly.The test will be an expression su h as (> ounter 0) whi h returns tfor true if the value of ounter is greater than zero, and nil for false if thevalue of ounter is equal to or less than zero. The expression that makes thenumber smaller and smaller an be a simple setq su h as (setq ounter(1- ounter)), where 1- is a built-in fun tion in Ema s Lisp that subtra ts1 from its argument.The template for a de rementing while loop looks like this:(while (> ounter 0) ; true-or-false-testbody...(setq ounter (1- ounter))) ; de rementerExample with de rementing ounterTo illustrate a loop with a de rementing ounter, we will rewrite thetriangle fun tion so the ounter de reases to zero.This is the reverse of the earlier version of the fun tion. In this ase, to�nd out how many pebbles are needed to make a triangle with 3 rows, addthe number of pebbles in the third row, 3, to the number in the pre edingrow, 2, and then add the total of those two rows to the row that pre edesthem, whi h is 1.Likewise, to �nd the number of pebbles in a triangle with 7 rows, add thenumber of pebbles in the seventh row, 7, to the number in the pre eding row,whi h is 6, and then add the total of those two rows to the row that pre edesthem, whi h is 5, and so on. As in the previous example, ea h addition onlyinvolves adding two numbers, the total of the rows already added up and thenumber of pebbles in the row that is being added to the total. This pro essof adding two numbers is repeated again and again until there are no morepebbles to add.

Page 148: An Introduction to Programming in Emacs Lisp

130 Chapter 11: Loops and Re ursionWe know how many pebbles to start with: the number of pebbles in thelast row is equal to the number of rows. If the triangle has seven rows, thenumber of pebbles in the last row is 7. Likewise, we know how many pebblesare in the pre eding row: it is one less than the number in the row.The parts of the fun tion de�nitionWe start with three variables: the total number of rows in the triangle;the number of pebbles in a row; and the total number of pebbles, whi h iswhat we want to al ulate. These variables an be named number-of-rows,number-of-pebbles-in-row, and total, respe tively.Both total and number-of-pebbles-in-row are used only inside thefun tion and are de lared with let. The initial value of total should, of ourse, be zero. However, the initial value of number-of-pebbles-in-rowshould be equal to the number of rows in the triangle, sin e the addition willstart with the longest row.This means that the beginning of the let expression will look like this:(let ((total 0)(number-of-pebbles-in-row number-of-rows))body...)The total number of pebbles an be found by repeatedly adding the num-ber of pebbles in a row to the total already found, that is, by repeatedlyevaluating the following expression:(setq total (+ total number-of-pebbles-in-row))After the number-of-pebbles-in-row is added to the total, the number-of-pebbles-in-row should be de remented by one, sin e the next time theloop repeats, the pre eding row will be added to the total.The number of pebbles in a pre eding row is one less than the numberof pebbles in a row, so the built-in Ema s Lisp fun tion 1- an be used to ompute the number of pebbles in the pre eding row. This an be done withthe following expression:(setq number-of-pebbles-in-row(1- number-of-pebbles-in-row))Finally, we know that the while loop should stop making repeated addi-tions when there are no pebbles in a row. So the test for the while loop issimply:(while (> number-of-pebbles-in-row 0)Putting the fun tion de�nition togetherWe an put these expressions together to reate a fun tion de�nition thatworks. However, on examination, we �nd that one of the lo al variables isunneeded!

Page 149: An Introduction to Programming in Emacs Lisp

Save your time: dolist and dotimes 131The fun tion de�nition looks like this:;;; First subtra tive version.(defun triangle (number-of-rows)"Add up the number of pebbles in a triangle."(let ((total 0)(number-of-pebbles-in-row number-of-rows))(while (> number-of-pebbles-in-row 0)(setq total (+ total number-of-pebbles-in-row))(setq number-of-pebbles-in-row(1- number-of-pebbles-in-row)))total))As written, this fun tion works.However, we do not need number-of-pebbles-in-row.When the triangle fun tion is evaluated, the symbol number-of-rowswill be bound to a number, giving it an initial value. That number an be hanged in the body of the fun tion as if it were a lo al variable, withoutany fear that su h a hange will e�e t the value of the variable outside ofthe fun tion. This is a very useful hara teristi of Lisp; it means thatthe variable number-of-rows an be used anywhere in the fun tion wherenumber-of-pebbles-in-row is used.Here is a se ond version of the fun tion written a bit more leanly:(defun triangle (number) ; Se ond version."Return sum of numbers 1 through NUMBER in lusive."(let ((total 0))(while (> number 0)(setq total (+ total number))(setq number (1- number)))total))In brief, a properly written while loop will onsist of three parts:1. A test that will return false after the loop has repeated itself the orre tnumber of times.2. An expression the evaluation of whi h will return the value desired afterbeing repeatedly evaluated.3. An expression to hange the value passed to the true-or-false-test sothat the test returns false after the loop has repeated itself the rightnumber of times.11.2 Save your time: dolist and dotimesIn addition to while, both dolist and dotimes provide for looping.Sometimes these are qui ker to write than the equivalent while loop. Bothare Lisp ma ros. (See se tion \Ma ros" in The GNU Ema s Lisp Referen eManual. )

Page 150: An Introduction to Programming in Emacs Lisp

132 Chapter 11: Loops and Re ursiondolist works like a while loop that ` drs down a list': dolist auto-mati ally shortens the list ea h time it loops|takes the dr of the list|andbinds the ar of ea h shorter version of the list to the �rst of its arguments.dotimes loops a spe i� number of time: you spe ify the number.The dolist Ma roSuppose, for example, you want to reverse a list, so that \�rst" \se ond"\third" be omes \third" \se ond" \�rst".In pra ti e, you would use the reverse fun tion, like this:(setq animals '(gazelle giraffe lion tiger))(reverse animals)Here is how you ould reverse the list using a while loop:(setq animals '(gazelle giraffe lion tiger))(defun reverse-list-with-while (list)"Using while, reverse the order of LIST."(let (value) ; make sure list starts empty(while list(setq value ( ons ( ar list) value))(setq list ( dr list)))value))(reverse-list-with-while animals)And here is how you ould use the dolist ma ro:(setq animals '(gazelle giraffe lion tiger))(defun reverse-list-with-dolist (list)"Using dolist, reverse the order of LIST."(let (value) ; make sure list starts empty(dolist (element list value)(setq value ( ons element value)))))(reverse-list-with-dolist animals)In Info, you an pla e your ursor after the losing parenthesis of ea h ex-pression and type C-x C-e; in ea h ase, you should see(tiger lion giraffe gazelle)in the e ho area.For this example, the existing reverse fun tion is obviously best. Thewhile loop is just like our �rst example (see Se tion 11.1.1, \A while Loopand a List", page 122). The while �rst he ks whether the list has elements;if so, it onstru ts a new list by adding the �rst element of the list to the

Page 151: An Introduction to Programming in Emacs Lisp

The dotimes Ma ro 133existing list (whi h in the �rst iteration of the loop is nil). Sin e the se ondelement is prepended in front of the �rst element, and the third element isprepended in front of the se ond element, the list is reversed.In the expression using a while loop, the (setq list ( dr list)) ex-pression shortens the list, so the while loop eventually stops. In addition,it provides the ons expression with a new �rst element by reating a newand shorter list at ea h repetition of the loop.The dolist expression does very mu h the same as the while expression,ex ept that the dolist ma ro does some of the work you have to do whenwriting a while expression.Like a while loop, a dolist loops. What is di�erent is that it automat-i ally shortens the list ea h time it loops | it ` drs down the list' on itsown | and it automati ally binds the ar of ea h shorter version of the listto the �rst of its arguments.In the example, the ar of ea h shorter version of the list is referredto using the symbol `element', the list itself is alled `list', and the valuereturned is alled `value'. The remainder of the dolist expression is thebody.The dolist expression binds the ar of ea h shorter version of the listto element and then evaluates the body of the expression; and repeats theloop. The result is returned in value.The dotimes Ma roThe dotimes ma ro is similar to dolist, ex ept that it loops a spe i� number of times.The �rst argument to dotimes is assigned the numbers 0, 1, 2 and soforth ea h time around the loop, and the value of the third argument isreturned. You need to provide the value of the se ond argument, whi h ishow many times the ma ro loops.For example, the following binds the numbers from 0 up to, but notin luding, the number 3 to the �rst argument, number, and then onstru tsa list of the three numbers. (The �rst number is 0, the se ond number is1, and the third number is 2; this makes a total of three numbers in all,starting with zero as the �rst number.)(let (value) ; otherwise a value is a void variable(dotimes (number 3 value)(setq value ( ons number value))))) (2 1 0)dotimes returns value, so the way to use dotimes is to operate on someexpression number number of times and then return the result, either as alist or an atom.

Page 152: An Introduction to Programming in Emacs Lisp

134 Chapter 11: Loops and Re ursionHere is an example of a defun that uses dotimes to add up the numberof pebbles in a triangle.(defun triangle-using-dotimes (number-of-rows)"Using dotimes, add up the number of pebbles in a triangle."(let ((total 0)) ; otherwise a total is a void variable(dotimes (number number-of-rows total)(setq total (+ total (1+ number))))))(triangle-using-dotimes 4)11.3 Re ursionA re ursive fun tion ontains ode that tells the Lisp interpreter to all aprogram that runs exa tly like itself, but with slightly di�erent arguments.The ode runs exa tly the same be ause it has the same name. However,even though it has the same name, it is not the same thread of exe ution.It is di�erent. In the jargon, it is a di�erent `instan e'.Eventually, if the program is written orre tly, the `slightly di�erent ar-guments' will be ome suÆ iently di�erent from the �rst arguments that the�nal instan e will stop.11.3.1 Building Robots: Extending the MetaphorIt is sometimes helpful to think of a running program as a robot that doesa job. In doing its job, a re ursive fun tion alls on a se ond robot to helpit. The se ond robot is identi al to the �rst in every way, ex ept that these ond robot helps the �rst and has been passed di�erent arguments thanthe �rst.In a re ursive fun tion, the se ond robot may all a third; and the thirdmay all a fourth, and so on. Ea h of these is a di�erent entity; but all are lones.Sin e ea h robot has slightly di�erent instru tions|the arguments willdi�er from one robot to the next|the last robot should know when to stop.Let's expand on the metaphor in whi h a omputer program is a robot.A fun tion de�nition provides the blueprints for a robot. When you installa fun tion de�nition, that is, when you evaluate a defun spe ial form, youinstall the ne essary equipment to build robots. It is as if you were in afa tory, setting up an assembly line. Robots with the same name are builta ording to the same blueprints. So they have, as it were, the same `modelnumber', but a di�erent `serial number'.We often say that a re ursive fun tion ` alls itself'. What we mean isthat the instru tions in a re ursive fun tion ause the Lisp interpreter torun a di�erent fun tion that has the same name and does the same job asthe �rst, but with di�erent arguments.

Page 153: An Introduction to Programming in Emacs Lisp

Re ursion with a List 135It is important that the arguments di�er from one instan e to the next;otherwise, the pro ess will never stop.11.3.2 The Parts of a Re ursive De�nitionA re ursive fun tion typi ally ontains a onditional expression whi h hasthree parts:1. A true-or-false-test that determines whether the fun tion is alled again,here alled the do-again-test.2. The name of the fun tion. When this name is alled, a new instan e ofthe fun tion|a new robot, as it were|is reated and told what to do.3. An expression that returns a di�erent value ea h time the fun tion is alled, here alled the next-step-expression. Consequently, the argu-ment (or arguments) passed to the new instan e of the fun tion willbe di�erent from that passed to the previous instan e. This auses the onditional expression, the do-again-test, to test false after the orre tnumber of repetitions.Re ursive fun tions an be mu h simpler than any other kind of fun tion.Indeed, when people �rst start to use them, they often look so mysteriouslysimple as to be in omprehensible. Like riding a bi y le, reading a re ursivefun tion de�nition takes a ertain kna k whi h is hard at �rst but then seemssimple.There are several di�erent ommon re ursive patterns. A very simplepattern looks like this:(defun name-of-re ursive-fun tion (argument-list)"do umentation..."(if do-again-testbody...(name-of-re ursive-fun tionnext-step-expression)))Ea h time a re ursive fun tion is evaluated, a new instan e of it is reatedand told what to do. The arguments tell the instan e what to do.An argument is bound to the value of the next-step-expression. Ea hinstan e runs with a di�erent value of the next-step-expression.The value in the next-step-expression is used in the do-again-test.The value returned by the next-step-expression is passed to the new in-stan e of the fun tion, whi h evaluates it (or some transmogri� ation of it)to determine whether to ontinue or stop. The next-step-expression is de-signed so that the do-again-test returns false when the fun tion should nolonger be repeated.The do-again-test is sometimes alled the stop ondition, sin e it stopsthe repetitions when it tests false.

Page 154: An Introduction to Programming in Emacs Lisp

136 Chapter 11: Loops and Re ursion11.3.3 Re ursion with a ListThe example of a while loop that printed the elements of a list of numbers an be written re ursively. Here is the ode, in luding an expression to setthe value of the variable animals to a list.If you are using Ema s 20 or before, this example must be opied to the`*s rat h*' bu�er and ea h expression must be evaluated there. Use C-u C-x C-e to evaluate the (print-elements-re ursively animals) expressionso that the results are printed in the bu�er; otherwise the Lisp interpreterwill try to squeeze the results into the one line of the e ho area.Also, pla e your ursor immediately after the last losing parenthesis ofthe print-elements-re ursively fun tion, before the omment. Other-wise, the Lisp interpreter will try to evaluate the omment.If you are using Ema s 21 or later, you an evaluate this expressiondire tly in Info.(setq animals '(gazelle giraffe lion tiger))(defun print-elements-re ursively (list)"Print ea h element of LIST on a line of its own.Uses re ursion."(if list ; do-again-test(progn(print ( ar list)) ; body(print-elements-re ursively ; re ursive all( dr list))))) ; next-step-expression(print-elements-re ursively animals)The print-elements-re ursively fun tion �rst tests whether there isany ontent in the list; if there is, the fun tion prints the �rst element of thelist, the ar of the list. Then the fun tion `invokes itself', but gives itself asits argument, not the whole list, but the se ond and subsequent elements ofthe list, the dr of the list.Put another way, if the list is not empty, the fun tion invokes anotherinstan e of ode that is similar to the initial ode, but is a di�erent threadof exe ution, with di�erent arguments than the �rst instan e.Put in yet another way, if the list is not empty, the �rst robot assemblies ase ond robot and tells it what to do; the se ond robot is a di�erent individualfrom the �rst, but is the same model.When the se ond evaluation o urs, the if expression is evaluated and iftrue, prints the �rst element of the list it re eives as its argument (whi h isthe se ond element of the original list). Then the fun tion ` alls itself' withthe dr of the list it is invoked with, whi h (the se ond time around) is the dr of the dr of the original list.

Page 155: An Introduction to Programming in Emacs Lisp

Re ursion in Pla e of a Counter 137Note that although we say that the fun tion ` alls itself', what we meanis that the Lisp interpreter assembles and instru ts a new instan e of theprogram. The new instan e is a lone of the �rst, but is a separate individual.Ea h time the fun tion `invokes itself', it invokes itself on a shorter versionof the original list. It reates a new instan e that works on a shorter list.Eventually, the fun tion invokes itself on an empty list. It reates a newinstan e whose argument is nil. The onditional expression tests the valueof list. Sin e the value of list is nil, the if expression tests false so thethen-part is not evaluated. The fun tion as a whole then returns nil.When you evaluate (print-elements-re ursively animals) in the`*s rat h*' bu�er, you see this result:giraffegazelleliontigernil11.3.4 Re ursion in Pla e of a CounterThe triangle fun tion des ribed in a previous se tion an also be writtenre ursively. It looks like this:(defun triangle-re ursively (number)"Return the sum of the numbers 1 through NUMBER in lusive.Uses re ursion."(if (= number 1) ; do-again-test1 ; then-part(+ number ; else-part(triangle-re ursively ; re ursive all(1- number))))) ; next-step-expression(triangle-re ursively 7)You an install this fun tion by evaluating it and then try it by evaluating(triangle-re ursively 7). (Remember to put your ursor immediatelyafter the last parenthesis of the fun tion de�nition, before the omment.)The fun tion evaluates to 28.To understand how this fun tion works, let's onsider what happens inthe various ases when the fun tion is passed 1, 2, 3, or 4 as the value of itsargument.First, what happens if the value of the argument is 1?The fun tion has an if expression after the do umentation string. Ittests whether the value of number is equal to 1; if so, Ema s evaluates the

Page 156: An Introduction to Programming in Emacs Lisp

138 Chapter 11: Loops and Re ursionthen-part of the if expression, whi h returns the number 1 as the value ofthe fun tion. (A triangle with one row has one pebble in it.)Suppose, however, that the value of the argument is 2. In this ase,Ema s evaluates the else-part of the if expression.The else-part onsists of an addition, the re ursive all to triangle-re ursively and a de rementing a tion; and it looks like this:(+ number (triangle-re ursively (1- number)))When Ema s evaluates this expression, the innermost expression is eval-uated �rst; then the other parts in sequen e. Here are the steps in detail:Step 1 Evaluate the innermost expression.The innermost expression is (1- number) so Ema s de rementsthe value of number from 2 to 1.Step 2 Evaluate the triangle-re ursively fun tion.The Lisp interpreter reates an individual instan e of triangle-re ursively. It does not matter that this fun tion is ontainedwithin itself. Ema s passes the result Step 1 as the argumentused by this instan e of the triangle-re ursively fun tionIn this ase, Ema s evaluates triangle-re ursively with anargument of 1. This means that this evaluation of triangle-re ursively returns 1.Step 3 Evaluate the value of number.The variable number is the se ond element of the list that startswith +; its value is 2.Step 4 Evaluate the + expression.The + expression re eives two arguments, the �rst from the eval-uation of number (Step 3) and the se ond from the evaluationof triangle-re ursively (Step 2).The result of the addition is the sum of 2 plus 1, and the number3 is returned, whi h is orre t. A triangle with two rows hasthree pebbles in it.An argument of 3 or 4Suppose that triangle-re ursively is alled with an argument of 3.Step 1 Evaluate the do-again-test.The if expression is evaluated �rst. This is the do-again test andreturns false, so the else-part of the if expression is evaluated.(Note that in this example, the do-again-test auses the fun tionto all itself when it tests false, not when it tests true.)Step 2 Evaluate the innermost expression of the else-part.The innermost expression of the else-part is evaluated, whi hde rements 3 to 2. This is the next-step-expression.

Page 157: An Introduction to Programming in Emacs Lisp

Re ursion Example Using ond 139Step 3 Evaluate the triangle-re ursively fun tion.The number 2 is passed to the triangle-re ursively fun tion.We know what happens when Ema s evaluates triangle-re ursively with an argument of 2. After going through thesequen e of a tions des ribed earlier, it returns a value of 3. Sothat is what will happen here.Step 4 Evaluate the addition.3 will be passed as an argument to the addition and will beadded to the number with whi h the fun tion was alled, whi his 3.The value returned by the fun tion as a whole will be 6.Now that we know what will happen when triangle-re ursively is alled with an argument of 3, it is evident what will happen if it is alledwith an argument of 4:In the re ursive all, the evaluation of(triangle-re ursively (1- 4))will return the value of evaluating(triangle-re ursively 3)whi h is 6 and this value will be added to 4 by the addition in thethird line.The value returned by the fun tion as a whole will be 10.Ea h time triangle-re ursively is evaluated, it evaluates a versionof itself|a di�erent instan e of itself|with a smaller argument, until theargument is small enough so that it does not evaluate itself.Note that this parti ular design for a re ursive fun tion requires thatoperations be deferred.Before (triangle-re ursively 7) an al ulate its answer, it must all(triangle-re ursively 6); and before (triangle-re ursively 6) an al ulate its answer, it must all (triangle-re ursively 5); and so on.That is to say, the al ulation that (triangle-re ursively 7) makes mustbe deferred until (triangle-re ursively 6) makes its al ulation; and(triangle-re ursively 6) must defer until (triangle-re ursively 5) ompletes; and so on.If ea h of these instan es of triangle-re ursively are thought of asdi�erent robots, the �rst robot must wait for the se ond to omplete its job,whi h must wait until the third ompletes, and so on.There is a way around this kind of waiting, whi h we will dis uss inSe tion 11.3.7, \Re ursion without Deferments", page 143.11.3.5 Re ursion Example Using ondThe version of triangle-re ursively des ribed earlier is written withthe if spe ial form. It an also be written using another spe ial form alled

Page 158: An Introduction to Programming in Emacs Lisp

140 Chapter 11: Loops and Re ursion ond. The name of the spe ial form ond is an abbreviation of the word` onditional'.Although the ond spe ial form is not used as often in the Ema s Lispsour es as if, it is used often enough to justify explaining it.The template for a ond expression looks like this:( ondbody...)where the body is a series of lists.Written out more fully, the template looks like this:( ond(�rst-true-or-false-test �rst- onsequent)(se ond-true-or-false-test se ond- onsequent)(third-true-or-false-test third- onsequent)...)When the Lisp interpreter evaluates the ond expression, it evaluates the�rst element (the ar or true-or-false-test) of the �rst expression in a seriesof expressions within the body of the ond.If the true-or-false-test returns nil the rest of that expression, the on-sequent, is skipped and the true-or-false-test of the next expression is eval-uated. When an expression is found whose true-or-false-test returns a valuethat is not nil, the onsequent of that expression is evaluated. The onse-quent an be one or more expressions. If the onsequent onsists of morethan one expression, the expressions are evaluated in sequen e and the valueof the last one is returned. If the expression does not have a onsequent, thevalue of the true-or-false-test is returned.If none of the true-or-false-tests test true, the ond expression returnsnil.Written using ond, the triangle fun tion looks like this:(defun triangle-using- ond (number)( ond ((<= number 0) 0)((= number 1) 1)((> number 1)(+ number (triangle-using- ond (1- number))))))In this example, the ond returns 0 if the number is less than or equal to0, it returns 1 if the number is 1 and it evaluates (+ number (triangle-using- ond (1- number))) if the number is greater than 1.11.3.6 Re ursive PatternsHere are three ommon re ursive patterns. Ea h involves a list. Re ursiondoes not need to involve lists, but Lisp is designed for lists and this providesa sense of its primal apabilities.

Page 159: An Introduction to Programming in Emacs Lisp

Re ursive Pattern: every 141Re ursive Pattern: everyIn the every re ursive pattern, an a tion is performed on every elementof a list.The basi pattern is:� If a list be empty, return nil.� Else, a t on the beginning of the list (the ar of the list)� through a re ursive all by the fun tion on the rest (the dr) ofthe list,� and, optionally, ombine the a ted-on element, using ons, withthe results of a ting on the rest.Here is example:(defun square-ea h (numbers-list)"Square ea h of a NUMBERS LIST, re ursively."(if (not numbers-list) ; do-again-testnil( ons(* ( ar numbers-list) ( ar numbers-list))(square-ea h ( dr numbers-list))))) ; next-step-expression(square-ea h '(1 2 3))) (1 4 9)If numbers-list is empty, do nothing. But if it has ontent, onstru t a list ombining the square of the �rst number in the list with the result of there ursive all.(The example follows the pattern exa tly: nil is returned if the numbers'list is empty. In pra ti e, you would write the onditional so it arries outthe a tion when the numbers' list is not empty.)The print-elements-re ursively fun tion (see Se tion 11.3.3, \Re ur-sion with a List", page 136) is another example of an every pattern, ex eptin this ase, rather than bring the results together using ons, we print ea helement of output.The print-elements-re ursively fun tion looks like this:(setq animals '(gazelle giraffe lion tiger))

Page 160: An Introduction to Programming in Emacs Lisp

142 Chapter 11: Loops and Re ursion(defun print-elements-re ursively (list)"Print ea h element of LIST on a line of its own.Uses re ursion."(if list ; do-again-test(progn(print ( ar list)) ; body(print-elements-re ursively ; re ursive all( dr list))))) ; next-step-expression(print-elements-re ursively animals)The pattern for print-elements-re ursively is:� If the list be empty, do nothing.� But if the list has at least one element,� a t on the beginning of the list (the ar of the list),� and make a re ursive all on the rest (the dr) of the list.Re ursive Pattern: a umulateAnother re ursive pattern is alled the a umulate pattern. In thea umulate re ursive pattern, an a tion is performed on every element of alist and the result of that a tion is a umulated with the results of perform-ing the a tion on the other elements.This is very like the `every' pattern using ons, ex ept that ons is notused, but some other ombiner.The pattern is:� If a list be empty, return zero or some other onstant.� Else, a t on the beginning of the list (the ar of the list),� and ombine that a ted-on element, using + or some other ombin-ing fun tion, with� a re ursive all by the fun tion on the rest (the dr) of the list.Here is an example:(defun add-elements (numbers-list)"Add the elements of NUMBERS-LIST together."(if (not numbers-list)0(+ ( ar numbers-list) (add-elements ( dr numbers-list)))))(add-elements '(1 2 3 4))) 10See Se tion 14.9.2, \Making a List of Files", page 194, for an example ofthe a umulate pattern.

Page 161: An Introduction to Programming in Emacs Lisp

Re ursion without Deferments 143Re ursive Pattern: keepA third re ursive pattern is alled the keep pattern. In the keep re ursivepattern, ea h element of a list is tested; the element is a ted on and theresults are kept only if the element meets a riterion.Again, this is very like the `every' pattern, ex ept the element is skippedunless it meets a riterion.The pattern has three parts:� If a list be empty, return nil.� Else, if the beginning of the list (the ar of the list) passes a test� a t on that element and ombine it, using ons with� a re ursive all by the fun tion on the rest (the dr) of the list.� Otherwise, if the beginning of the list (the ar of the list) fails the test� skip on that element,� and, re ursively all the fun tion on the rest (the dr) of the list.Here is an example that uses ond:(defun keep-three-letter-words (word-list)"Keep three letter words in WORD-LIST."( ond;; First do-again-test: stop- ondition((not word-list) nil);; Se ond do-again-test: when to a t((eq 3 (length (symbol-name ( ar word-list))));; ombine a ted-on element with re ursive all on shorter list( ons ( ar word-list) (keep-three-letter-words ( dr word-list))));; Third do-again-test: when to skip element;;; re ursively all shorter list with next-step expression(t (keep-three-letter-words ( dr word-list)))))(keep-three-letter-words '(one two three four five six))) (one two six)It goes without saying that you need not use nil as the test for when tostop; and you an, of ourse, ombine these patterns.11.3.7 Re ursion without DefermentsLet's onsider again what happens with the triangle-re ursively fun -tion. We will �nd that the intermediate al ulations are deferred until all an be done.

Page 162: An Introduction to Programming in Emacs Lisp

144 Chapter 11: Loops and Re ursionHere is the fun tion de�nition:(defun triangle-re ursively (number)"Return the sum of the numbers 1 through NUMBER in lusive.Uses re ursion."(if (= number 1) ; do-again-test1 ; then-part(+ number ; else-part(triangle-re ursively ; re ursive all(1- number))))) ; next-step-expressionWhat happens when we all this fun tion with a argument of 7?The �rst instan e of the triangle-re ursively fun tion adds the num-ber 7 to the value returned by a se ond instan e of triangle-re ursively,an instan e that has been passed an argument of 6. That is to say, the �rst al ulation is:(+ 7 (triangle-re ursively 6)The �rst instan e of triangle-re ursively|you may want to think of itas a little robot| annot omplete its job. It must hand o� the al ulationfor (triangle-re ursively 6) to a se ond instan e of the program, to ase ond robot. This se ond individual is ompletely di�erent from the �rstone; it is, in the jargon, a `di�erent instantiation'. Or, put another way, itis a di�erent robot. It is the same model as the �rst; it al ulates trianglenumbers re ursively; but it has a di�erent serial number.And what does (triangle-re ursively 6) return? It returns the num-ber 6 added to the value returned by evaluating triangle-re ursivelywith an argument of 5. Using the robot metaphor, it asks yet another robotto help it.Now the total is:(+ 7 6 (triangle-re ursively 5)And what happens next?(+ 7 6 5 (triangle-re ursively 4)Ea h time triangle-re ursively is alled, ex ept for the last time,it reates another instan e of the program|another robot|and asks it tomake a al ulation.Eventually, the full addition is set up and performed:(+ 7 6 5 4 3 2 1)This design for the fun tion defers the al ulation of the �rst step untilthe se ond an be done, and defers that until the third an be done, andso on. Ea h deferment means the omputer must remember what is beingwaited on. This is not a problem when there are only a few steps, as in thisexample. But it an be a problem when there are more steps.

Page 163: An Introduction to Programming in Emacs Lisp

No Deferment Solution 14511.3.8 No Deferment SolutionThe solution to the problem of deferred operations is to write in a mannerthat does not defer operations2. This requires writing to a di�erent pattern,often one that involves writing two fun tion de�nitions, an `initialization'fun tion and a `helper' fun tion.The `initialization' fun tion sets up the job; the `helper' fun tion does thework.Here are the two fun tion de�nitions for adding up numbers. They areso simple, I �nd them hard to understand.(defun triangle-initialization (number)"Return the sum of the numbers 1 through NUMBER in lusive.This is the `initialization' omponent of a two fun tionduo that uses re ursion."(triangle-re ursive-helper 0 0 number))(defun triangle-re ursive-helper (sum ounter number)"Return SUM, using COUNTER, through NUMBER in lusive.This is the `helper' omponent of a two fun tion duothat uses re ursion."(if (> ounter number)sum(triangle-re ursive-helper (+ sum ounter) ; sum(1+ ounter) ; ounternumber))) ; numberInstall both fun tion de�nitions by evaluating them, then all triangle-initialization with 2 rows:(triangle-initialization 2)) 3The `initialization' fun tion alls the �rst instan e of the `helper' fun tionwith three arguments: zero, zero, and a number whi h is the number of rowsin the triangle.The �rst two arguments passed to the `helper' fun tion are initializa-tion values. These values are hanged when triangle-re ursive-helperinvokes new instan es.32 The phrase tail re ursive is used to des ribe su h a pro ess, one that uses ` onstantspa e'.3 The jargon is mildly onfusing: triangle-re ursive-helper uses a pro ess that isiterative in a pro edure that is re ursive. The pro ess is alled iterative be ause the omputer need only re ord the three values, sum, ounter, and number; the pro edureis re ursive be ause the fun tion ` alls itself'. On the other hand, both the pro essand the pro edure used by triangle-re ursively are alled re ursive. The word`re ursive' has di�erent meanings in the two ontexts.

Page 164: An Introduction to Programming in Emacs Lisp

146 Chapter 11: Loops and Re ursionLet's see what happens when we have a triangle that has one row. (Thistriangle will have one pebble in it!)triangle-initialization will all its helper with the arguments 0 0 1.That fun tion will run the onditional test whether (> ounter number):(> 0 1)and �nd that the result is false, so it will invoke the then-part of the if lause: (triangle-re ursive-helper(+ sum ounter) ; sum plus ounter ) sum(1+ ounter) ; in rement ounter ) ounternumber) ; number stays the samewhi h will �rst ompute:(triangle-re ursive-helper (+ 0 0) ; sum(1+ 0) ; ounter1) ; numberwhi h is:(triangle-re ursive-helper 0 1 1)Again, (> ounter number) will be false, so again, the Lisp interpreterwill evaluate triangle-re ursive-helper, reating a new instan e withnew arguments.This new instan e will be;(triangle-re ursive-helper(+ sum ounter) ; sum plus ounter ) sum(1+ ounter) ; in rement ounter ) ounternumber) ; number stays the samewhi h is:(triangle-re ursive-helper 1 2 1)In this ase, the (> ounter number) test will be true! So the instan ewill return the value of the sum, whi h will be 1, as expe ted.Now, let's pass triangle-initialization an argument of 2, to �nd outhow many pebbles there are in a triangle with two rows.That fun tion alls (triangle-re ursive-helper 0 0 2).In stages, the instan es alled will be:sum ounter number(triangle-re ursive-helper 0 1 2)(triangle-re ursive-helper 1 2 2)(triangle-re ursive-helper 3 3 2)

Page 165: An Introduction to Programming in Emacs Lisp

Looping Exer ise 147When the last instan e is alled, the (> ounter number) test will betrue, so the instan e will return the value of sum, whi h will be 3.This kind of pattern helps when you are writing fun tions that an usemany resour es in a omputer.11.4 Looping Exer ise� Write a fun tion similar to triangle in whi h ea h row has a valuewhi h is the square of the row number. Use a while loop.� Write a fun tion similar to triangle that multiplies instead of adds thevalues.� Rewrite these two fun tions re ursively. Rewrite these fun tions using ond.� Write a fun tion for Texinfo mode that reates an index entry at thebeginning of a paragraph for every `�dfn' within the paragraph. (Ina Texinfo �le, `�dfn' marks a de�nition. For more information, see\Indi ating De�nitions, Commands, et ." in Texinfo, The GNU Do u-mentation Format.)

Page 166: An Introduction to Programming in Emacs Lisp

148 Chapter 11: Loops and Re ursion

Page 167: An Introduction to Programming in Emacs Lisp

The Regular Expression for senten e-end 14912 Regular Expression Sear hesRegular expression sear hes are used extensively in GNU Ema s. Thetwo fun tions, forward-senten e and forward-paragraph, illustrate thesesear hes well. They use regular expressions to �nd where to move point.The phrase `regular expression' is often written as `regexp'.Regular expression sear hes are des ribed in se tion \Regular ExpressionSear h" in The GNU Ema s Manual, as well as in se tion \Regular Expres-sions" in The GNU Ema s Lisp Referen e Manual. In writing this hapter,I am presuming that you have at least a mild a quaintan e with them. Themajor point to remember is that regular expressions permit you to sear hfor patterns as well as for literal strings of hara ters. For example, the odein forward-senten e sear hes for the pattern of possible hara ters that ould mark the end of a senten e, and moves point to that spot.Before looking at the ode for the forward-senten e fun tion, it is worth onsidering what the pattern that marks the end of a senten e must be.The pattern is dis ussed in the next se tion; following that is a des rip-tion of the regular expression sear h fun tion, re-sear h-forward. Theforward-senten e fun tion is des ribed in the se tion following. Finally,the forward-paragraph fun tion is des ribed in the last se tion of this hap-ter. forward-paragraph is a omplex fun tion that introdu es several newfeatures.12.1 The Regular Expression for senten e-endThe symbol senten e-end is bound to the pattern that marks the endof a senten e. What should this regular expression be?Clearly, a senten e may be ended by a period, a question mark, or anex lamation mark. Indeed, only lauses that end with one of those three hara ters should be onsidered the end of a senten e. This means that thepattern should in lude the hara ter set:[.?!℄However, we do not want forward-senten emerely to jump to a period,a question mark, or an ex lamation mark, be ause su h a hara ter mightbe used in the middle of a senten e. A period, for example, is used afterabbreviations. So other information is needed.A ording to onvention, you type two spa es after every senten e, butonly one spa e after a period, a question mark, or an ex lamation mark in thebody of a senten e. So a period, a question mark, or an ex lamation markfollowed by two spa es is a good indi ator of an end of senten e. However, ina �le, the two spa es may instead be a tab or the end of a line. This meansthat the regular expression should in lude these three items as alternatives.

Page 168: An Introduction to Programming in Emacs Lisp

150 Chapter 12: Regular Expression Sear hesThis group of alternatives will look like this:\\($\\| \\| \\)^ ^^TAB SPCHere, `$' indi ates the end of the line, and I have pointed out where the taband two spa es are inserted in the expression. Both are inserted by puttingthe a tual hara ters into the expression.Two ba kslashes, `\\', are required before the parentheses and verti albars: the �rst ba kslash quotes the following ba kslash in Ema s; and these ond indi ates that the following hara ter, the parenthesis or the verti albar, is spe ial.Also, a senten e may be followed by one or more arriage returns, likethis:[℄*Like tabs and spa es, a arriage return is inserted into a regular expressionby inserting it literally. The asterisk indi ates that the hRETi is repeated zeroor more times.But a senten e end does not onsist only of a period, a question mark or anex lamation mark followed by appropriate spa e: a losing quotation markor a losing bra e of some kind may pre ede the spa e. Indeed more thanone su h mark or bra e may pre ede the spa e. These require a expressionthat looks like this:[℄\"')}℄*In this expression, the �rst `℄' is the �rst hara ter in the expression; these ond hara ter is `"', whi h is pre eded by a `\' to tell Ema s the `"' is notspe ial. The last three hara ters are `'', `)', and `}'.All this suggests what the regular expression pattern for mat hing theend of a senten e should be; and, indeed, if we evaluate senten e-end we�nd that it returns the following value:senten e-end) "[.?!℄[℄\"')}℄*\\($\\| \\| \\)[℄*"12.2 The re-sear h-forward Fun tionThe re-sear h-forward fun tion is very like the sear h-forward fun -tion. (See Se tion 8.1.3, \The sear h-forward Fun tion", page 92.)re-sear h-forward sear hes for a regular expression. If the sear h issu essful, it leaves point immediately after the last hara ter in the target.If the sear h is ba kwards, it leaves point just before the �rst hara ter inthe target. You may tell re-sear h-forward to return t for true. (Movingpoint is therefore a `side e�e t'.)

Page 169: An Introduction to Programming in Emacs Lisp

forward-senten e 151Like sear h-forward, the re-sear h-forward fun tion takes four argu-ments:1. The �rst argument is the regular expression that the fun tion sear hesfor. The regular expression will be a string between quotations marks.2. The optional se ond argument limits how far the fun tion will sear h;it is a bound, whi h is spe i�ed as a position in the bu�er.3. The optional third argument spe i�es how the fun tion responds tofailure: nil as the third argument auses the fun tion to signal an error(and print a message) when the sear h fails; any other value auses itto return nil if the sear h fails and t if the sear h su eeds.4. The optional fourth argument is the repeat ount. A negative repeat ount auses re-sear h-forward to sear h ba kwards.The template for re-sear h-forward looks like this:(re-sear h-forward "regular-expression"limit-of-sear hwhat-to-do-if-sear h-failsrepeat- ount)The se ond, third, and fourth arguments are optional. However, if youwant to pass a value to either or both of the last two arguments, you must alsopass a value to all the pre eding arguments. Otherwise, the Lisp interpreterwill mistake whi h argument you are passing the value to.In the forward-senten e fun tion, the regular expression will be thevalue of the variable senten e-end, namely:"[.?!℄[℄\"')}℄*\\($\\| \\| \\)[℄*"The limit of the sear h will be the end of the paragraph (sin e a senten e annot go beyond a paragraph). If the sear h fails, the fun tion will returnnil; and the repeat ount will be provided by the argument to the forward-senten e fun tion.12.3 forward-senten eThe ommand to move the ursor forward a senten e is a straightforwardillustration of how to use regular expression sear hes in Ema s Lisp. Indeed,the fun tion looks longer and more ompli ated than it is; this is be ause thefun tion is designed to go ba kwards as well as forwards; and, optionally, overmore than one senten e. The fun tion is usually bound to the key ommandM-e.

Page 170: An Introduction to Programming in Emacs Lisp

152 Chapter 12: Regular Expression Sear hesHere is the ode for forward-senten e:(defun forward-senten e (&optional arg)"Move forward to next senten e-end. With argument, repeat.With negative argument, move ba kward repeatedly to senten e-beginning.Senten e ends are identified by the value of senten e-endtreated as a regular expression. Also, every paragraph boundaryterminates senten es as well."(intera tive "p")(or arg (setq arg 1))(while (< arg 0)(let ((par-beg(save-ex ursion (start-of-paragraph-text) (point))))(if (re-sear h-ba kward( on at senten e-end "[^ \t\n℄") par-beg t)(goto- har (1- (mat h-end 0)))(goto- har par-beg)))(setq arg (1+ arg)))(while (> arg 0)(let ((par-end(save-ex ursion (end-of-paragraph-text) (point))))(if (re-sear h-forward senten e-end par-end t)(skip- hars-ba kward " \t\n")(goto- har par-end)))(setq arg (1- arg))))The fun tion looks long at �rst sight and it is best to look at its skeleton�rst, and then its mus le. The way to see the skeleton is to look at theexpressions that start in the left-most olumns:(defun forward-senten e (&optional arg)"do umentation..."(intera tive "p")(or arg (setq arg 1))(while (< arg 0)body-of-while-loop(while (> arg 0)body-of-while-loopThis looks mu h simpler! The fun tion de�nition onsists of do umenta-tion, an intera tive expression, an or expression, and while loops.Let's look at ea h of these parts in turn.We note that the do umentation is thorough and understandable.The fun tion has an intera tive "p" de laration. This means that thepro essed pre�x argument, if any, is passed to the fun tion as its argument.(This will be a number.) If the fun tion is not passed an argument (itis optional) then the argument arg will be bound to 1. When forward-

Page 171: An Introduction to Programming in Emacs Lisp

The while loops 153senten e is alled non-intera tively without an argument, arg is bound tonil.The or expression handles the pre�x argument. What it does is eitherleave the value of arg as it is, but only if arg is bound to a value; or it setsthe value of arg to 1, in the ase when arg is bound to nil.The while loopsTwo while loops follow the or expression. The �rst while has a true-or-false-test that tests true if the pre�x argument for forward-senten e isa negative number. This is for going ba kwards. The body of this loop issimilar to the body of the se ond while lause, but it is not exa tly thesame. We will skip this while loop and on entrate on the se ond whileloop.The se ond while loop is for moving point forward. Its skeleton lookslike this:(while (> arg 0) ; true-or-false-test(let varlist(if (true-or-false-test)then-partelse-part(setq arg (1- arg)))) ; while loop de rementerThe while loop is of the de rementing kind. (See Se tion 11.1.4, \A Loopwith a De rementing Counter", page 129.) It has a true-or-false-test thattests true so long as the ounter (in this ase, the variable arg) is greaterthan zero; and it has a de rementer that subtra ts 1 from the value of the ounter every time the loop repeats.If no pre�x argument is given to forward-senten e, whi h is the most ommon way the ommand is used, this while loop will run on e, sin e thevalue of arg will be 1.The body of the while loop onsists of a let expression, whi h reatesand binds a lo al variable, and has, as its body, an if expression.The body of the while loop looks like this:(let ((par-end(save-ex ursion (end-of-paragraph-text) (point))))(if (re-sear h-forward senten e-end par-end t)(skip- hars-ba kward " \t\n")(goto- har par-end)))The let expression reates and binds the lo al variable par-end. As weshall see, this lo al variable is designed to provide a bound or limit to theregular expression sear h. If the sear h fails to �nd a proper senten e endingin the paragraph, it will stop on rea hing the end of the paragraph.

Page 172: An Introduction to Programming in Emacs Lisp

154 Chapter 12: Regular Expression Sear hesBut �rst, let us examine how par-end is bound to the value of the endof the paragraph. What happens is that the let sets the value of par-endto the value returned when the Lisp interpreter evaluates the expression(save-ex ursion (end-of-paragraph-text) (point))In this expression, (end-of-paragraph-text)moves point to the end of theparagraph, (point) returns the value of point, and then save-ex ursionrestores point to its original position. Thus, the let binds par-end to thevalue returned by the save-ex ursion expression, whi h is the position ofthe end of the paragraph. (The (end-of-paragraph-text) fun tion usesforward-paragraph, whi h we will dis uss shortly.)Ema s next evaluates the body of the let, whi h is an if expression thatlooks like this:(if (re-sear h-forward senten e-end par-end t) ; if-part(skip- hars-ba kward " \t\n") ; then-part(goto- har par-end))) ; else-partThe if tests whether its �rst argument is true and if so, evaluates itsthen-part; otherwise, the Ema s Lisp interpreter evaluates the else-part.The true-or-false-test of the if expression is the regular expression sear h.It may seem odd to have what looks like the `real work' of the forward-senten e fun tion buried here, but this is a ommon way this kind of oper-ation is arried out in Lisp.The regular expression sear hThe re-sear h-forward fun tion sear hes for the end of the senten e,that is, for the pattern de�ned by the senten e-end regular expression.If the pattern is found|if the end of the senten e is found|then the re-sear h-forward fun tion does two things:1. The re-sear h-forward fun tion arries out a side e�e t, whi h is tomove point to the end of the o urren e found.2. The re-sear h-forward fun tion returns a value of true. This is thevalue re eived by the if, and means that the sear h was su essful.The side e�e t, the movement of point, is ompleted before the if fun tionis handed the value returned by the su essful on lusion of the sear h.When the if fun tion re eives the value of true from a su essful all tore-sear h-forward, the if evaluates the then-part, whi h is the expression(skip- hars-ba kward " \t\n"). This expression moves ba kwards overany blank spa es, tabs or arriage returns until a printed hara ter is foundand then leaves point after the hara ter. Sin e point has already beenmoved to the end of the pattern that marks the end of the senten e, thisa tion leaves point right after the losing printed hara ter of the senten e,whi h is usually a period.On the other hand, if the re-sear h-forward fun tion fails to �nd apattern marking the end of the senten e, the fun tion returns false. The

Page 173: An Introduction to Programming in Emacs Lisp

forward-paragraph: a Goldmine of Fun tions 155false then auses the if to evaluate its third argument, whi h is (goto- harpar-end): it moves point to the end of the paragraph.Regular expression sear hes are ex eptionally useful and the pattern il-lustrated by re-sear h-forward, in whi h the sear h is the test of an ifexpression, is handy. You will see or write ode in orporating this patternoften.12.4 forward-paragraph: a Goldmine of Fun tionsThe forward-paragraph fun tion moves point forward to the end of theparagraph. It is usually bound to M-} and makes use of a number of fun tionsthat are important in themselves, in luding let*, mat h-beginning, andlooking-at.The fun tion de�nition for forward-paragraph is onsiderably longerthan the fun tion de�nition for forward-senten e be ause it works with aparagraph, ea h line of whi h may begin with a �ll pre�x.A �ll pre�x onsists of a string of hara ters that are repeated at thebeginning of ea h line. For example, in Lisp ode, it is a onvention to startea h line of a paragraph-long omment with `;;; '. In Text mode, four blankspa es make up another ommon �ll pre�x, reating an indented paragraph.(See se tion \Fill Pre�x" in The GNU Ema s Manual, for more informationabout �ll pre�xes.)The existen e of a �ll pre�x means that in addition to being able to�nd the end of a paragraph whose lines begin on the left-most olumn, theforward-paragraph fun tion must be able to �nd the end of a paragraphwhen all or many of the lines in the bu�er begin with the �ll pre�x.Moreover, it is sometimes pra ti al to ignore a �ll pre�x that exists, espe- ially when blank lines separate paragraphs. This is an added ompli ation.Rather than print all of the forward-paragraph fun tion, we will onlyprint parts of it. Read without preparation, the fun tion an be daunting!In outline, the fun tion looks like this:(defun forward-paragraph (&optional arg)"do umentation..."(intera tive "p")(or arg (setq arg 1))(let*varlist(while (< arg 0) ; ba kward-moving- ode...(setq arg (1+ arg)))(while (> arg 0) ; forward-moving- ode...(setq arg (1- arg)))))

Page 174: An Introduction to Programming in Emacs Lisp

156 Chapter 12: Regular Expression Sear hesThe �rst parts of the fun tion are routine: the fun tion's argument list onsists of one optional argument. Do umentation follows.The lower ase `p' in the intera tive de laration means that the pro- essed pre�x argument, if any, is passed to the fun tion. This will be anumber, and is the repeat ount of how many paragraphs point will move.The or expression in the next line handles the ommon ase when no argu-ment is passed to the fun tion, whi h o urs if the fun tion is alled fromother ode rather than intera tively. This ase was des ribed earlier. (SeeSe tion 12.3, \forward-senten e", page 151.) Now we rea h the end of thefamiliar part of this fun tion.The let* expressionThe next line of the forward-paragraph fun tion begins a let* expres-sion. This is a di�erent kind of expression than we have seen so far. Thesymbol is let* not let.The let* spe ial form is like let ex ept that Ema s sets ea h variablein sequen e, one after another, and variables in the latter part of the varlist an make use of the values to whi h Ema s set variables in the earlier partof the varlist.In the let* expression in this fun tion, Ema s binds two variables: fill-prefix-regexp and paragraph-separate. The value to whi h paragraph-separate is bound depends on the value of fill-prefix-regexp.Let's look at ea h in turn. The symbol fill-prefix-regexp is set tothe value returned by evaluating the following list:(and fill-prefix(not (equal fill-prefix ""))(not paragraph-ignore-fill-prefix)(regexp-quote fill-prefix))This is an expression whose �rst element is the and spe ial form.As we learned earlier (see \The kill-new fun tion", page 105), the andspe ial form evaluates ea h of its arguments until one of the argumentsreturns a value of nil, in whi h ase the and expression returns nil; however,if none of the arguments returns a value of nil, the value resulting fromevaluating the last argument is returned. (Sin e su h a value is not nil, itis onsidered true in Lisp.) In other words, an and expression returns a truevalue only if all its arguments are true.In this ase, the variable fill-prefix-regexp is bound to a non-nilvalue only if the following four expressions produ e a true (i.e., a non-nil)value when they are evaluated; otherwise, fill-prefix-regexp is bound tonil.

Page 175: An Introduction to Programming in Emacs Lisp

The let* expression 157fill-prefixWhen this variable is evaluated, the value of the �ll pre�x, ifany, is returned. If there is no �ll pre�x, this variable returnsnil.(not (equal fill-prefix "")This expression he ks whether an existing �ll pre�x is an emptystring, that is, a string with no hara ters in it. An empty stringis not a useful �ll pre�x.(not paragraph-ignore-fill-prefix)This expression returns nil if the variable paragraph-ignore-fill-prefix has been turned on by being set to a true valuesu h as t.(regexp-quote fill-prefix)This is the last argument to the and spe ial form. If all thearguments to the and are true, the value resulting from evaluat-ing this expression will be returned by the and expression andbound to the variable fill-prefix-regexp,The result of evaluating this and expression su essfully is that fill-prefix-regexp will be bound to the value of fill-prefix as modi�ed bythe regexp-quote fun tion. What regexp-quote does is read a string andreturn a regular expression that will exa tly mat h the string and mat hnothing else. This means that fill-prefix-regexp will be set to a valuethat will exa tly mat h the �ll pre�x if the �ll pre�x exists. Otherwise, thevariable will be set to nil.The se ond lo al variable in the let* expression is paragraph-separate.It is bound to the value returned by evaluating the expression:(if fill-prefix-regexp( on at paragraph-separate"\\|^" fill-prefix-regexp "[ \t℄*$")paragraph-separate)))This expression shows why let* rather than let was used. The true-or-false-test for the if depends on whether the variable fill-prefix-regexpevaluates to nil or some other value.If fill-prefix-regexp does not have a value, Ema s evaluates the else-part of the if expression and binds paragraph-separate to its lo al value.(paragraph-separate is a regular expression that mat hes what separatesparagraphs.)But if fill-prefix-regexp does have a value, Ema s evaluates the then-part of the if expression and binds paragraph-separate to a regular ex-pression that in ludes the fill-prefix-regexp as part of the pattern.Spe i� ally, paragraph-separate is set to the original value of the para-graph separate regular expression on atenated with an alternative expres-sion that onsists of the fill-prefix-regexp followed by a blank line. The

Page 176: An Introduction to Programming in Emacs Lisp

158 Chapter 12: Regular Expression Sear hes`^' indi ates that the fill-prefix-regexp must begin a line, and the op-tional whitespa e to the end of the line is de�ned by "[ \t℄*$".) The `\\|'de�nes this portion of the regexp as an alternative to paragraph-separate.Now we get into the body of the let*. The �rst part of the body of thelet* deals with the ase when the fun tion is given a negative argument andis therefore moving ba kwards. We will skip this se tion.The forward motion while loopThe se ond part of the body of the let* deals with forward motion. Itis a while loop that repeats itself so long as the value of arg is greater thanzero. In the most ommon use of the fun tion, the value of the argument is1, so the body of the while loop is evaluated exa tly on e, and the ursormoves forward one paragraph.This part handles three situations: when point is between paragraphs,when point is within a paragraph and there is a �ll pre�x, and when pointis within a paragraph and there is no �ll pre�x.The while loop looks like this:(while (> arg 0)(beginning-of-line);; between paragraphs(while (prog1 (and (not (eobp))(looking-at paragraph-separate))(forward-line 1)));; within paragraphs, with a �ll pre�x(if fill-prefix-regexp;; There is a �ll pre�x; it overrides paragraph-start.(while (and (not (eobp))(not (looking-at paragraph-separate))(looking-at fill-prefix-regexp))(forward-line 1));; within paragraphs, no �ll pre�x(if (re-sear h-forward paragraph-start nil t)(goto- har (mat h-beginning 0))(goto- har (point-max))))(setq arg (1- arg)))We an see immediately that this is a de rementing ounter while loop,using the expression (setq arg (1- arg)) as the de rementer.

Page 177: An Introduction to Programming in Emacs Lisp

Between paragraphs 159The body of the loop onsists of three expressions:;; between paragraphs(beginning-of-line)(whilebody-of-while);; within paragraphs, with �ll pre�x(if true-or-false-testthen-part;; within paragraphs, no �ll pre�xelse-partWhen the Ema s Lisp interpreter evaluates the body of the while loop, the�rst thing it does is evaluate the (beginning-of-line) expression and movepoint to the beginning of the line. Then there is an inner while loop. Thiswhile loop is designed to move the ursor out of the blank spa e betweenparagraphs, if it should happen to be there. Finally, there is an if expressionthat a tually moves point to the end of the paragraph.Between paragraphsFirst, let us look at the inner while loop. This loop handles the asewhen point is between paragraphs; it uses three fun tions that are new tous: prog1, eobp and looking-at.� prog1 is similar to the progn spe ial form, ex ept that prog1 evaluatesits arguments in sequen e and then returns the value of its �rst argumentas the value of the whole expression. (progn returns the value of its lastargument as the value of the expression.) The se ond and subsequentarguments to prog1 are evaluated only for their side e�e ts.� eobp is an abbreviation of `End Of Buffer P' and is a fun tion thatreturns true if point is at the end of the bu�er.� looking-at is a fun tion that returns true if the text following pointmat hes the regular expression passed looking-at as its argument.The while loop we are studying looks like this:(while (prog1 (and (not (eobp))(looking-at paragraph-separate))(forward-line 1)))This is a while loop with no body! The true-or-false-test of the loop is theexpression:(prog1 (and (not (eobp))(looking-at paragraph-separate))(forward-line 1))The �rst argument to the prog1 is the and expression. It has within in it atest of whether point is at the end of the bu�er and also a test of whether

Page 178: An Introduction to Programming in Emacs Lisp

160 Chapter 12: Regular Expression Sear hesthe pattern following point mat hes the regular expression for separatingparagraphs.If the ursor is not at the end of the bu�er and if the hara ters fol-lowing the ursor mark the separation between two paragraphs, then theand expression is true. After evaluating the and expression, the Lisp inter-preter evaluates the se ond argument to prog1, whi h is forward-line. Thismoves point forward one line. The value returned by the prog1 however, isthe value of its �rst argument, so the while loop ontinues so long as pointis not at the end of the bu�er and is between paragraphs. When, �nally,point is moved to a paragraph, the and expression tests false. Note however,that the forward-line ommand is arried out anyhow. This means thatwhen point is moved from between paragraphs to a paragraph, it is left atthe beginning of the se ond line of the paragraph.Within paragraphsThe next expression in the outer while loop is an if expression. TheLisp interpreter evaluates the then-part of the if when the fill-prefix-regexp variable has a value other than nil, and it evaluates the else-partwhen the value of if fill-prefix-regexp is nil, that is, when there is no�ll pre�x.No �ll pre�xIt is simplest to look at the ode for the ase when there is no �ll pre�x�rst. This ode onsists of yet another inner if expression, and reads asfollows:(if (re-sear h-forward paragraph-start nil t)(goto- har (mat h-beginning 0))(goto- har (point-max)))This expression a tually does the work that most people think of as theprimary purpose of the forward-paragraph ommand: it auses a regularexpression sear h to o ur that sear hes forward to the start of the nextparagraph and if it is found, moves point there; but if the start of anotherparagraph if not found, it moves point to the end of the a essible region ofthe bu�er.The only unfamiliar part of this is the use of mat h-beginning. This isanother fun tion that is new to us. The mat h-beginning fun tion returnsa number spe ifying the lo ation of the start of the text that was mat hedby the last regular expression sear h.The mat h-beginning fun tion is used here be ause of a hara teristi of a forward sear h: a su essful forward sear h, regardless of whether it isa plain sear h or a regular expression sear h, will move point to the end ofthe text that is found. In this ase, a su essful sear h will move point to

Page 179: An Introduction to Programming in Emacs Lisp

Summary 161the end of the pattern for paragraph-start, whi h will be the beginning ofthe next paragraph rather than the end of the urrent one.However, we want to put point at the end of the urrent paragraph, not atthe beginning of the next one. The two positions may be di�erent, be ausethere may be several blank lines between paragraphs.When given an argument of 0, mat h-beginning returns the positionthat is the start of the text that the most re ent regular expression sear hmat hed. In this ase, the most re ent regular expression sear h is the onelooking for paragraph-start, so mat h-beginning returns the beginningposition of the pattern, rather than the end of the pattern. The beginningposition is the end of the paragraph.(In identally, when passed a positive number as an argument, the mat h-beginning fun tion will pla e point at that parenthesized expression in thelast regular expression. It is a useful fun tion.)With a �ll pre�xThe inner if expression just dis ussed is the else-part of an en losing ifexpression whi h tests whether there is a �ll pre�x. If there is a �ll pre�x,the then-part of this if is evaluated. It looks like this:(while (and (not (eobp))(not (looking-at paragraph-separate))(looking-at fill-prefix-regexp))(forward-line 1))What this expression does is move point forward line by line so long as three onditions are true:1. Point is not at the end of the bu�er.2. The text following point does not separate paragraphs.3. The pattern following point is the �ll pre�x regular expression.The last ondition may be puzzling, until you remember that point wasmoved to the beginning of the line early in the forward-paragraph fun tion.This means that if the text has a �ll pre�x, the looking-at fun tion willsee it.SummaryIn summary, when moving forward, the forward-paragraph fun tiondoes the following:� Move point to the beginning of the line.� Skip over lines between paragraphs.� Che k whether there is a �ll pre�x, and if there is:| Go forward line by line so long as the line is not a paragraph sep-arating line.

Page 180: An Introduction to Programming in Emacs Lisp

162 Chapter 12: Regular Expression Sear hes� But if there is no �ll pre�x,| Sear h for the next paragraph start pattern.| Go to the beginning of the paragraph start pattern, whi h will bethe end of the previous paragraph.| Or else go to the end of the a essible portion of the bu�er.For review, here is the ode we have just been dis ussing, formatted for larity:(intera tive "p")(or arg (setq arg 1))(let* ((fill-prefix-regexp(and fill-prefix (not (equal fill-prefix ""))(not paragraph-ignore-fill-prefix)(regexp-quote fill-prefix)))(paragraph-separate(if fill-prefix-regexp( on at paragraph-separate"\\|^"fill-prefix-regexp"[ \t℄*$")paragraph-separate)))omitted-ba kward-moving- ode ...(while (> arg 0) ; forward-moving- ode(beginning-of-line)(while (prog1 (and (not (eobp))(looking-at paragraph-separate))(forward-line 1)))(if fill-prefix-regexp(while (and (not (eobp)) ; then-part(not (looking-at paragraph-separate))(looking-at fill-prefix-regexp))(forward-line 1)) ; else-part: the inner-if(if (re-sear h-forward paragraph-start nil t)(goto- har (mat h-beginning 0))(goto- har (point-max))))(setq arg (1- arg))))) ; de rementerThe full de�nition for the forward-paragraph fun tion not only in ludesthis ode for going forwards, but also ode for going ba kwards.

Page 181: An Introduction to Programming in Emacs Lisp

Create Your Own `TAGS' File 163If you are reading this inside of GNU Ema s and you want to see thewhole fun tion, you an type C-h f (des ribe-fun tion) and the name ofthe fun tion. This gives you the fun tion do umentation and the name ofthe library ontaining the fun tion's sour e. Pla e point over the name ofthe library and press the RET key; you will be taken dire tly to the sour e.(Be sure to install your sour es! Without them, you are like a person whotries to drive a ar with his eyes shut!)Or { a good habit to get into { you an type M-. (find-tag) andthe name of the fun tion when prompted for it. This will take you di-re tly to the sour e. If the find-tag fun tion �rst asks you for thename of a `TAGS' table, give it the name of the `TAGS' �le su h as`/usr/lo al/share/ema s/21.0.100/lisp/TAGS'. (The exa t path to your`TAGS' �le depends on how your opy of Ema s was installed.)You an also reate your own `TAGS' �le for dire tories that la k one.12.5 Create Your Own `TAGS' FileThe M-. (find-tag) ommand takes you dire tly to the sour e for afun tion, variable, node, or other sour e. The fun tion depends on tagstables to tell it where to go.You often need to build and install tags tables yourself. They are notbuilt automati ally. A tags table is alled a `TAGS' �le; the name is in upper ase letters.You an reate a `TAGS' �le by alling the etags program that omes asa part of the Ema s distribution. Usually, etags is ompiled and installedwhen Ema s is built. (etags is not an Ema s Lisp fun tion or a part ofEma s; it is a C program.)To reate a `TAGS' �le, �rst swit h to the dire tory in whi h you wantto reate the �le. In Ema s you an do this with the M-x d ommand,or by visiting a �le in the dire tory, or by listing the dire tory with C-x d(dired). Then run the ompile ommand, with etags *.el as the ommandto exe uteM-x ompile RET etags *.el RETto reate a `TAGS' �le.For example, if you have a large number of �les in your `~/ema s' dire -tory, as I do|I have 137 `.el' �les in it, of whi h I load 12|you an reatea `TAGS' �le for the Ema s Lisp �les in that dire tory.The etags program takes all the usual shell `wild ards'. For example,if you have two dire tories for whi h you want a single `TAGS file', typeetags *.el ../elisp/*.el, where `../elisp/' is the se ond dire tory:M-x ompile RET etags *.el ../elisp/*.el RET

Page 182: An Introduction to Programming in Emacs Lisp

164 Chapter 12: Regular Expression Sear hesTypeM-x ompile RET etags --help RETto see a list of the options a epted by etags as well as a list of supportedlanguages.The etags program handles more than 20 languages, in luding Ema sLisp, Common Lisp, S heme, C, C++, Ada, Fortran, Java, LaTeX, Pas al,Perl, Python, Texinfo, make�les, and most assemblers. The program has noswit hes for spe ifying the language; it re ognizes the language in an input�le a ording to its �le name and ontents.`etags' is very helpful when you are writing ode yourself and want torefer ba k to fun tions you have already written. Just run etags again atintervals as you write new fun tions, so they be ome part of the `TAGS' �le.If you think an appropriate `TAGS' �le already exists for what you want,but do not know where it is, you an use the lo ate program to attempt to�nd it.Type M-x lo ate RET TAGS RET and Ema s will list for you the full pathnames of all your `TAGS' �les. On my system, this ommand lists 34 `TAGS'�les. On the other hand, a `plain vanilla' system I re ently installed did not ontain any `TAGS' �les.If the tags table you want has been reated, you an use the M-x visit-tags-table ommand to spe ify it. Otherwise, you will need to reate thetag table yourself and then use M-x visit-tags-table.Building Tags in the Ema s sour esThe GNU Ema s sour es ome with a `Makefile' that ontains a sophis-ti ated etags ommand that reates, olle ts, and merges tags tables fromall over the Ema s sour es and puts the information into one `TAGS' �le inthe `sr /' dire tory below the top level of your Ema s sour e dire tory.To build this `TAGS' �le, go to the top level of your Ema s sour e dire toryand run the ompile ommand make tags:M-x ompile RET make tags RET(The make tags ommand works well with the GNU Ema s sour es, as wellas with some other sour e pa kages.)For more information, see se tion \Tag Tables" in The GNU Ema s Man-ual.12.6 ReviewHere is a brief summary of some re ently introdu ed fun tions.while Repeatedly evaluate the body of the expression so long as the�rst element of the body tests true. Then return nil. (Theexpression is evaluated only for its side e�e ts.)

Page 183: An Introduction to Programming in Emacs Lisp

Review 165For example:(let ((foo 2))(while (> foo 0)(insert (format "foo is %d.\n" foo))(setq foo (1- foo))))) foo is 2.foo is 1.nil(The insert fun tion inserts its arguments at point; the formatfun tion returns a string formatted from its arguments the waymessage formats its arguments; \n produ es a new line.)re-sear h-forwardSear h for a pattern, and if the pattern is found, move point torest just after it.Takes four arguments, like sear h-forward:1. A regular expression that spe i�es the pattern to sear h for.2. Optionally, the limit of the sear h.3. Optionally, what to do if the sear h fails, return nil or anerror message.4. Optionally, how many times to repeat the sear h; if nega-tive, the sear h goes ba kwards.let* Bind some variables lo ally to parti ular values, and then eval-uate the remaining arguments, returning the value of the lastone. While binding the lo al variables, use the lo al values ofvariables bound earlier, if any.For example:(let* ((foo 7)(bar (* 3 foo)))(message "`bar' is %d." bar))) `bar' is 21.mat h-beginningReturn the position of the start of the text found by the lastregular expression sear h.looking-atReturn t for true if the text after point mat hes the argument,whi h should be a regular expression.eobp Return t for true if point is at the end of the a essible part ofa bu�er. The end of the a essible part is the end of the bu�erif the bu�er is not narrowed; it is the end of the narrowed partif the bu�er is narrowed.

Page 184: An Introduction to Programming in Emacs Lisp

166 Chapter 12: Regular Expression Sear hesprog1 Evaluate ea h argument in sequen e and then return the valueof the �rst.For example:(prog1 1 2 3 4)) 112.7 Exer ises with re-sear h-forward� Write a fun tion to sear h for a regular expression that mat hes two ormore blank lines in sequen e.� Write a fun tion to sear h for dupli ated words, su h as `the the'. Seese tion \Syntax of Regular Expressions" in The GNU Ema s Manual,for information on how to write a regexp (a regular expression) to mat ha string that is omposed of two identi al halves. You an devise severalregexps; some are better than others. The fun tion I use is des ribedin an appendix, along with several regexps. See Appendix A, \the-theDupli ated Words Fun tion", page 241.

Page 185: An Introduction to Programming in Emacs Lisp

The ount-words-region Fun tion 16713 Counting: Repetition and RegexpsRepetition and regular expression sear hes are powerful tools that youoften use when you write ode in Ema s Lisp. This hapter illustrates theuse of regular expression sear hes through the onstru tion of word ount ommands using while loops and re ursion.The standard Ema s distribution ontains a fun tion for ounting thenumber of lines within a region. However, there is no orresponding fun tionfor ounting words.Certain types of writing ask you to ount words. Thus, if you writean essay, you may be limited to 800 words; if you write a novel, you maydis ipline yourself to write 1000 words a day. It seems odd to me thatEma s la ks a word ount ommand. Perhaps people use Ema s mostly for ode or types of do umentation that do not require word ounts; or perhapsthey restri t themselves to the operating system word ount ommand, w .Alternatively, people may follow the publishers' onvention and ompute aword ount by dividing the number of hara ters in a do ument by �ve. Inany event, here are ommands to ount words.13.1 The ount-words-region Fun tionA word ount ommand ould ount words in a line, paragraph, region,or bu�er. What should the ommand over? You ould design the ommandto ount the number of words in a omplete bu�er. However, the Ema s tra-dition en ourages exibility|you may want to ount words in just a se tion,rather than all of a bu�er. So it makes more sense to design the ommandto ount the number of words in a region. On e you have a ount-words-region ommand, you an, if you wish, ount words in a whole bu�er bymarking it with C-x h (mark-whole-buffer).Clearly, ounting words is a repetitive a t: starting from the beginningof the region, you ount the �rst word, then the se ond word, then the thirdword, and so on, until you rea h the end of the region. This means thatword ounting is ideally suited to re ursion or to a while loop.First, we will implement the word ount ommand with a while loop,then with re ursion. The ommand will, of ourse, be intera tive.The template for an intera tive fun tion de�nition is, as always:(defun name-of-fun tion (argument-list)"do umentation..."(intera tive-expression...)body...)What we need to do is �ll in the slots.The name of the fun tion should be self-explanatory and similar to theexisting ount-lines-region name. This makes the name easier to remem-ber. ount-words-region is a good hoi e.

Page 186: An Introduction to Programming in Emacs Lisp

168 Chapter 13: Counting: Repetition and RegexpsThe fun tion ounts words within a region. This means that the argumentlist must ontain symbols that are bound to the two positions, the beginningand end of the region. These two positions an be alled `beginning' and`end' respe tively. The �rst line of the do umentation should be a single sen-ten e, sin e that is all that is printed as do umentation by a ommand su has apropos. The intera tive expression will be of the form `(intera tive"r")', sin e that will ause Ema s to pass the beginning and end of theregion to the fun tion's argument list. All this is routine.The body of the fun tion needs to be written to do three tasks: �rst, toset up onditions under whi h the while loop an ount words, se ond, torun the while loop, and third, to send a message to the user.When a user alls ount-words-region, point may be at the beginningor the end of the region. However, the ounting pro ess must start at thebeginning of the region. This means we will want to put point there ifit is not already there. Exe uting (goto- har beginning) ensures this.Of ourse, we will want to return point to its expe ted position when thefun tion �nishes its work. For this reason, the body must be en losed in asave-ex ursion expression.The entral part of the body of the fun tion onsists of a while loopin whi h one expression jumps point forward word by word, and anotherexpression ounts those jumps. The true-or-false-test of the while loopshould test true so long as point should jump forward, and false when pointis at the end of the region.We ould use (forward-word 1) as the expression for moving point for-ward word by word, but it is easier to see what Ema s identi�es as a `word'if we use a regular expression sear h.A regular expression sear h that �nds the pattern for whi h it is sear hingleaves point after the last hara ter mat hed. This means that a su essionof su essful word sear hes will move point forward word by word.As a pra ti al matter, we want the regular expression sear h to jumpover whitespa e and pun tuation between words as well as over the wordsthemselves. A regexp that refuses to jump over interword whitespa e wouldnever jump more than one word! This means that the regexp should in ludethe whitespa e and pun tuation that follows a word, if any, as well as theword itself. (A word may end a bu�er and not have any following whitespa eor pun tuation, so that part of the regexp must be optional.)Thus, what we want for the regexp is a pattern de�ning one or more word onstituent hara ters followed, optionally, by one or more hara ters thatare not word onstituents. The regular expression for this is:\w+\W*The bu�er's syntax table determines whi h hara ters are and are not word onstituents. (See Se tion 14.2, \What Constitutes a Word or Symbol?",page 182, for more about syntax. Also, see se tion \The Syntax Table" in

Page 187: An Introduction to Programming in Emacs Lisp

The ount-words-region Fun tion 169The GNU Ema s Manual, and se tion \Syntax Tables" in The GNU Ema sLisp Referen e Manual.)The sear h expression looks like this:(re-sear h-forward "\\w+\\W*")(Note that paired ba kslashes pre ede the `w' and `W'. A single ba kslashhas spe ial meaning to the Ema s Lisp interpreter. It indi ates that the fol-lowing hara ter is interpreted di�erently than usual. For example, the two hara ters, `\n', stand for `newline', rather than for a ba kslash followed by`n'. Two ba kslashes in a row stand for an ordinary, `unspe ial' ba kslash.)We need a ounter to ount how many words there are; this variablemust �rst be set to 0 and then in remented ea h time Ema s goes aroundthe while loop. The in rementing expression is simply:(setq ount (1+ ount))Finally, we want to tell the user how many words there are in the region.The message fun tion is intended for presenting this kind of information tothe user. The message has to be phrased so that it reads properly regardlessof how many words there are in the region: we don't want to say that \thereare 1 words in the region". The on i t between singular and plural isungrammati al. We an solve this problem by using a onditional expressionthat evaluates di�erent messages depending on the number of words in theregion. There are three possibilities: no words in the region, one word in theregion, and more than one word. This means that the ond spe ial form isappropriate.All this leads to the following fun tion de�nition:;;; First version; has bugs!(defun ount-words-region (beginning end)"Print number of words in the region.Words are defined as at least one word- onstituent hara ter followed by at least one hara ter thatis not a word- onstituent. The buffer's syntaxtable determines whi h hara ters these are."(intera tive "r")(message "Counting words in region ... ");;; 1. Set up appropriate onditions.(save-ex ursion(goto- har beginning)(let (( ount 0));;; 2. Run the while loop.(while (< (point) end)(re-sear h-forward "\\w+\\W*")(setq ount (1+ ount)))

Page 188: An Introduction to Programming in Emacs Lisp

170 Chapter 13: Counting: Repetition and Regexps;;; 3. Send a message to the user.( ond ((zerop ount)(message"The region does NOT have any words."))((= 1 ount)(message"The region has 1 word."))(t(message"The region has %d words." ount))))))As written, the fun tion works, but not in all ir umstan es.13.1.1 The Whitespa e Bug in ount-words-regionThe ount-words-region ommand des ribed in the pre eding se tionhas two bugs, or rather, one bug with two manifestations. First, if youmark a region ontaining only whitespa e in the middle of some text, the ount-words-region ommand tells you that the region ontains one word!Se ond, if you mark a region ontaining only whitespa e at the end of thebu�er or the a essible portion of a narrowed bu�er, the ommand displaysan error message that looks like this:Sear h failed: "\\w+\\W*"If you are reading this in Info in GNU Ema s, you an test for these bugsyourself.First, evaluate the fun tion in the usual manner to install it.If you wish, you an also install this keybinding by evaluating it:(global-set-key "\C- =" ' ount-words-region)To ondu t the �rst test, set mark and point to the beginning and end ofthe following line and then type C- = (or M-x ount-words-region if youhave not bound C- =):one two threeEma s will tell you, orre tly, that the region has three words.Repeat the test, but pla e mark at the beginning of the line and pla epoint just before the word `one'. Again type the ommand C- = (or M-x ount-words-region). Ema s should tell you that the region has no words,sin e it is omposed only of the whitespa e at the beginning of the line. Butinstead Ema s tells you that the region has one word!For the third test, opy the sample line to the end of the `*s rat h*'bu�er and then type several spa es at the end of the line. Pla e mark rightafter the word `three' and point at the end of line. (The end of the linewill be the end of the bu�er.) Type C- = (or M-x ount-words-region) asyou did before. Again, Ema s should tell you that the region has no words,

Page 189: An Introduction to Programming in Emacs Lisp

The Whitespa e Bug in ount-words-region 171sin e it is omposed only of the whitespa e at the end of the line. Instead,Ema s displays an error message saying `Sear h failed'.The two bugs stem from the same problem.Consider the �rst manifestation of the bug, in whi h the ommand tellsyou that the whitespa e at the beginning of the line ontains one word.What happens is this: The M-x ount-words-region ommand moves pointto the beginning of the region. The while tests whether the value of pointis smaller than the value of end, whi h it is. Consequently, the regularexpression sear h looks for and �nds the �rst word. It leaves point after theword. ount is set to one. The while loop repeats; but this time the valueof point is larger than the value of end, the loop is exited; and the fun tiondisplays a message saying the number of words in the region is one. In brief,the regular expression sear h looks for and �nds the word even though it isoutside the marked region.In the se ond manifestation of the bug, the region is whitespa e at theend of the bu�er. Ema s says `Sear h failed'. What happens is that thetrue-or-false-test in the while loop tests true, so the sear h expression isexe uted. But sin e there are no more words in the bu�er, the sear h fails.In both manifestations of the bug, the sear h extends or attempts toextend outside of the region.The solution is to limit the sear h to the region|this is a fairly simplea tion, but as you may have ome to expe t, it is not quite as simple as youmight think.As we have seen, the re-sear h-forward fun tion takes a sear h patternas its �rst argument. But in addition to this �rst, mandatory argument, ita epts three optional arguments. The optional se ond argument bounds thesear h. The optional third argument, if t, auses the fun tion to return nilrather than signal an error if the sear h fails. The optional fourth argumentis a repeat ount. (In Ema s, you an see a fun tion's do umentation bytyping C-h f, the name of the fun tion, and then hRETi.)In the ount-words-region de�nition, the value of the end of the regionis held by the variable end whi h is passed as an argument to the fun -tion. Thus, we an add end as an argument to the regular expression sear hexpression:(re-sear h-forward "\\w+\\W*" end)However, if you make only this hange to the ount-words-region de�ni-tion and then test the new version of the de�nition on a stret h of whitespa e,you will re eive an error message saying `Sear h failed'.What happens is this: the sear h is limited to the region, and fails asyou expe t be ause there are no word- onstituent hara ters in the region.Sin e it fails, we re eive an error message. But we do not want to re eive anerror message in this ase; we want to re eive the message that "The regiondoes NOT have any words."

Page 190: An Introduction to Programming in Emacs Lisp

172 Chapter 13: Counting: Repetition and RegexpsThe solution to this problem is to provide re-sear h-forward with athird argument of t, whi h auses the fun tion to return nil rather thansignal an error if the sear h fails.However, if you make this hange and try it, you will see the message\Counting words in region ... " and . . . you will keep on seeing that message. . . , until you type C-g (keyboard-quit).Here is what happens: the sear h is limited to the region, as before, andit fails be ause there are no word- onstituent hara ters in the region, asexpe ted. Consequently, the re-sear h-forward expression returns nil.It does nothing else. In parti ular, it does not move point, whi h it doesas a side e�e t if it �nds the sear h target. After the re-sear h-forwardexpression returns nil, the next expression in the while loop is evaluated.This expression in rements the ount. Then the loop repeats. The true-or-false-test tests true be ause the value of point is still less than the value ofend, sin e the re-sear h-forward expression did not move point. . . . andthe y le repeats . . .The ount-words-region de�nition requires yet another modi� ation,to ause the true-or-false-test of the while loop to test false if the sear hfails. Put another way, there are two onditions that must be satis�ed in thetrue-or-false-test before the word ount variable is in remented: point muststill be within the region and the sear h expression must have found a wordto ount.Sin e both the �rst ondition and the se ond ondition must be truetogether, the two expressions, the region test and the sear h expression, anbe joined with an and spe ial form and embedded in the while loop as thetrue-or-false-test, like this:(and (< (point) end) (re-sear h-forward "\\w+\\W*" end t))(For information about and, see Se tion 12.4, \forward-paragraph: a Gold-mine of Fun tions", page 155.)The re-sear h-forward expression returns t if the sear h su eeds andas a side e�e t moves point. Consequently, as words are found, point ismoved through the region. When the sear h expression fails to �nd anotherword, or when point rea hes the end of the region, the true-or-false-test testsfalse, the while loop exists, and the ount-words-region fun tion displaysone or other of its messages.After in orporating these �nal hanges, the ount-words-region workswithout bugs (or at least, without bugs that I have found!). Here is what itlooks like:;;; Final version: while(defun ount-words-region (beginning end)"Print number of words in the region."(intera tive "r")(message "Counting words in region ... ")

Page 191: An Introduction to Programming in Emacs Lisp

Count Words Re ursively 173;;; 1. Set up appropriate onditions.(save-ex ursion(let (( ount 0))(goto- har beginning);;; 2. Run the while loop.(while (and (< (point) end)(re-sear h-forward "\\w+\\W*" end t))(setq ount (1+ ount)));;; 3. Send a message to the user.( ond ((zerop ount)(message"The region does NOT have any words."))((= 1 ount)(message"The region has 1 word."))(t(message"The region has %d words." ount))))))13.2 Count Words Re ursivelyYou an write the fun tion for ounting words re ursively as well as witha while loop. Let's see how this is done.First, we need to re ognize that the ount-words-region fun tion hasthree jobs: it sets up the appropriate onditions for ounting to o ur; it ounts the words in the region; and it sends a message to the user tellinghow many words there are.If we write a single re ursive fun tion to do everything, we will re eivea message for every re ursive all. If the region ontains 13 words, we willre eive thirteen messages, one right after the other. We don't want this!Instead, we must write two fun tions to do the job, one of whi h (the re ur-sive fun tion) will be used inside of the other. One fun tion will set up the onditions and display the message; the other will return the word ount.Let us start with the fun tion that auses the message to be displayed.We an ontinue to all this ount-words-region.This is the fun tion that the user will all. It will be intera tive. Indeed,it will be similar to our previous versions of this fun tion, ex ept that itwill all re ursive- ount-words to determine how many words are in theregion.

Page 192: An Introduction to Programming in Emacs Lisp

174 Chapter 13: Counting: Repetition and RegexpsWe an readily onstru t a template for this fun tion, based on our pre-vious versions:;; Re ursive version; uses regular expression sear h(defun ount-words-region (beginning end)"do umentation..."(intera tive-expression...);;; 1. Set up appropriate onditions.(explanatory message)(set-up fun tions...;;; 2. Count the words.re ursive all;;; 3. Send a message to the user.message providing word ount))The de�nition looks straightforward, ex ept that somehow the ount re-turned by the re ursive all must be passed to the message displaying theword ount. A little thought suggests that this an be done by making useof a let expression: we an bind a variable in the varlist of a let expressionto the number of words in the region, as returned by the re ursive all; andthen the ond expression, using binding, an display the value to the user.Often, one thinks of the binding within a let expression as somehowse ondary to the `primary' work of a fun tion. But in this ase, what youmight onsider the `primary' job of the fun tion, ounting words, is donewithin the let expression.Using let, the fun tion de�nition looks like this:(defun ount-words-region (beginning end)"Print number of words in the region."(intera tive "r");;; 1. Set up appropriate onditions.(message "Counting words in region ... ")(save-ex ursion(goto- har beginning);;; 2. Count the words.(let (( ount (re ursive- ount-words end)))

Page 193: An Introduction to Programming in Emacs Lisp

Count Words Re ursively 175;;; 3. Send a message to the user.( ond ((zerop ount)(message"The region does NOT have any words."))((= 1 ount)(message"The region has 1 word."))(t(message"The region has %d words." ount))))))Next, we need to write the re ursive ounting fun tion.A re ursive fun tion has at least three parts: the `do-again-test', the`next-step-expression', and the re ursive all.The do-again-test determines whether the fun tion will or will not be alled again. Sin e we are ounting words in a region and an use a fun tionthat moves point forward for every word, the do-again-test an he k whetherpoint is still within the region. The do-again-test should �nd the value ofpoint and determine whether point is before, at, or after the value of theend of the region. We an use the point fun tion to lo ate point. Clearly,we must pass the value of the end of the region to the re ursive ountingfun tion as an argument.In addition, the do-again-test should also test whether the sear h �nds aword. If it does not, the fun tion should not all itself again.The next-step-expression hanges a value so that when the re ursive fun -tion is supposed to stop alling itself, it stops. More pre isely, the next-step-expression hanges a value so that at the right time, the do-again-test stopsthe re ursive fun tion from alling itself again. In this ase, the next-step-expression an be the expression that moves point forward, word by word.The third part of a re ursive fun tion is the re ursive all.Somewhere, also, we also need a part that does the `work' of the fun tion,a part that does the ounting. A vital part!But already, we have an outline of the re ursive ounting fun tion:(defun re ursive- ount-words (region-end)"do umentation..."do-again-testnext-step-expressionre ursive all)Now we need to �ll in the slots. Let's start with the simplest ases �rst:if point is at or beyond the end of the region, there annot be any words inthe region, so the fun tion should return zero. Likewise, if the sear h fails,there are no words to ount, so the fun tion should return zero.On the other hand, if point is within the region and the sear h su eeds,the fun tion should all itself again.

Page 194: An Introduction to Programming in Emacs Lisp

176 Chapter 13: Counting: Repetition and RegexpsThus, the do-again-test should look like this:(and (< (point) region-end)(re-sear h-forward "\\w+\\W*" region-end t))Note that the sear h expression is part of the do-again-test|the fun tionreturns t if its sear h su eeds and nil if it fails. (See Se tion 13.1.1, \TheWhitespa e Bug in ount-words-region", page 170, for an explanation ofhow re-sear h-forward works.)The do-again-test is the true-or-false test of an if lause. Clearly, ifthe do-again-test su eeds, the then-part of the if lause should all thefun tion again; but if it fails, the else-part should return zero sin e eitherpoint is outside the region or the sear h failed be ause there were no wordsto �nd.But before onsidering the re ursive all, we need to onsider the next-step-expression. What is it? Interestingly, it is the sear h part of the do-again-test.In addition to returning t or nil for the do-again-test, re-sear h-forward moves point forward as a side e�e t of a su essful sear h. This isthe a tion that hanges the value of point so that the re ursive fun tion stops alling itself when point ompletes its movement through the region. Con-sequently, the re-sear h-forward expression is the next-step-expression.In outline, then, the body of the re ursive- ount-words fun tion lookslike this:(if do-again-test-and-next-step- ombined;; thenre ursive- all-returning- ount;; elsereturn-zero)How to in orporate the me hanism that ounts?If you are not used to writing re ursive fun tions, a question like this anbe troublesome. But it an and should be approa hed systemati ally.We know that the ounting me hanism should be asso iated in someway with the re ursive all. Indeed, sin e the next-step-expression movespoint forward by one word, and sin e a re ursive all is made for ea h word,the ounting me hanism must be an expression that adds one to the valuereturned by a all to re ursive- ount-words.Consider several ases:� If there are two words in the region, the fun tion should return a valueresulting from adding one to the value returned when it ounts the �rstword, plus the number returned when it ounts the remaining words inthe region, whi h in this ase is one.� If there is one word in the region, the fun tion should return a valueresulting from adding one to the value returned when it ounts that

Page 195: An Introduction to Programming in Emacs Lisp

Count Words Re ursively 177word, plus the number returned when it ounts the remaining words inthe region, whi h in this ase is zero.� If there are no words in the region, the fun tion should return zero.From the sket h we an see that the else-part of the if returns zero forthe ase of no words. This means that the then-part of the if must returna value resulting from adding one to the value returned from a ount of theremaining words.The expression will look like this, where 1+ is a fun tion that adds oneto its argument.(1+ (re ursive- ount-words region-end))The whole re ursive- ount-words fun tion will then look like this:(defun re ursive- ount-words (region-end)"do umentation...";;; 1. do-again-test(if (and (< (point) region-end)(re-sear h-forward "\\w+\\W*" region-end t));;; 2. then-part: the re ursive all(1+ (re ursive- ount-words region-end));;; 3. else-part0))Let's examine how this works:If there are no words in the region, the else part of the if expression isevaluated and onsequently the fun tion returns zero.If there is one word in the region, the value of point is less than the valueof region-end and the sear h su eeds. In this ase, the true-or-false-testof the if expression tests true, and the then-part of the if expression isevaluated. The ounting expression is evaluated. This expression returns avalue (whi h will be the value returned by the whole fun tion) that is thesum of one added to the value returned by a re ursive all.Meanwhile, the next-step-expression has aused point to jump over the�rst (and in this ase only) word in the region. This means that when(re ursive- ount-words region-end) is evaluated a se ond time, as aresult of the re ursive all, the value of point will be equal to or greaterthan the value of region end. So this time, re ursive- ount-words willreturn zero. The zero will be added to one, and the original evaluation ofre ursive- ount-words will return one plus zero, whi h is one, whi h isthe orre t amount.Clearly, if there are two words in the region, the �rst all to re ursive- ount-words returns one added to the value returned by alling re ursive- ount-words on a region ontaining the remaining word|that is, it addsone to one, produ ing two, whi h is the orre t amount.

Page 196: An Introduction to Programming in Emacs Lisp

178 Chapter 13: Counting: Repetition and RegexpsSimilarly, if there are three words in the region, the �rst all tore ursive- ount-words returns one added to the value returned by allingre ursive- ount-words on a region ontaining the remaining two words|and so on and so on.With full do umentation the two fun tions look like this:The re ursive fun tion:(defun re ursive- ount-words (region-end)"Number of words between point and REGION-END.";;; 1. do-again-test(if (and (< (point) region-end)(re-sear h-forward "\\w+\\W*" region-end t));;; 2. then-part: the re ursive all(1+ (re ursive- ount-words region-end));;; 3. else-part0))The wrapper:;;; Re ursive version(defun ount-words-region (beginning end)"Print number of words in the region.Words are defined as at least one word- onstituent hara ter followed by at least one hara ter that isnot a word- onstituent. The buffer's syntax tabledetermines whi h hara ters these are."(intera tive "r")(message "Counting words in region ... ")(save-ex ursion(goto- har beginning)(let (( ount (re ursive- ount-words end)))( ond ((zerop ount)(message"The region does NOT have any words."))((= 1 ount)(message "The region has 1 word."))(t(message"The region has %d words." ount))))))

Page 197: An Introduction to Programming in Emacs Lisp

Exer ise: Counting Pun tuation 17913.3 Exer ise: Counting Pun tuationUsing a while loop, write a fun tion to ount the number of pun tuationmarks in a region|period, omma, semi olon, olon, ex lamation mark, andquestion mark. Do the same using re ursion.

Page 198: An Introduction to Programming in Emacs Lisp

180 Chapter 13: Counting: Repetition and Regexps

Page 199: An Introduction to Programming in Emacs Lisp

What to Count? 18114 Counting Words in a defunOur next proje t is to ount the number of words in a fun tion de�nition.Clearly, this an be done using some variant of ount-word-region. SeeChapter 13, \Counting Words: Repetition and Regexps", page 167. If weare just going to ount the words in one de�nition, it is easy enough tomark the de�nition with the C-M-h (mark-defun) ommand, and then all ount-word-region.However, I am more ambitious: I want to ount the words and symbolsin every de�nition in the Ema s sour es and then print a graph that showshow many fun tions there are of ea h length: how many ontain 40 to 49words or symbols, how many ontain 50 to 59 words or symbols, and so on.I have often been urious how long a typi al fun tion is, and this will tell.Des ribed in one phrase, the histogram proje t is daunting; but dividedinto numerous small steps, ea h of whi h we an take one at a time, theproje t be omes less fearsome. Let us onsider what the steps must be:� First, write a fun tion to ount the words in one de�nition. This in ludesthe problem of handling symbols as well as words.� Se ond, write a fun tion to list the numbers of words in ea h fun tionin a �le. This fun tion an use the ount-words-in-defun fun tion.� Third, write a fun tion to list the numbers of words in ea h fun tionin ea h of several �les. This entails automati ally �nding the various�les, swit hing to them, and ounting the words in the de�nitions withinthem.� Fourth, write a fun tion to onvert the list of numbers that we reatedin step three to a form that will be suitable for printing as a graph.� Fifth, write a fun tion to print the results as a graph.This is quite a proje t! But if we take ea h step slowly, it will not bediÆ ult.14.1 What to Count?When we �rst start thinking about how to ount the words in a fun tionde�nition, the �rst question is (or ought to be) what are we going to ount?When we speak of `words' with respe t to a Lisp fun tion de�nition, we area tually speaking, in large part, of `symbols'. For example, the followingmultiply-by-seven fun tion ontains the �ve symbols defun, multiply-by-seven, number, *, and 7. In addition, in the do umentation string, it ontains the four words `Multiply', `NUMBER', `by', and `seven'. The symbol`number' is repeated, so the de�nition ontains a total of ten words andsymbols.(defun multiply-by-seven (number)"Multiply NUMBER by seven."(* 7 number))

Page 200: An Introduction to Programming in Emacs Lisp

182 Chapter 14: Counting Words in a defunHowever, if we mark the multiply-by-seven de�nition with C-M-h (mark-defun), and then all ount-words-region on it, we will �nd that ount-words-region laims the de�nition has eleven words, not ten! Something iswrong!The problem is twofold: ount-words-region does not ount the `*' asa word, and it ounts the single symbol, multiply-by-seven, as ontainingthree words. The hyphens are treated as if they were interword spa es ratherthan intraword onne tors: `multiply-by-seven' is ounted as if it werewritten `multiply by seven'.The ause of this onfusion is the regular expression sear h within the ount-words-region de�nition that moves point forward word by word. Inthe anoni al version of ount-words-region, the regexp is:"\\w+\\W*"This regular expression is a pattern de�ning one or more word onstituent hara ters possibly followed by one or more hara ters that are not word onstituents. What is meant by `word onstituent hara ters' brings us tothe issue of syntax, whi h is worth a se tion of its own.14.2 What Constitutes a Word or Symbol?Ema s treats di�erent hara ters as belonging to di�erent syntax ate-gories. For example, the regular expression, `\\w+', is a pattern spe ifyingone or more word onstituent hara ters. Word onstituent hara ters aremembers of one syntax ategory. Other syntax ategories in lude the lassof pun tuation hara ters, su h as the period and the omma, and the lassof whitespa e hara ters, su h as the blank spa e and the tab hara ter.(For more information, see se tion \The Syntax Table" in The GNU Ema sManual, and se tion \Syntax Tables" in The GNU Ema s Lisp Referen eManual.)Syntax tables spe ify whi h hara ters belong to whi h ategories. Usu-ally, a hyphen is not spe i�ed as a `word onstituent hara ter'. Instead,it is spe i�ed as being in the ` lass of hara ters that are part of symbolnames but not words.' This means that the ount-words-region fun tiontreats it in the same way it treats an interword white spa e, whi h is why ount-words-region ounts `multiply-by-seven' as three words.There are two ways to ause Ema s to ount `multiply-by-seven' asone symbol: modify the syntax table or modify the regular expression.We ould rede�ne a hyphen as a word onstituent hara ter by modifyingthe syntax table that Ema s keeps for ea h mode. This a tion would serveour purpose, ex ept that a hyphen is merely the most ommon hara terwithin symbols that is not typi ally a word onstituent hara ter; there areothers, too.

Page 201: An Introduction to Programming in Emacs Lisp

The ount-words-in-defun Fun tion 183Alternatively, we an rede�ne the regular expression used in the ount-words de�nition so as to in lude symbols. This pro edure has the merit of larity, but the task is a little tri ky.The �rst part is simple enough: the pattern must mat h \at least one hara ter that is a word or symbol onstituent". Thus:"\\(\\w\\|\\s_\\)+"The `\\(' is the �rst part of the grouping onstru t that in ludes the `\\w'and the `\\s_' as alternatives, separated by the `\\|'. The `\\w' mat hes anyword- onstituent hara ter and the `\\s_' mat hes any hara ter that is partof a symbol name but not a word- onstituent hara ter. The `+' followingthe group indi ates that the word or symbol onstituent hara ters must bemat hed at least on e.However, the se ond part of the regexp is more diÆ ult to design. Whatwe want is to follow the �rst part with \optionally one or more hara tersthat are not onstituents of a word or symbol". At �rst, I thought I ouldde�ne this with the following:"\\(\\W\\|\\S_\\)*"The upper ase `W' and `S' mat h hara ters that are not word or symbol onstituents. Unfortunately, this expression mat hes any hara ter that iseither not a word onstituent or not a symbol onstituent. This mat hes any hara ter!I then noti ed that every word or symbol in my test region was followedby white spa e (blank spa e, tab, or newline). So I tried pla ing a patternto mat h one or more blank spa es after the pattern for one or more wordor symbol onstituents. This failed, too. Words and symbols are oftenseparated by whitespa e, but in a tual ode parentheses may follow symbolsand pun tuation may follow words. So �nally, I designed a pattern in whi hthe word or symbol onstituents are followed optionally by hara ters thatare not white spa e and then followed optionally by white spa e.Here is the full regular expression:"\\(\\w\\|\\s_\\)+[^ \t\n℄*[ \t\n℄*"14.3 The ount-words-in-defun Fun tionWe have seen that there are several ways to write a ount-word-regionfun tion. To write a ount-words-in-defun, we need merely adapt one ofthese versions.The version that uses a while loop is easy to understand, so I am going toadapt that. Be ause ount-words-in-defunwill be part of a more omplexprogram, it need not be intera tive and it need not display a message butjust return the ount. These onsiderations simplify the de�nition a little.On the other hand, ount-words-in-defun will be used within a bu�erthat ontains fun tion de�nitions. Consequently, it is reasonable to ask that

Page 202: An Introduction to Programming in Emacs Lisp

184 Chapter 14: Counting Words in a defunthe fun tion determine whether it is alled when point is within a fun tionde�nition, and if it is, to return the ount for that de�nition. This adds omplexity to the de�nition, but saves us from needing to pass argumentsto the fun tion.These onsiderations lead us to prepare the following template:(defun ount-words-in-defun ()"do umentation..."(set up...(while loop...)return ount)As usual, our job is to �ll in the slots.First, the set up.We are presuming that this fun tion will be alled within a bu�er on-taining fun tion de�nitions. Point will either be within a fun tion de�nitionor not. For ount-words-in-defun to work, point must move to the begin-ning of the de�nition, a ounter must start at zero, and the ounting loopmust stop when point rea hes the end of the de�nition.The beginning-of-defun fun tion sear hes ba kwards for an openingdelimiter su h as a `(' at the beginning of a line, and moves point to thatposition, or else to the limit of the sear h. In pra ti e, this means thatbeginning-of-defun moves point to the beginning of an en losing or pre- eding fun tion de�nition, or else to the beginning of the bu�er. We an usebeginning-of-defun to pla e point where we wish to start.The while loop requires a ounter to keep tra k of the words or symbolsbeing ounted. A let expression an be used to reate a lo al variable forthis purpose, and bind it to an initial value of zero.The end-of-defun fun tion works like beginning-of-defun ex ept thatit moves point to the end of the de�nition. end-of-defun an be used as partof an expression that determines the position of the end of the de�nition.The set up for ount-words-in-defun takes shape rapidly: �rst we movepoint to the beginning of the de�nition, then we reate a lo al variable tohold the ount, and �nally, we re ord the position of the end of the de�nitionso the while loop will know when to stop looping.The ode looks like this:(beginning-of-defun)(let (( ount 0)(end (save-ex ursion (end-of-defun) (point))))The ode is simple. The only slight ompli ation is likely to on ern end: itis bound to the position of the end of the de�nition by a save-ex ursionexpression that returns the value of point after end-of-defun temporarilymoves it to the end of the de�nition.The se ond part of the ount-words-in-defun, after the set up, is thewhile loop.

Page 203: An Introduction to Programming in Emacs Lisp

The ount-words-in-defun Fun tion 185The loop must ontain an expression that jumps point forward word byword and symbol by symbol, and another expression that ounts the jumps.The true-or-false-test for the while loop should test true so long as pointshould jump forward, and false when point is at the end of the de�nition.We have already rede�ned the regular expression for this (see Se tion 14.2,\Syntax", page 182), so the loop is straightforward:(while (and (< (point) end)(re-sear h-forward"\\(\\w\\|\\s_\\)+[^ \t\n℄*[ \t\n℄*" end t)(setq ount (1+ ount)))The third part of the fun tion de�nition returns the ount of words andsymbols. This part is the last expression within the body of the let expres-sion, and an be, very simply, the lo al variable ount, whi h when evaluatedreturns the ount.Put together, the ount-words-in-defun de�nition looks like this:(defun ount-words-in-defun ()"Return the number of words and symbols in a defun."(beginning-of-defun)(let (( ount 0)(end (save-ex ursion (end-of-defun) (point))))(while(and (< (point) end)(re-sear h-forward"\\(\\w\\|\\s_\\)+[^ \t\n℄*[ \t\n℄*"end t))(setq ount (1+ ount))) ount))How to test this? The fun tion is not intera tive, but it is easy to put awrapper around the fun tion to make it intera tive; we an use almost thesame ode as for the re ursive version of ount-words-region:;;; Intera tive version.(defun ount-words-defun ()"Number of words and symbols in a fun tion definition."(intera tive)(message"Counting words and symbols in fun tion definition ... ")(let (( ount ( ount-words-in-defun)))( ond((zerop ount)(message"The definition does NOT have any words or symbols."))

Page 204: An Introduction to Programming in Emacs Lisp

186 Chapter 14: Counting Words in a defun((= 1 ount)(message"The definition has 1 word or symbol."))(t(message"The definition has %d words or symbols." ount)))))Let's re-use C- = as a onvenient keybinding:(global-set-key "\C- =" ' ount-words-defun)Now we an try out ount-words-defun: install both ount-words-in-defun and ount-words-defun, and set the keybinding, and then pla e the ursor within the following de�nition:(defun multiply-by-seven (number)"Multiply NUMBER by seven."(* 7 number))) 10Su ess! The de�nition has 10 words and symbols.The next problem is to ount the numbers of words and symbols in severalde�nitions within a single �le.14.4 Count Several defuns Within a FileA �le su h as `simple.el' may have 80 or more fun tion de�nitions withinit. Our long term goal is to olle t statisti s on many �les, but as a �rststep, our immediate goal is to olle t statisti s on one �le.The information will be a series of numbers, ea h number being the lengthof a fun tion de�nition. We an store the numbers in a list.We know that we will want to in orporate the information regarding one�le with information about many other �les; this means that the fun tionfor ounting de�nition lengths within one �le need only return the list oflengths. It need not and should not display any messages.The word ount ommands ontain one expression to jump point forwardword by word and another expression to ount the jumps. The fun tion toreturn the lengths of de�nitions an be designed to work the same way, withone expression to jump point forward de�nition by de�nition and anotherexpression to onstru t the lengths' list.This statement of the problem makes it elementary to write the fun tionde�nition. Clearly, we will start the ount at the beginning of the �le, sothe �rst ommand will be (goto- har (point-min)). Next, we start thewhile loop; and the true-or-false test of the loop an be a regular expressionsear h for the next fun tion de�nition|so long as the sear h su eeds, pointis moved forward and then the body of the loop is evaluated. The body needsan expression that onstru ts the lengths' list. ons, the list onstru tion ommand, an be used to reate the list. That is almost all there is to it.

Page 205: An Introduction to Programming in Emacs Lisp

lengths-list-file in Detail 187Here is what this fragment of ode looks like:(goto- har (point-min))(while (re-sear h-forward "^(defun" nil t)(setq lengths-list( ons ( ount-words-in-defun) lengths-list)))What we have left out is the me hanism for �nding the �le that ontainsthe fun tion de�nitions.In previous examples, we either used this, the Info �le, or we swit hedba k and forth to some other bu�er, su h as the `*s rat h*' bu�er.Finding a �le is a new pro ess that we have not yet dis ussed.14.5 Find a FileTo �nd a �le in Ema s, you use the C-x C-f (find-file) ommand. This ommand is almost, but not quite right for the lengths problem.Let's look at the sour e for find-file (you an use the find-tag om-mand or C-h f (des ribe-fun tion) to �nd the sour e of a fun tion):(defun find-file (filename)"Edit file FILENAME.Swit h to a buffer visiting file FILENAME, reating one if none already exists."(intera tive "FFind file: ")(swit h-to-buffer (find-file-nosele t filename)))The de�nition possesses short but omplete do umentation and an in-tera tive spe i� ation that prompts you for a �le name when you use the ommand intera tively. The body of the de�nition ontains two fun tions,find-file-nosele t and swit h-to-buffer.A ording to its do umentation as shown by C-h f (the des ribe-fun tion ommand), the find-file-nosele t fun tion reads the named�le into a bu�er and returns the bu�er. However, the bu�er is not sele ted.Ema s does not swit h its attention (or yours if you are using find-file-nosele t) to the named bu�er. That is what swit h-to-buffer does: itswit hes the bu�er to whi h Ema s attention is dire ted; and it swit hes thebu�er displayed in the window to the new bu�er. We have dis ussed bu�erswit hing elsewhere. (See Se tion 2.3, \Swit hing Bu�ers", page 26.)In this histogram proje t, we do not need to display ea h �le on thes reen as the program determines the length of ea h de�nition within it.Instead of employing swit h-to-buffer, we an work with set-buffer,whi h redire ts the attention of the omputer program to a di�erent bu�erbut does not redisplay it on the s reen. So instead of alling on find-fileto do the job, we must write our own expression.The task is easy: use find-file-nosele t and set-buffer.

Page 206: An Introduction to Programming in Emacs Lisp

188 Chapter 14: Counting Words in a defun14.6 lengths-list-file in DetailThe ore of the lengths-list-file fun tion is a while loop ontaininga fun tion to move point forward `defun by defun' and a fun tion to ountthe number of words and symbols in ea h defun. This ore must be sur-rounded by fun tions that do various other tasks, in luding �nding the �le,and ensuring that point starts out at the beginning of the �le. The fun tionde�nition looks like this:(defun lengths-list-file (filename)"Return list of definitions' lengths within FILE.The returned list is a list of numbers.Ea h number is the number of words orsymbols in one fun tion definition."(message "Working on `%s' ... " filename)(save-ex ursion(let ((buffer (find-file-nosele t filename))(lengths-list))(set-buffer buffer)(setq buffer-read-only t)(widen)(goto- har (point-min))(while (re-sear h-forward "^(defun" nil t)(setq lengths-list( ons ( ount-words-in-defun) lengths-list)))(kill-buffer buffer)lengths-list)))The fun tion is passed one argument, the name of the �le on whi h it willwork. It has four lines of do umentation, but no intera tive spe i� ation.Sin e people worry that a omputer is broken if they don't see anythinggoing on, the �rst line of the body is a message.The next line ontains a save-ex ursion that returns Ema s' attentionto the urrent bu�er when the fun tion ompletes. This is useful in ase youembed this fun tion in another fun tion that presumes point is restored tothe original bu�er.In the varlist of the let expression, Ema s �nds the �le and binds thelo al variable buffer to the bu�er ontaining the �le. At the same time,Ema s reates lengths-list as a lo al variable.Next, Ema s swit hes its attention to the bu�er.In the following line, Ema s makes the bu�er read-only. Ideally, this lineis not ne essary. None of the fun tions for ounting words and symbols in afun tion de�nition should hange the bu�er. Besides, the bu�er is not goingto be saved, even if it were hanged. This line is entirely the onsequen eof great, perhaps ex essive, aution. The reason for the aution is that thisfun tion and those it alls work on the sour es for Ema s and it is very

Page 207: An Introduction to Programming in Emacs Lisp

lengths-list-file in Detail 189in onvenient if they are inadvertently modi�ed. It goes without saying thatI did not realize a need for this line until an experiment went awry andstarted to modify my Ema s sour e �les . . .Next omes a all to widen the bu�er if it is narrowed. This fun tionis usually not needed|Ema s reates a fresh bu�er if none already exists;but if a bu�er visiting the �le already exists Ema s returns that one. Inthis ase, the bu�er may be narrowed and must be widened. If we wantedto be fully `user-friendly', we would arrange to save the restri tion and thelo ation of point, but we won't.The (goto- har (point-min)) expression moves point to the beginningof the bu�er.Then omes a while loop in whi h the `work' of the fun tion is arried out.In the loop, Ema s determines the length of ea h de�nition and onstru tsa lengths' list ontaining the information.Ema s kills the bu�er after working through it. This is to save spa einside of Ema s. My version of Ema s 19 ontained over 300 sour e �lesof interest; Ema s 21 ontains over 800 sour e �les. Another fun tion willapply lengths-list-file to ea h of the �les.Finally, the last expression within the let expression is the lengths-listvariable; its value is returned as the value of the whole fun tion.You an try this fun tion by installing it in the usual fashion. Then pla eyour ursor after the following expression and type C-x C-e (eval-last-sexp).(lengths-list-file"/usr/lo al/share/ema s/21.0.100/lisp/ema s-lisp/debug.el")(You may need to hange the pathname of the �le; the one here workedwith GNU Ema s version 21.0.100. To hange the expression, opy it to the`*s rat h*' bu�er and edit it.(Also, to see the full length of the list, rather than a trun ated version, youmay have to evaluate the following:( ustom-set-variables '(eval-expression-print-length nil))(See Se tion 16.2, \Setting Variables with def ustom", page 214. Thenevaluate the lengths-list-file expression.)

Page 208: An Introduction to Programming in Emacs Lisp

190 Chapter 14: Counting Words in a defunThe lengths' list for `debug.el' takes less than a se ond to produ e andlooks like this:(77 95 85 87 131 89 50 25 44 44 68 35 64 45 17 34 167 457)(Using my old ma hine, the version 19 lengths' list for `debug.el' tookseven se onds to produ e and looked like this:(75 41 80 62 20 45 44 68 45 12 34 235)(The newer version of `debug.el' ontains more defuns than the earlierone; and my new ma hine is mu h faster than the old one.)Note that the length of the last de�nition in the �le is �rst in the list.14.7 Count Words in defuns in Di�erent FilesIn the previous se tion, we reated a fun tion that returns a list of thelengths of ea h de�nition in a �le. Now, we want to de�ne a fun tion toreturn a master list of the lengths of the de�nitions in a list of �les.Working on ea h of a list of �les is a repetitious a t, so we an use eithera while loop or re ursion.The design using a while loop is routine. The argument passed the fun -tion is a list of �les. As we saw earlier (see Se tion 11.1.1, \Loop Example",page 122), you an write a while loop so that the body of the loop is evalu-ated if su h a list ontains elements, but to exit the loop if the list is empty.For this design to work, the body of the loop must ontain an expressionthat shortens the list ea h time the body is evaluated, so that eventually thelist is empty. The usual te hnique is to set the value of the list to the valueof the dr of the list ea h time the body is evaluated.The template looks like this:(while test-whether-list-is-emptybody...set-list-to- dr-of-list)Also, we remember that a while loop returns nil (the result of evaluat-ing the true-or-false-test), not the result of any evaluation within its body.(The evaluations within the body of the loop are done for their side e�e ts.)However, the expression that sets the lengths' list is part of the body|andthat is the value that we want returned by the fun tion as a whole. To dothis, we en lose the while loop within a let expression, and arrange thatthe last element of the let expression ontains the value of the lengths' list.(See \Loop Example with an In rementing Counter", page 125.)

Page 209: An Introduction to Programming in Emacs Lisp

The append Fun tion 191These onsiderations lead us dire tly to the fun tion itself:;;; Use while loop.(defun lengths-list-many-files (list-of-files)"Return list of lengths of defuns in LIST-OF-FILES."(let (lengths-list);;; true-or-false-test(while list-of-files(setq lengths-list(appendlengths-list;;; Generate a lengths' list.(lengths-list-file(expand-file-name ( ar list-of-files)))));;; Make �les' list shorter.(setq list-of-files ( dr list-of-files)));;; Return �nal value of lengths' list.lengths-list))expand-file-name is a built-in fun tion that onverts a �le name to theabsolute, long, path name form of the dire tory in whi h the fun tion is alled.Thus, if expand-file-name is alled on debug.el when Ema s is visitingthe `/usr/lo al/share/ema s/21.0.100/lisp/ema s-lisp/' dire tory,debug.elbe omes/usr/lo al/share/ema s/21.0.100/lisp/ema s-lisp/debug.elThe only other new element of this fun tion de�nition is the as yet un-studied fun tion append, whi h merits a short se tion for itself.14.7.1 The append Fun tionThe append fun tion atta hes one list to another. Thus,(append '(1 2 3 4) '(5 6 7 8))produ es the list(1 2 3 4 5 6 7 8)This is exa tly how we want to atta h two lengths' lists produ ed bylengths-list-file to ea h other. The results ontrast with ons,( ons '(1 2 3 4) '(5 6 7 8))

Page 210: An Introduction to Programming in Emacs Lisp

192 Chapter 14: Counting Words in a defunwhi h onstru ts a new list in whi h the �rst argument to ons be omes the�rst element of the new list:((1 2 3 4) 5 6 7 8)14.8 Re ursively Count Words in Di�erent FilesBesides a while loop, you an work on ea h of a list of �les with re ursion.A re ursive version of lengths-list-many-files is short and simple.The re ursive fun tion has the usual parts: the `do-again-test', the `next-step-expression', and the re ursive all. The `do-again-test' determineswhether the fun tion should all itself again, whi h it will do if the list-of-files ontains any remaining elements; the `next-step-expression' resetsthe list-of-files to the dr of itself, so eventually the list will be empty;and the re ursive all alls itself on the shorter list. The omplete fun tionis shorter than this des ription!(defun re ursive-lengths-list-many-files (list-of-files)"Return list of lengths of ea h defun in LIST-OF-FILES."(if list-of-files ; do-again-test(append(lengths-list-file(expand-file-name ( ar list-of-files)))(re ursive-lengths-list-many-files( dr list-of-files)))))In a senten e, the fun tion returns the lengths' list for the �rst of the list-of-files appended to the result of alling itself on the rest of the list-of-files.Here is a test of re ursive-lengths-list-many-files, along with theresults of running lengths-list-file on ea h of the �les individually.Install re ursive-lengths-list-many-files and lengths-list-file,if ne essary, and then evaluate the following expressions. You may need to hange the �les' pathnames; those here work when this Info �le and theEma s sour es are lo ated in their ustomary pla es. To hange the expres-sions, opy them to the `*s rat h*' bu�er, edit them, and then evaluatethem.The results are shown after the `)'. (These results are for �les fromEma s Version 21.0.100; �les from other versions of Ema s may produ edi�erent results.)( d "/usr/lo al/share/ema s/21.0.100/")(lengths-list-file "./lisp/ma ros.el")) (273 263 456 90)(lengths-list-file "./lisp/mail/mailalias.el")) (38 32 26 77 174 180 321 198 324)

Page 211: An Introduction to Programming in Emacs Lisp

Sorting Lists 193(lengths-list-file "./lisp/makesum.el")) (85 181)(re ursive-lengths-list-many-files'("./lisp/ma ros.el""./lisp/mail/mailalias.el""./lisp/makesum.el"))) (273 263 456 90 38 32 26 77 174 180 321 198 324 85 181)The re ursive-lengths-list-many-files fun tion produ es the out-put we want.The next step is to prepare the data in the list for display in a graph.14.9 Prepare the Data for Display in a GraphThe re ursive-lengths-list-many-files fun tion returns a list ofnumbers. Ea h number re ords the length of a fun tion de�nition. Whatwe need to do now is transform this data into a list of numbers suitable forgenerating a graph. The new list will tell how many fun tions de�nitions ontain less than 10 words and symbols, how many ontain between 10 and19 words and symbols, how many ontain between 20 and 29 words andsymbols, and so on.In brief, we need to go through the lengths' list produ ed by there ursive-lengths-list-many-files fun tion and ount the number ofdefuns within ea h range of lengths, and produ e a list of those numbers.Based on what we have done before, we an readily foresee that it shouldnot be too hard to write a fun tion that ` drs' down the lengths' list, looksat ea h element, determines whi h length range it is in, and in rements a ounter for that range.However, before beginning to write su h a fun tion, we should onsiderthe advantages of sorting the lengths' list �rst, so the numbers are orderedfrom smallest to largest. First, sorting will make it easier to ount thenumbers in ea h range, sin e two adja ent numbers will either be in thesame length range or in adja ent ranges. Se ond, by inspe ting a sorted list,we an dis over the highest and lowest number, and thereby determine thelargest and smallest length range that we will need.14.9.1 Sorting ListsEma s ontains a fun tion to sort lists, alled (as you might guess) sort.The sort fun tion takes two arguments, the list to be sorted, and a predi atethat determines whether the �rst of two list elements is \less" than these ond.As we saw earlier (see Se tion 1.8.4, \Using the Wrong Type Obje t asan Argument", page 14), a predi ate is a fun tion that determines whether

Page 212: An Introduction to Programming in Emacs Lisp

194 Chapter 14: Counting Words in a defunsome property is true or false. The sort fun tion will reorder a list a ord-ing to whatever property the predi ate uses; this means that sort an beused to sort non-numeri lists by non-numeri riteria|it an, for example,alphabetize a list.The < fun tion is used when sorting a numeri list. For example,(sort '(4 8 21 17 33 7 21 7) '<)produ es this:(4 7 7 8 17 21 21 33)(Note that in this example, both the arguments are quoted so that thesymbols are not evaluated before being passed to sort as arguments.)Sorting the list returned by the re ursive-lengths-list-many-filesfun tion is straightforward; it uses the < fun tion:(sort(re ursive-lengths-list-many-files'("../lisp/ma ros.el""../lisp/mailalias.el""../lisp/makesum.el"))'<whi h produ es:(85 86 116 122 154 176 179 265)(Note that in this example, the �rst argument to sort is not quoted, sin ethe expression must be evaluated so as to produ e the list that is passed tosort.)14.9.2 Making a List of FilesThe re ursive-lengths-list-many-files fun tion requires a list of�les as its argument. For our test examples, we onstru ted su h a list byhand; but the Ema s Lisp sour e dire tory is too large for us to do for that.Instead, we will write a fun tion to do the job for us. In this fun tion, wewill use both a while loop and a re ursive all.We did not have to write a fun tion like this for older versions of GNUEma s, sin e they pla ed all the `.el' �les in one dire tory. Instead, we wereable to use the dire tory-files fun tion, whi h lists the names of �les thatmat h a spe i�ed pattern within a single dire tory.However, re ent versions of Ema s pla e Ema s Lisp �les in sub-dire tories of the top level `lisp' dire tory. This re-arrangement easesnavigation. For example, all the mail related �les are in a `lisp'sub-dire tory alled `mail'. But at the same time, this arrangement for esus to reate a �le listing fun tion that des ends into the sub-dire tories.We an reate this fun tion, alled files-in-below-dire tory, usingfamiliar fun tions su h as ar, nth dr, and substring in onjun tion withan existing fun tion alled dire tory-files-and-attributes. This latter

Page 213: An Introduction to Programming in Emacs Lisp

Making a List of Files 195fun tion not only lists all the �lenames in a dire tory, in luding the namesof sub-dire tories, but also their attributes.To restate our goal: to reate a fun tion that will enable us to feed�lenames to re ursive-lengths-list-many-files as a list that looks likethis (but with more elements):("../lisp/ma ros.el""../lisp/mail/rmail.el""../lisp/makesum.el")The dire tory-files-and-attributes fun tion returns a list of lists.Ea h of the lists within the main list onsists of 13 elements. The �rstelement is a string that ontains the name of the �le { whi h, in GNU/Linux,may be a `dire tory �le', that is to say, a �le with the spe ial attributes ofa dire tory. The se ond element of the list is t for a dire tory, a string forsymboli link (the string is the name linked to), or nil.For example, the �rst `.el' �le in the `lisp/' dire tory is `abbrev.el'.Its name is `/usr/lo al/share/ema s/21.0.100/lisp/abbrev.el' and itis not a dire tory or a symboli link.This is how dire tory-files-and-attributes lists that �le and itsattributes:("/usr/lo al/share/ema s/21.0.100/lisp/abbrev.el"nil11000100(15019 32380)(14883 48041)(15214 49336)11583"-rw-rw-r--"t341385776)On the other hand, `mail/' is a dire tory within the `lisp/' dire tory.The beginning of its listing looks like this:("/usr/lo al/share/ema s/21.0.100/lisp/mail"t...)(Look at the do umentation of file-attributes to learn about the dif-ferent attributes. Bear in mind that the file-attributes fun tion does notlist the �lename, so its �rst element is dire tory-files-and-attributes'sse ond element.)

Page 214: An Introduction to Programming in Emacs Lisp

196 Chapter 14: Counting Words in a defunWe will want our new fun tion, files-in-below-dire tory, to list the`.el' �les in the dire tory it is told to he k, and in any dire tories belowthat dire tory.This gives us a hint on how to onstru t files-in-below-dire tory:within a dire tory, the fun tion should add `.el' �lenames to a list; and if,within a dire tory, the fun tion omes upon a sub-dire tory, it should gointo that sub-dire tory and repeat its a tions.However, we should note that every dire tory ontains a name that refersto itself, alled `.', (\dot") and a name that refers to its parent dire tory, alled `..' (\double dot"). (In `/', the root dire tory, `..' refers to itself,sin e `/' has no parent.) Clearly, we do not want our files-in-below-dire tory fun tion to enter those dire tories, sin e they always lead us,dire tly or indire tly, to the urrent dire tory.Consequently, our files-in-below-dire tory fun tion must do severaltasks:� Che k to see whether it is looking at a �lename that ends in `.el'; andif so, add its name to a list.� Che k to see whether it is looking at a �lename that is the name of adire tory; and if so,� Che k to see whether it is looking at `.' or `..'; and if so skip it.� Or else, go into that dire tory and repeat the pro ess.Let's write a fun tion de�nition to do these tasks. We will use a whileloop to move from one �lename to another within a dire tory, he king whatneeds to be done; and we will use a re ursive all to repeat the a tions onea h sub-dire tory. The re ursive pattern is `a umulate' (see \Re ursivePattern: a umulate", page 142), using append as the ombiner.Here is the fun tion:(defun files-in-below-dire tory (dire tory)"List the .el files in DIRECTORY and in its sub-dire tories.";; Although the fun tion will be used non-intera tively,;; it will be easier to test if we make it intera tive.;; The dire tory will have a name su h as;; "/usr/lo al/share/ema s/21.0.100/lisp/"(intera tive "DDire tory name: ")(let (el-files-list( urrent-dire tory-list(dire tory-files-and-attributes dire tory t)));; while we are in the urrent dire tory(while urrent-dire tory-list

Page 215: An Introduction to Programming in Emacs Lisp

Counting fun tion de�nitions 197( ond;; he k to see whether filename ends in `.el';; and if so, append its name to a list.((equal ".el" (substring ( ar ( ar urrent-dire tory-list)) -3))(setq el-files-list( ons ( ar ( ar urrent-dire tory-list)) el-files-list)));; he k whether filename is that of a dire tory((eq t ( ar ( dr ( ar urrent-dire tory-list))));; de ide whether to skip or re urse(if (equal (or "." "..")(substring ( ar ( ar urrent-dire tory-list)) -1));; then do nothing if filename is that of;; urrent dire tory or parent();; else des end into the dire tory and repeat the pro ess(setq el-files-list(append(files-in-below-dire tory( ar ( ar urrent-dire tory-list)))el-files-list)))));; move to the next filename in the list; this also;; shortens the list so the while loop eventually omes to an end(setq urrent-dire tory-list ( dr urrent-dire tory-list)));; return the filenamesel-files-list))The files-in-below-dire tory dire tory-files fun tion takes oneargument, the name of a dire tory.Thus, on my system,(length(files-in-below-dire tory "/usr/lo al/share/ema s/21.0.100/lisp/"))tells me that my version 21.0.100 Lisp sour es dire tory ontains 754 `.el'�les.files-in-below-dire tory returns a list in reverse alphabeti al order.An expression to sort the list in alphabeti al order looks like this:(sort(files-in-below-dire tory "/usr/lo al/share/ema s/21.0.100/lisp/")'string-lessp)14.9.3 Counting fun tion de�nitionsOur immediate goal is to generate a list that tells us how many fun tionde�nitions ontain fewer than 10 words and symbols, how many ontain

Page 216: An Introduction to Programming in Emacs Lisp

198 Chapter 14: Counting Words in a defunbetween 10 and 19 words and symbols, how many ontain between 20 and29 words and symbols, and so on.With a sorted list of numbers, this is easy: ount how many elementsof the list are smaller than 10, then, after moving past the numbers just ounted, ount how many are smaller than 20, then, after moving past thenumbers just ounted, ount how many are smaller than 30, and so on. Ea hof the numbers, 10, 20, 30, 40, and the like, is one larger than the top ofthat range. We an all the list of su h numbers the top-of-ranges list.If we wished, we ould generate this list automati ally, but it is simplerto write a list manually. Here it is:(defvar top-of-ranges'(10 20 30 40 5060 70 80 90 100110 120 130 140 150160 170 180 190 200210 220 230 240 250260 270 280 290 300)"List spe ifying ranges for `defuns-per-range'.")To hange the ranges, we edit this list.Next, we need to write the fun tion that reates the list of the number ofde�nitions within ea h range. Clearly, this fun tion must take the sorted-lengths and the top-of-ranges lists as arguments.The defuns-per-range fun tion must do two things again and again: itmust ount the number of de�nitions within a range spe i�ed by the urrenttop-of-range value; and it must shift to the next higher value in the top-of-ranges list after ounting the number of de�nitions in the urrent range.Sin e ea h of these a tions is repetitive, we an use while loops for the job.One loop ounts the number of de�nitions in the range de�ned by the urrenttop-of-range value, and the other loop sele ts ea h of the top-of-range valuesin turn.Several entries of the sorted-lengths list are ounted for ea h range;this means that the loop for the sorted-lengths list will be inside the loopfor the top-of-ranges list, like a small gear inside a big gear.The inner loop ounts the number of de�nitions within the range. It is asimple ounting loop of the type we have seen before. (See Se tion 11.1.3, \Aloop with an in rementing ounter", page 124.) The true-or-false test of theloop tests whether the value from the sorted-lengths list is smaller thanthe urrent value of the top of the range. If it is, the fun tion in rementsthe ounter and tests the next value from the sorted-lengths list.

Page 217: An Introduction to Programming in Emacs Lisp

Counting fun tion de�nitions 199The inner loop looks like this:(while length-element-smaller-than-top-of-range(setq number-within-range (1+ number-within-range))(setq sorted-lengths ( dr sorted-lengths)))The outer loop must start with the lowest value of the top-of-rangeslist, and then be set to ea h of the su eeding higher values in turn. This an be done with a loop like this:(while top-of-rangesbody-of-loop...(setq top-of-ranges ( dr top-of-ranges)))Put together, the two loops look like this:(while top-of-ranges;; Count the number of elements within the urrent range.(while length-element-smaller-than-top-of-range(setq number-within-range (1+ number-within-range))(setq sorted-lengths ( dr sorted-lengths)));; Move to next range.(setq top-of-ranges ( dr top-of-ranges)))In addition, in ea h ir uit of the outer loop, Ema s should re ord thenumber of de�nitions within that range (the value of number-within-range)in a list. We an use ons for this purpose. (See Se tion 7.2, \ ons",page 83.)The ons fun tion works �ne, ex ept that the list it onstru ts will on-tain the number of de�nitions for the highest range at its beginning and thenumber of de�nitions for the lowest range at its end. This is be ause onsatta hes new elements of the list to the beginning of the list, and sin e thetwo loops are working their way through the lengths' list from the lower end�rst, the defuns-per-range-list will end up largest number �rst. But wewill want to print our graph with smallest values �rst and the larger later.The solution is to reverse the order of the defuns-per-range-list. We ando this using the nreverse fun tion, whi h reverses the order of a list.For example,(nreverse '(1 2 3 4))produ es:(4 3 2 1)Note that the nreverse fun tion is \destru tive"|that is, it hangesthe list to whi h it is applied; this ontrasts with the ar and dr fun tions,whi h are non-destru tive. In this ase, we do not want the original defuns-per-range-list, so it does not matter that it is destroyed. (The reversefun tion provides a reversed opy of a list, leaving the original list as is.)

Page 218: An Introduction to Programming in Emacs Lisp

200 Chapter 14: Counting Words in a defunPut all together, the defuns-per-range looks like this:(defun defuns-per-range (sorted-lengths top-of-ranges)"SORTED-LENGTHS defuns in ea h TOP-OF-RANGES range."(let ((top-of-range ( ar top-of-ranges))(number-within-range 0)defuns-per-range-list);; Outer loop.(while top-of-ranges;; Inner loop.(while (and;; Need number for numeri test.( ar sorted-lengths)(< ( ar sorted-lengths) top-of-range));; Count number of de�nitions within urrent range.(setq number-within-range (1+ number-within-range))(setq sorted-lengths ( dr sorted-lengths)));; Exit inner loop but remain within outer loop.(setq defuns-per-range-list( ons number-within-range defuns-per-range-list))(setq number-within-range 0) ; Reset ount to zero.;; Move to next range.(setq top-of-ranges ( dr top-of-ranges));; Spe ify next top of range value.(setq top-of-range ( ar top-of-ranges)));; Exit outer loop and ount the number of defuns larger than;; the largest top-of-range value.(setq defuns-per-range-list( ons(length sorted-lengths)defuns-per-range-list));; Return a list of the number of de�nitions within ea h range,;; smallest to largest.(nreverse defuns-per-range-list)))

Page 219: An Introduction to Programming in Emacs Lisp

Counting fun tion de�nitions 201The fun tion is straightforward ex ept for one subtle feature. The true-or-false test of the inner loop looks like this:(and ( ar sorted-lengths)(< ( ar sorted-lengths) top-of-range))instead of like this:(< ( ar sorted-lengths) top-of-range)The purpose of the test is to determine whether the �rst item in thesorted-lengths list is less than the value of the top of the range.The simple version of the test works �ne unless the sorted-lengthslist has a nil value. In that ase, the ( ar sorted-lengths) expressionfun tion returns nil. The < fun tion annot ompare a number to nil,whi h is an empty list, so Ema s signals an error and stops the fun tionfrom attempting to ontinue to exe ute.The sorted-lengths list always be omes nil when the ounter rea hesthe end of the list. This means that any attempt to use the defuns-per-range fun tion with the simple version of the test will fail.We solve the problem by using the ( ar sorted-lengths) expression in onjun tion with the and expression. The ( ar sorted-lengths) expres-sion returns a non-nil value so long as the list has at least one number withinit, but returns nil if the list is empty. The and expression �rst evaluatesthe ( ar sorted-lengths) expression, and if it is nil, returns false withoutevaluating the < expression. But if the ( ar sorted-lengths) expressionreturns a non-nil value, the and expression evaluates the < expression, andreturns that value as the value of the and expression.This way, we avoid an error. See Se tion 12.4, \forward-paragraph: aGoldmine of Fun tions", page 155, for more information about and.Here is a short test of the defuns-per-range fun tion. First, evaluatethe expression that binds (a shortened) top-of-ranges list to the list ofvalues, then evaluate the expression for binding the sorted-lengths list,and then evaluate the defuns-per-range fun tion.;; (Shorter list than we will use later.)(setq top-of-ranges'(110 120 130 140 150160 170 180 190 200))(setq sorted-lengths'(85 86 110 116 122 129 154 176 179 200 265 300 300))(defuns-per-range sorted-lengths top-of-ranges)

Page 220: An Introduction to Programming in Emacs Lisp

202 Chapter 14: Counting Words in a defunThe list returned looks like this:(2 2 2 0 0 1 0 2 0 0 4)Indeed, there are two elements of the sorted-lengths list smaller than 110,two elements between 110 and 119, two elements between 120 and 129, andso on. There are four elements with a value of 200 or larger.

Page 221: An Introduction to Programming in Emacs Lisp

Readying a Graph 20315 Readying a GraphOur goal is to onstru t a graph showing the numbers of fun tion de�ni-tions of various lengths in the Ema s lisp sour es.As a pra ti al matter, if you were reating a graph, you would probablyuse a program su h as gnuplot to do the job. (gnuplot is ni ely integratedinto GNU Ema s.) In this ase, however, we reate one from s rat h, andin the pro ess we will re-a quaint ourselves with some of what we learnedbefore and learn more.In this hapter, we will �rst write a simple graph printing fun tion. This�rst de�nition will be a prototype, a rapidly written fun tion that enablesus to re onnoiter this unknown graph-making territory. We will dis overdragons, or �nd that they are myth. After s outing the terrain, we will feelmore on�dent and enhan e the fun tion to label the axes automati ally.Sin e Ema s is designed to be exible and work with all kinds of terminals,in luding hara ter-only terminals, the graph will need to be made from oneof the `typewriter' symbols. An asterisk will do; as we enhan e the graph-printing fun tion, we an make the hoi e of symbol a user option.We an all this fun tion graph-body-print; it will take a numbers-listas its only argument. At this stage, we will not label the graph, but onlyprint its body.The graph-body-print fun tion inserts a verti al olumn of asterisks forea h element in the numbers-list. The height of ea h line is determined bythe value of that element of the numbers-list.Inserting olumns is a repetitive a t; that means that this fun tion anbe written either with a while loop or re ursively.Our �rst hallenge is to dis over how to print a olumn of asterisks.Usually, in Ema s, we print hara ters onto a s reen horizontally, line byline, by typing. We have two routes we an follow: write our own olumn-insertion fun tion or dis over whether one exists in Ema s.To see whether there is one in Ema s, we an use the M-x apropos om-mand. This ommand is like the C-h a ( ommand-apropos) ommand, ex- ept that the latter �nds only those fun tions that are ommands. TheM-x apropos ommand lists all symbols that mat h a regular expression,in luding fun tions that are not intera tive.What we want to look for is some ommand that prints or inserts olumns.Very likely, the name of the fun tion will ontain either the word `print' orthe word `insert' or the word ` olumn'. Therefore, we an simply type M-xapropos RET print\|insert\| olumn RET and look at the result. On mysystem, this ommand takes quite some time, and then produ es a list of79 fun tions and variables. S anning down the list, the only fun tion thatlooks as if it might do the job is insert-re tangle.

Page 222: An Introduction to Programming in Emacs Lisp

204 Chapter 15: Readying a GraphIndeed, this is the fun tion we want; its do umentation says:insert-re tangle:Insert text of RECTANGLE with upper left orner at point.RECTANGLE's first line is inserted at point,its se ond line is inserted at a point verti ally under point, et .RECTANGLE should be a list of strings.We an run a qui k test, to make sure it does what we expe t of it.Here is the result of pla ing the ursor after the insert-re tangle ex-pression and typing C-u C-x C-e (eval-last-sexp). The fun tion insertsthe strings `"first"', `"se ond"', and `"third"' at and below point. Alsothe fun tion returns nil.(insert-re tangle '("first" "se ond" "third"))firstse ondthirdnilOf ourse, we won't be inserting the text of the insert-re tangle expres-sion itself into the bu�er in whi h we are making the graph, but will allthe fun tion from our program. We shall, however, have to make sure thatpoint is in the bu�er at the pla e where the insert-re tangle fun tion willinsert its olumn of strings.If you are reading this in Info, you an see how this works by swit hingto another bu�er, su h as the `*s rat h*' bu�er, pla ing point somewherein the bu�er, typing M-:, typing the insert-re tangle expression into theminibu�er at the prompt, and then typing hRETi. This auses Ema s toevaluate the expression in the minibu�er, but to use as the value of pointthe position of point in the `*s rat h*' bu�er. (M-: is the keybinding foreval-expression.)We �nd when we do this that point ends up at the end of the last insertedline|that is to say, this fun tion moves point as a side-e�e t. If we were torepeat the ommand, with point at this position, the next insertion wouldbe below and to the right of the previous insertion. We don't want this! Ifwe are going to make a bar graph, the olumns need to be beside ea h other.So we dis over that ea h y le of the olumn-inserting while loop mustreposition point to the pla e we want it, and that pla e will be at the top,not the bottom, of the olumn. Moreover, we remember that when we printa graph, we do not expe t all the olumns to be the same height. This meansthat the top of ea h olumn may be at a di�erent height from the previousone. We annot simply reposition point to the same line ea h time, butmoved over to the right|or perhaps we an. . .We are planning to make the olumns of the bar graph out of asterisks.The number of asterisks in the olumn is the number spe i�ed by the urrentelement of the numbers-list. We need to onstru t a list of asterisks of theright length for ea h all to insert-re tangle. If this list onsists solely ofthe requisite number of asterisks, then we will have position point the right

Page 223: An Introduction to Programming in Emacs Lisp

Readying a Graph 205number of lines above the base for the graph to print orre tly. This ouldbe diÆ ult.Alternatively, if we an �gure out some way to pass insert-re tanglea list of the same length ea h time, then we an pla e point on the same lineea h time, but move it over one olumn to the right for ea h new olumn.If we do this, however, some of the entries in the list passed to insert-re tangle must be blanks rather than asterisks. For example, if the max-imum height of the graph is 5, but the height of the olumn is 3, theninsert-re tangle requires an argument that looks like this:(" " " " "*" "*" "*")This last proposal is not so diÆ ult, so long as we an determine the olumn height. There are two ways for us to spe ify the olumn height:we an arbitrarily state what it will be, whi h would work �ne for graphsof that height; or we an sear h through the list of numbers and use themaximum height of the list as the maximum height of the graph. If thelatter operation were diÆ ult, then the former pro edure would be easiest,but there is a fun tion built into Ema s that determines the maximum ofits arguments. We an use that fun tion. The fun tion is alled max and itreturns the largest of all its arguments, whi h must be numbers. Thus, forexample,(max 3 4 6 5 7 3)returns 7. (A orresponding fun tion alled min returns the smallest of allits arguments.)However, we annot simply all max on the numbers-list; the max fun -tion expe ts numbers as its argument, not a list of numbers. Thus, thefollowing expression,(max '(3 4 6 5 7 3))produ es the following error message;Wrong type of argument: number-or-marker-p, (3 4 6 5 7 3)We need a fun tion that passes a list of arguments to a fun tion. Thisfun tion is apply. This fun tion `applies' its �rst argument (a fun tion) toits remaining arguments, the last of whi h may be a list.For example,(apply 'max 3 4 7 3 '(4 8 5))returns 8.(In identally, I don't know how you would learn of this fun tion withouta book su h as this. It is possible to dis over other fun tions, like sear h-forward or insert-re tangle, by guessing at a part of their names andthen using apropos. Even though its base in metaphor is lear|`apply'its �rst argument to the rest|I doubt a novi e would ome up with thatparti ular word when using apropos or other aid. Of ourse, I ould bewrong; after all, the fun tion was �rst named by someone who had to inventit.)

Page 224: An Introduction to Programming in Emacs Lisp

206 Chapter 15: Readying a GraphThe se ond and subsequent arguments to apply are optional, so we anuse apply to all a fun tion and pass the elements of a list to it, like this,whi h also returns 8:(apply 'max '(4 8 5))This latter way is how we will use apply. The re ursive-lengths-list-many-files fun tion returns a numbers' list to whi h we an applymax (we ould also apply max to the sorted numbers' list; it does not matterwhether the list is sorted or not.)Hen e, the operation for �nding the maximum height of the graph is this:(setq max-graph-height (apply 'max numbers-list))Now we an return to the question of how to reate a list of strings for a olumn of the graph. Told the maximum height of the graph and the numberof asterisks that should appear in the olumn, the fun tion should return alist of strings for the insert-re tangle ommand to insert.Ea h olumn is made up of asterisks or blanks. Sin e the fun tion ispassed the value of the height of the olumn and the number of asterisks inthe olumn, the number of blanks an be found by subtra ting the numberof asterisks from the height of the olumn. Given the number of blanks andthe number of asterisks, two while loops an be used to onstru t the list:;;; First version.(defun olumn-of-graph (max-graph-height a tual-height)"Return list of strings that is one olumn of a graph."(let ((insert-list nil)(number-of-top-blanks(- max-graph-height a tual-height)));; Fill in asterisks.(while (> a tual-height 0)(setq insert-list ( ons "*" insert-list))(setq a tual-height (1- a tual-height)));; Fill in blanks.(while (> number-of-top-blanks 0)(setq insert-list ( ons " " insert-list))(setq number-of-top-blanks(1- number-of-top-blanks)));; Return whole list.insert-list))If you install this fun tion and then evaluate the following expression youwill see that it returns the list as desired:( olumn-of-graph 5 3)

Page 225: An Introduction to Programming in Emacs Lisp

Readying a Graph 207returns(" " " " "*" "*" "*")As written, olumn-of-graph ontains a major aw: the symbols usedfor the blank and for the marked entries in the olumn are `hard- oded' asa spa e and asterisk. This is �ne for a prototype, but you, or another user,may wish to use other symbols. For example, in testing the graph fun tion,you many want to use a period in pla e of the spa e, to make sure the pointis being repositioned properly ea h time the insert-re tangle fun tion is alled; or you might want to substitute a `+' sign or other symbol for theasterisk. You might even want to make a graph- olumn that is more thanone display olumn wide. The program should be more exible. The way todo that is to repla e the blank and the asterisk with two variables that we an all graph-blank and graph-symbol and de�ne those variables separately.Also, the do umentation is not well written. These onsiderations leadus to the se ond version of the fun tion:(defvar graph-symbol "*""String used as symbol in graph, usually an asterisk.")(defvar graph-blank " ""String used as blank in graph, usually a blank spa e.graph-blank must be the same number of olumns wideas graph-symbol.")(For an explanation of defvar, see Se tion 8.4, \Initializing a Variable withdefvar", page 100.);;; Se ond version.(defun olumn-of-graph (max-graph-height a tual-height)"Return MAX-GRAPH-HEIGHT strings; ACTUAL-HEIGHT are graph-symbols.The graph-symbols are ontiguous entries at the endof the list.The list will be inserted as one olumn of a graph.The strings are either graph-blank or graph-symbol."(let ((insert-list nil)(number-of-top-blanks(- max-graph-height a tual-height)));; Fill in graph-symbols.(while (> a tual-height 0)(setq insert-list ( ons graph-symbol insert-list))(setq a tual-height (1- a tual-height)))

Page 226: An Introduction to Programming in Emacs Lisp

208 Chapter 15: Readying a Graph;; Fill in graph-blanks.(while (> number-of-top-blanks 0)(setq insert-list ( ons graph-blank insert-list))(setq number-of-top-blanks(1- number-of-top-blanks)));; Return whole list.insert-list))If we wished, we ould rewrite olumn-of-graph a third time to provideoptionally for a line graph as well as for a bar graph. This would not behard to do. One way to think of a line graph is that it is no more than abar graph in whi h the part of ea h bar that is below the top is blank. To onstru t a olumn for a line graph, the fun tion �rst onstru ts a list ofblanks that is one shorter than the value, then it uses ons to atta h a graphsymbol to the list; then it uses ons again to atta h the `top blanks' to thelist.It is easy to see how to write su h a fun tion, but sin e we don't need it,we will not do it. But the job ould be done, and if it were done, it wouldbe done with olumn-of-graph. Even more important, it is worth notingthat few hanges would have to be made anywhere else. The enhan ement,if we ever wish to make it, is simple.Now, �nally, we ome to our �rst a tual graph printing fun tion. Thisprints the body of a graph, not the labels for the verti al and horizontalaxes, so we an all this graph-body-print.15.1 The graph-body-print Fun tionAfter our preparation in the pre eding se tion, the graph-body-printfun tion is straightforward. The fun tion will print olumn after olumn ofasterisks and blanks, using the elements of a numbers' list to spe ify thenumber of asterisks in ea h olumn. This is a repetitive a t, whi h meanswe an use a de rementing while loop or re ursive fun tion for the job. Inthis se tion, we will write the de�nition using a while loop.The olumn-of-graph fun tion requires the height of the graph as anargument, so we should determine and re ord that as a lo al variable.This leads us to the following template for the while loop version of thisfun tion:(defun graph-body-print (numbers-list)"do umentation..."(let ((height ......))(while numbers-listinsert- olumns-and-reposition-point(setq numbers-list ( dr numbers-list)))))

Page 227: An Introduction to Programming in Emacs Lisp

The graph-body-print Fun tion 209We need to �ll in the slots of the template.Clearly, we an use the (apply 'max numbers-list) expression to deter-mine the height of the graph.The while loop will y le through the numbers-list one element at atime. As it is shortened by the (setq numbers-list ( dr numbers-list))expression, the ar of ea h instan e of the list is the value of the argumentfor olumn-of-graph.At ea h y le of the while loop, the insert-re tangle fun tion insertsthe list returned by olumn-of-graph. Sin e the insert-re tangle fun -tion moves point to the lower right of the inserted re tangle, we need to savethe lo ation of point at the time the re tangle is inserted, move ba k to thatposition after the re tangle is inserted, and then move horizontally to thenext pla e from whi h insert-re tangle is alled.If the inserted olumns are one hara ter wide, as they will be if sin-gle blanks and asterisks are used, the repositioning ommand is simply(forward- har 1); however, the width of a olumn may be greater than one.This means that the repositioning ommand should be written (forward- har symbol-width). The symbol-width itself is the length of a graph-blank and an be found using the expression (length graph-blank). Thebest pla e to bind the symbol-width variable to the value of the width ofgraph olumn is in the varlist of the let expression.These onsiderations lead to the following fun tion de�nition:(defun graph-body-print (numbers-list)"Print a bar graph of the NUMBERS-LIST.The numbers-list onsists of the Y-axis values."(let ((height (apply 'max numbers-list))(symbol-width (length graph-blank))from-position)(while numbers-list(setq from-position (point))(insert-re tangle( olumn-of-graph height ( ar numbers-list)))(goto- har from-position)(forward- har symbol-width);; Draw graph olumn by olumn.(sit-for 0)(setq numbers-list ( dr numbers-list)));; Pla e point for X axis labels.(forward-line height)(insert "\n")))

Page 228: An Introduction to Programming in Emacs Lisp

210 Chapter 15: Readying a GraphThe one unexpe ted expression in this fun tion is the (sit-for 0) expres-sion in the while loop. This expression makes the graph printing operationmore interesting to wat h than it would be otherwise. The expression ausesEma s to `sit' or do nothing for a zero length of time and then redraw thes reen. Pla ed here, it auses Ema s to redraw the s reen olumn by olumn.Without it, Ema s would not redraw the s reen until the fun tion exits.We an test graph-body-print with a short list of numbers.1. Install graph-symbol, graph-blank, olumn-of-graph, whi h are inChapter 15, \Readying a Graph", page 203, and graph-body-print.2. Copy the following expression:(graph-body-print '(1 2 3 4 6 4 3 5 7 6 5 2 3))3. Swit h to the `*s rat h*' bu�er and pla e the ursor where you wantthe graph to start.4. Type M-: (eval-expression).5. Yank the graph-body-print expression into the minibu�er with C-y(yank).6. Press hRETi to evaluate the graph-body-print expression.Ema s will print a graph like this:** *** ******* ************* **************************15.2 The re ursive-graph-body-print Fun tionThe graph-body-print fun tion may also be written re ursively. There ursive solution is divided into two parts: an outside `wrapper' that usesa let expression to determine the values of several variables that need onlybe found on e, su h as the maximum height of the graph, and an insidefun tion that is alled re ursively to print the graph.

Page 229: An Introduction to Programming in Emacs Lisp

Need for Printed Axes 211The `wrapper' is un ompli ated:(defun re ursive-graph-body-print (numbers-list)"Print a bar graph of the NUMBERS-LIST.The numbers-list onsists of the Y-axis values."(let ((height (apply 'max numbers-list))(symbol-width (length graph-blank))from-position)(re ursive-graph-body-print-internalnumbers-listheightsymbol-width)))The re ursive fun tion is a little more diÆ ult. It has four parts: the`do-again-test', the printing ode, the re ursive all, and the `next-step-expression'. The `do-again-test' is an if expression that determines whetherthe numbers-list ontains any remaining elements; if it does, the fun -tion prints one olumn of the graph using the printing ode and alls itselfagain. The fun tion alls itself again a ording to the value produ ed by the`next-step-expression' whi h auses the all to a t on a shorter version of thenumbers-list.(defun re ursive-graph-body-print-internal(numbers-list height symbol-width)"Print a bar graph.Used within re ursive-graph-body-print fun tion."(if numbers-list(progn(setq from-position (point))(insert-re tangle( olumn-of-graph height ( ar numbers-list)))(goto- har from-position)(forward- har symbol-width)(sit-for 0) ; Draw graph olumn by olumn.(re ursive-graph-body-print-internal( dr numbers-list) height symbol-width))))After installation, this expression an be tested; here is a sample:(re ursive-graph-body-print '(3 2 5 6 7 5 3 4 6 4 3 2 1))Here is what re ursive-graph-body-print produ es:*** ***** ***** **** **********************************

Page 230: An Introduction to Programming in Emacs Lisp

212 Chapter 15: Readying a GraphEither of these two fun tions, graph-body-print or re ursive-graph-body-print, reate the body of a graph.15.3 Need for Printed AxesA graph needs printed axes, so you an orient yourself. For a do-on eproje t, it may be reasonable to draw the axes by hand using Ema s' Pi turemode; but a graph drawing fun tion may be used more than on e.For this reason, I have written enhan ements to the basi print-graph-body fun tion that automati ally print labels for the horizontal and verti alaxes. Sin e the label printing fun tions do not ontain mu h new material,I have pla ed their des ription in an appendix. See Appendix C, \A Graphwith Labelled Axes", page 255.15.4 Exer iseWrite a line graph version of the graph printing fun tions.

Page 231: An Introduction to Programming in Emacs Lisp

Site-wide Initialization Files 21316 Your `.ema s' File\You don't have to like Ema s to like it" { this seemingly paradoxi alstatement is the se ret of GNU Ema s. The plain, `out of the box' Ema s isa generi tool. Most people who use it, ustomize it to suit themselves.GNU Ema s is mostly written in Ema s Lisp; this means that by writingexpressions in Ema s Lisp you an hange or extend Ema s.There are those who appre iate Ema s' default on�guration. After all,Ema s starts you in C mode when you edit a C �le, starts you in Fortranmode when you edit a Fortran �le, and starts you in Fundamental modewhen you edit an unadorned �le. This all makes sense, if you do not knowwho is going to use Ema s. Who knows what a person hopes to do with anunadorned �le? Fundamental mode is the right default for su h a �le, justas C mode is the right default for editing C ode. But when you do knowwho is going to use Ema s|you, yourself|then it makes sense to ustomizeEma s.For example, I seldom want Fundamental mode when I edit an otherwiseundistinguished �le; I want Text mode. This is why I ustomize Ema s: soit suits me.You an ustomize and extend Ema s by writing or adapting a `~/.ema s'�le. This is your personal initialization �le; its ontents, written in Ema sLisp, tell Ema s what to do.1A `~/.ema s' �le ontains Ema s Lisp ode. You an write this odeyourself; or you an use Ema s' ustomize feature to write the ode foryou. You an ombine your own expressions and auto-written Customizeexpressions in your `.ema s' �le.(I myself prefer to write my own expressions, ex ept for those, parti ularlyfonts, that I �nd easier to manipulate using the ustomize ommand. I ombine the two methods.)Most of this hapter is about writing expressions yourself. It des ribesa simple `.ema s' �le; for more information, see se tion \The Init File" inThe GNU Ema s Manual, and se tion \The Init File" in The GNU Ema sLisp Referen e Manual.16.1 Site-wide Initialization FilesIn addition to your personal initialization �le, Ema s automati ally loadsvarious site-wide initialization �les, if they exist. These have the same formas your `.ema s' �le, but are loaded by everyone.1 You may also add `.el' to `~/.ema s' and all it a `~/.ema s.el' �le. In the past,you were forbidden to type the extra keystrokes that the name `~/.ema s.el' requires,but now you may. The new format is onsistent with the Ema s Lisp �le naming onventions; the old format saves typing.

Page 232: An Introduction to Programming in Emacs Lisp

214 Chapter 16: Your `.ema s' FileTwo site-wide initialization �les, `site-load.el' and `site-init.el',are loaded into Ema s and then `dumped' if a `dumped' version of Ema s is reated, as is most ommon. (Dumped opies of Ema s load more qui kly.However, on e a �le is loaded and dumped, a hange to it does not leadto a hange in Ema s unless you load it yourself or re-dump Ema s. Seese tion \Building Ema s" in The GNU Ema s Lisp Referen e Manual, andthe `INSTALL' �le.)Three other site-wide initialization �les are loaded automati ally ea htime you start Ema s, if they exist. These are `site-start.el', whi h isloaded before your `.ema s' �le, and `default.el', and the terminal type�le, whi h are both loaded after your `.ema s' �le.Settings and de�nitions in your `.ema s' �le will overwrite on i tingsettings and de�nitions in a `site-start.el' �le, if it exists; but the settingsand de�nitions in a `default.el' or terminal type �le will overwrite those inyour `.ema s' �le. (You an prevent interferen e from a terminal type �le bysetting term-file-prefix to nil. See Se tion 16.11, \A Simple Extension",page 224.)The `INSTALL' �le that omes in the distribution ontains des riptions ofthe `site-init.el' and `site-load.el' �les.The `loadup.el', `startup.el', and `loaddefs.el' �les ontrol loading.These �les are in the `lisp' dire tory of the Ema s distribution and areworth perusing.The `loaddefs.el' �le ontains a good many suggestions as to what toput into your own `.ema s' �le, or into a site-wide initialization �le.16.2 Spe ifying Variables using def ustomYou an spe ify variables using def ustom so that you and others anthen an use Ema s' ustomize feature to set their values. (You annot use ustomize to write fun tion de�nitions; but you an write defuns in your`.ema s' �le. Indeed, you an write any Lisp expression in your `.ema s'�le.)The ustomize feature depends on the def ustom spe ial form. Al-though you an use defvar or setq for variables that users set, thedef ustom spe ial form is designed for the job.You an use your knowledge of defvar for writing the �rst three argu-ments for def ustom. The �rst argument to def ustom is the name of thevariable. The se ond argument is the variable's initial value, if any; and thisvalue is set only if the value has not already been set. The third argumentis the do umentation.The fourth and subsequent arguments to def ustom spe ify types andoptions; these are not featured in defvar. (These arguments are optional.)Ea h of these arguments onsists of a keyword followed by a value. Ea hkeyword starts with the hara ter :.

Page 233: An Introduction to Programming in Emacs Lisp

Spe ifying Variables using def ustom 215For example, the ustomizable user option variable text-mode-hooklooks like this:(def ustom text-mode-hook nil"Normal hook run when entering Text mode and many related modes.":type 'hook:options '(turn-on-auto-fill flyspell-mode):group 'data)The name of the variable is text-mode-hook; it has no default value; andits do umentation string tells you what it does.The :type keyword tells Ema s what kind of data text-mode-hookshould be set to and how to display the value in a Customization bu�er.The :options keyword spe i�es a suggested list of values for the vari-able. Currently, you an use :options only for a hook. The list is only asuggestion; it is not ex lusive; a person who sets the variable may set it toother values; the list shown following the :options keyword is intended too�er onvenient hoi es to a user.Finally, the :group keyword tells the Ema s Customization ommand inwhi h group the variable is lo ated. This tells where to �nd it.For more information, see se tion \Writing Customization De�nitions"in The GNU Ema s Lisp Referen e Manual.Consider text-mode-hook as an example.There are two ways to ustomize this variable. You an use the us-tomization ommand or write the appropriate expressions yourself.Using the ustomization ommand, you an type:M-x ustomizeand �nd that the group for editing �les of data is alled `data'. Enter thatgroup. Text Mode Hook is the �rst member. You an li k on its variousoptions to set the values. After you li k on the button toSave for Future SessionsEma s will write an expression into your `.ema s' �le. It will look like this:( ustom-set-variables;; ustom-set-variables was added by Custom --;; don't edit or ut/paste it!;; Your init file should ontain only one su h instan e.'(text-mode-hook (quote (turn-on-auto-fill text-mode-hook-identify))))(The text-mode-hook-identify fun tion tells toggle-text-mode-auto-fill whi h bu�ers are in Text mode.)In spite of the warning, you ertainly may edit, ut, and paste the ex-pression! I do all time. The purpose of the warning is to s are those whodo not know what they are doing, so they do not inadvertently generate anerror.

Page 234: An Introduction to Programming in Emacs Lisp

216 Chapter 16: Your `.ema s' FileThe ustom-set-variables works somewhat di�erently than a setq.While I have never learned the di�eren es, I do modify the ustom-set-variables expressions in my `.ema s' �le by hand: I make the hangesin what appears to me to be a reasonable manner and have not had anyproblems. Others prefer to use the Customization ommand and let Ema sdo the work for them.Another ustom-set-... fun tion is ustom-set-fa es. This fun tionsets the various font fa es. Over time, I have set a onsiderable numberof fa es. Some of the time, I re-set them using ustomize; other times, Isimply edit the ustom-set-fa es expression in my `.ema s' �le itself.The se ond way to ustomize your text-mode-hook is to set it yourselfin your `.ema s' �le using ode that has nothing to do with the ustom-set-... fun tions.When you do this, and later use ustomize, you will see a message thatsays this option has been hanged outside the ustomize buffer.This message is only a warning. If you li k on the button toSave for Future SessionsEma s will write a ustom-set-... expression near the end of your `.ema s'�le that will be evaluated after your hand-written expression. It will, there-fore, overrule your hand-written expression. No harm will be done. Whenyou do this, however, be areful to remember whi h expression is a tive; ifyou forget, you may onfuse yourself.So long as you remember where the values are set, you will have notrouble. In any event, the values are always set in your initialization �le,whi h is usually alled `.ema s'.I myself use ustomize for hardly anything. Mostly, I write expressionsmyself.16.3 Beginning a `.ema s' FileWhen you start Ema s, it loads your `.ema s' �le unless you tell it notto by spe ifying `-q' on the ommand line. (The ema s -q ommand givesyou a plain, out-of-the-box Ema s.)A `.ema s' �le ontains Lisp expressions. Often, these are no more thanexpressions to set values; sometimes they are fun tion de�nitions.See se tion \The Init File `~/.ema s'" in The GNU Ema s Manual, fora short des ription of initialization �les.This hapter goes over some of the same ground, but is a walk amongextra ts from a omplete, long-used `.ema s' �le|my own.The �rst part of the �le onsists of omments: reminders to myself. Bynow, of ourse, I remember these things, but when I started, I did not.

Page 235: An Introduction to Programming in Emacs Lisp

Text and Auto Fill Mode 217;;;; Bob's .ema s file; Robert J. Chassell; 26 September 1985Look at that date! I started this �le a long time ago. I have been adding toit ever sin e.; Ea h se tion in this file is introdu ed by a; line beginning with four semi olons; and ea h; entry is introdu ed by a line beginning with; three semi olons.This des ribes the usual onventions for omments in Ema s Lisp. Every-thing on a line that follows a semi olon is a omment. Two, three, andfour semi olons are used as se tion and subse tion markers. (See se tion\Comments" in The GNU Ema s Lisp Referen e Manual, for more about omments.);;;; The Help Key; Control-h is the help key;; after typing ontrol-h, type a letter to; indi ate the subje t about whi h you want help.; For an explanation of the help fa ility,; type ontrol-h two times in a row.Just remember: type C-h two times for help.; To find out about any mode, type ontrol-h m; while in that mode. For example, to find out; about mail mode, enter mail mode and then type; ontrol-h m.`Mode help', as I all this, is very helpful. Usually, it tells you all you needto know.Of ourse, you don't need to in lude omments like these in your `.ema s'�le. I in luded them in mine be ause I kept forgetting about Mode help orthe onventions for omments|but I was able to remember to look here toremind myself.16.4 Text and Auto Fill ModeNow we ome to the part that `turns on' Text mode and Auto Fill mode.;;; Text mode and Auto Fill mode; The next three lines put Ema s into Text mode; and Auto Fill mode, and are for writers who; want to start writing prose rather than ode.(setq default-major-mode 'text-mode)(add-hook 'text-mode-hook 'text-mode-hook-identify)(add-hook 'text-mode-hook 'turn-on-auto-fill)

Page 236: An Introduction to Programming in Emacs Lisp

218 Chapter 16: Your `.ema s' FileHere is the �rst part of this `.ema s' �le that does something besidesremind a forgetful human!The �rst of the two lines in parentheses tells Ema s to turn on Text modewhen you �nd a �le, unless that �le should go into some other mode, su has C mode.When Ema s reads a �le, it looks at the extension to the �le name, ifany. (The extension is the part that omes after a `.'.) If the �le ends witha `. ' or `.h' extension then Ema s turns on C mode. Also, Ema s looks at�rst nonblank line of the �le; if the line says `-*- C -*-', Ema s turns onC mode. Ema s possesses a list of extensions and spe i� ations that it usesautomati ally. In addition, Ema s looks near the last page for a per-bu�er,\lo al variables list", if any.See se tions \How Major Modes are Chosen" and \Lo al Variables inFiles" in The GNU Ema s Manual.Now, ba k to the `.ema s' �le.Here is the line again; how does it work?(setq default-major-mode 'text-mode)This line is a short, but omplete Ema s Lisp expression.We are already familiar with setq. It sets the following variable,default-major-mode, to the subsequent value, whi h is text-mode. Thesingle quote mark before text-mode tells Ema s to deal dire tly with thetext-mode variable, not with whatever it might stand for. See Se tion 1.9,\Setting the Value of a Variable", page 17, for a reminder of how setq works.The main point is that there is no di�eren e between the pro edure you useto set a value in your `.ema s' �le and the pro edure you use anywhere elsein Ema s.Here are the next two lines:(add-hook 'text-mode-hook 'text-mode-hook-identify)(add-hook 'text-mode-hook 'turn-on-auto-fill)In these two lines, the add-hook ommand �rst adds text-mode-hook-identify to the variable alled text-mode-hook and then adds turn-on-auto-fill to the variable.turn-on-auto-fill is the name of a program, that, you guessed it!,turns on Auto Fill mode. text-mode-hook-identify is a fun tion thattells toggle-text-mode-auto-fill whi h bu�ers are in Text mode.Every time Ema s turns on Text mode, Ema s runs the ommands`hooked' onto Text mode. So every time Ema s turns on Text mode, Ema salso turns on Auto Fill mode.In brief, the �rst line auses Ema s to enter Text mode when you edita �le, unless the �le name extension, �rst non-blank line, or lo al variablestell Ema s otherwise.Text mode among other a tions, sets the syntax table to work onve-niently for writers. In Text mode, Ema s onsiders an apostrophe as part

Page 237: An Introduction to Programming in Emacs Lisp

Indent Tabs Mode 219of a word like a letter; but Ema s does not onsider a period or a spa e aspart of a word. Thus, M-f moves you over `it's'. On the other hand, in Cmode, M-f stops just after the `t' of `it's'.The se ond and third lines auses Ema s to turn on Auto Fill mode whenit turns on Text mode. In Auto Fill mode, Ema s automati ally breaks aline that is too wide and brings the ex essively wide part of the line downto the next line. Ema s breaks lines between words, not within them.When Auto Fill mode is turned o�, lines ontinue to the right as youtype them. Depending on how you set the value of trun ate-lines, thewords you type either disappear o� the right side of the s reen, or else areshown, in a rather ugly and unreadable manner, as a ontinuation line onthe s reen.In addition, in this part of my `.ema s' �le, I tell the Ema s �ll ommandsto insert two spa es after a olon:(setq olon-double-spa e t)16.5 Mail AliasesHere is a setq that `turns on' mail aliases, along with more reminders.;;; Mail mode; To enter mail mode, type `C-x m'; To enter RMAIL (for reading mail),; type `M-x rmail'(setq mail-aliases t)This setq ommand sets the value of the variable mail-aliases to t. Sin et means true, the line says, in e�e t, \Yes, use mail aliases."Mail aliases are onvenient short names for long email addresses or forlists of email addresses. The �le where you keep your `aliases' is `~/.mailr '.You write an alias like this:alias geo george�foobar.wiz.eduWhen you write a message to George, address it to `geo'; the mailer willautomati ally expand `geo' to the full address.16.6 Indent Tabs ModeBy default, Ema s inserts tabs in pla e of multiple spa es when it formatsa region. (For example, you might indent many lines of text all at on ewith the indent-region ommand.) Tabs look �ne on a terminal or withordinary printing, but they produ e badly indented output when you useTEX or Texinfo sin e TEX ignores tabs.

Page 238: An Introduction to Programming in Emacs Lisp

220 Chapter 16: Your `.ema s' FileThe following turns o� Indent Tabs mode:;;; Prevent Extraneous Tabs(setq-default indent-tabs-mode nil)Note that this line uses setq-default rather than the setq ommandthat we have seen before. The setq-default ommand sets values only inbu�ers that do not have their own lo al values for the variable.See se tions \Tabs vs. Spa es" and \Lo al Variables in Files" in TheGNU Ema s Manual.16.7 Some KeybindingsNow for some personal keybindings:;;; Compare windows(global-set-key "\C- w" ' ompare-windows) ompare-windows is a nifty ommand that ompares the text in your urrent window with text in the next window. It makes the omparison bystarting at point in ea h window, moving over text in ea h window as far asthey mat h. I use this ommand all the time.This also shows how to set a key globally, for all modes.The ommand is global-set-key. It is followed by the keybinding. In a`.ema s' �le, the keybinding is written as shown: \C- stands for ` ontrol- ', whi h means `press the ontrol key and the key at the same time'.The w means `press the w key'. The keybinding is surrounded by doublequotation marks. In do umentation, you would write this as C- w. (If youwere binding a hMETAi key, su h as M- , rather than a hCTLi key, you wouldwrite \M- . See se tion \Rebinding Keys in Your Init File" in The GNUEma s Manual, for details.)The ommand invoked by the keys is ompare-windows. Note that ompare-windows is pre eded by a single quote; otherwise, Ema s would�rst try to evaluate the symbol to determine its value.These three things, the double quotation marks, the ba kslash before the`C', and the single quote mark are ne essary parts of keybinding that I tendto forget. Fortunately, I have ome to remember that I should look at myexisting `.ema s' �le, and adapt what is there.As for the keybinding itself: C- w. This ombines the pre�x key, C- ,with a single hara ter, in this ase, w. This set of keys, C- followed by asingle hara ter, is stri tly reserved for individuals' own use. (I all these`own' keys, sin e these are for my own use.) You should always be able to reate su h a keybinding for your own use without stomping on someoneelse's keybinding. If you ever write an extension to Ema s, please avoidtaking any of these keys for publi use. Create a key like C- C-w instead.Otherwise, we will run out of `own' keys.

Page 239: An Introduction to Programming in Emacs Lisp

Keymaps 221Here is another keybinding, with a omment:;;; Keybinding for `o ur'; I use o ur a lot, so let's bind it to a key:(global-set-key "\C- o" 'o ur)The o ur ommand shows all the lines in the urrent bu�er that ontaina mat h for a regular expression. Mat hing lines are shown in a bu�er alled`*O ur*'. That bu�er serves as a menu to jump to o urren es.Here is how to unbind a key, so it does not work:;;; Unbind `C-x f'(global-unset-key "\C-xf")There is a reason for this unbinding: I found I inadvertently typed C-x fwhen I meant to type C-x C-f. Rather than �nd a �le, as I intended, Ia identally set the width for �lled text, almost always to a width I did notwant. Sin e I hardly ever reset my default width, I simply unbound the key.The following rebinds an existing key:;;; Rebind `C-x C-b' for `buffer-menu'(global-set-key "\C-x\C-b" 'buffer-menu)By default, C-x C-b runs the list-buffers ommand. This ommandlists your bu�ers in another window. Sin e I almost always want to dosomething in that window, I prefer the buffer-menu ommand, whi h notonly lists the bu�ers, but moves point into that window.16.8 KeymapsEma s uses keymaps to re ord whi h keys all whi h ommands. Whenyou use global-set-key to set the keybinding for a single ommand in allparts of Ema s, you are spe ifying the keybinding in urrent-global-map.Spe i� modes, su h as C mode or Text mode, have their own keymaps;the mode-spe i� keymaps override the global map that is shared by allbu�ers.The global-set-key fun tion binds, or rebinds, the global keymap. Forexample, the following binds the key C-x C-b to the fun tion buffer-menu:(global-set-key "\C-x\C-b" 'buffer-menu)Mode-spe i� keymaps are bound using the define-key fun tion, whi htakes a spe i� keymap as an argument, as well as the key and the ommand.For example, my `.ema s' �le ontains the following expression to bind thetexinfo-insert-�group ommand to C- C- g:(define-key texinfo-mode-map "\C- \C- g" 'texinfo-insert-�group)The texinfo-insert-�group fun tion itself is a little extension to Texinfomode that inserts `�group' into a Texinfo �le. I use this ommand all thetime and prefer to type the three strokes C- C- g rather than the sixstrokes � g r o u p. (`�group' and its mat hing `�end group' are ommands

Page 240: An Introduction to Programming in Emacs Lisp

222 Chapter 16: Your `.ema s' Filethat keep all en losed text together on one page; many multi-line examplesin this book are surrounded by `�group ... �end group'.)Here is the texinfo-insert-�group fun tion de�nition:(defun texinfo-insert-�group ()"Insert the string �group in a Texinfo buffer."(intera tive)(beginning-of-line)(insert "�group\n"))(Of ourse, I ould have used Abbrev mode to save typing, rather thanwrite a fun tion to insert a word; but I prefer key strokes onsistent withother Texinfo mode key bindings.)You will see numerous define-key expressions in `loaddefs.el' as wellas in the various mode libraries, su h as ` -mode.el' and `lisp-mode.el'.See se tion \Customizing Key Bindings" in The GNU Ema s Manual,and se tion \Keymaps" in The GNU Ema s Lisp Referen e Manual, formore information about keymaps.16.9 Loading FilesMany people in the GNU Ema s ommunity have written extensions toEma s. As time goes by, these extensions are often in luded in new releases.For example, the Calendar and Diary pa kages are now part of the standardGNU Ema s.(Cal , whi h I onsider a vital part of Ema s, would be part of the stan-dard distribution ex ept that it was so large it was pa kaged separately andno one has hanged that.)You an use a load ommand to evaluate a omplete �le and therebyinstall all the fun tions and variables in the �le into Ema s. For example:(load "~/ema s/slowsplit")This evaluates, i.e. loads, the `slowsplit.el' �le or if it exists, thefaster, byte ompiled `slowsplit.el ' �le from the `ema s' sub-dire tory ofyour home dire tory. The �le ontains the fun tion split-window-quietly,whi h John Robinson wrote in 1989.The split-window-quietly fun tion splits a window with the minimumof redisplay. I installed it in 1989 be ause it worked well with the slow 1200baud terminals I was then using. Nowadays, I only o asionally ome a rosssu h a slow onne tion, but I ontinue to use the fun tion be ause I like theway it leaves the bottom half of a bu�er in the lower of the new windowsand the top half in the upper window.

Page 241: An Introduction to Programming in Emacs Lisp

Autoloading 223To repla e the key binding for the default split-window-verti ally,you must also unset that key and bind the keys to split-window-quietly,like this:(global-unset-key "\C-x2")(global-set-key "\C-x2" 'split-window-quietly)If you load many extensions, as I do, then instead of spe ifying the exa tlo ation of the extension �le, as shown above, you an spe ify that dire toryas part of Ema s' load-path. Then, when Ema s loads a �le, it will sear hthat dire tory as well as its default list of dire tories. (The default list isspe i�ed in `paths.h' when Ema s is built.)The following ommand adds your `~/ema s' dire tory to the existingload path:;;; Ema s Load Path(setq load-path ( ons "~/ema s" load-path))In identally, load-library is an intera tive interfa e to the load fun -tion. The omplete fun tion looks like this:(defun load-library (library)"Load the library named LIBRARY.This is an interfa e to the fun tion `load'."(intera tive "sLoad library: ")(load library))The name of the fun tion, load-library, omes from the use of `library'as a onventional synonym for `�le'. The sour e for the load-library om-mand is in the `files.el' library.Another intera tive ommand that does a slightly di�erent job is load-file. See se tion \Libraries of Lisp Code for Ema s" in The GNU Ema sManual, for information on the distin tion between load-library and this ommand.16.10 AutoloadingInstead of installing a fun tion by loading the �le that ontains it, or byevaluating the fun tion de�nition, you an make the fun tion available butnot a tually install it until it is �rst alled. This is alled autoloading.When you exe ute an autoloaded fun tion, Ema s automati ally evalu-ates the �le that ontains the de�nition, and then alls the fun tion.Ema s starts qui ker with autoloaded fun tions, sin e their libraries arenot loaded right away; but you need to wait a moment when you �rst usesu h a fun tion, while its ontaining �le is evaluated.Rarely used fun tions are frequently autoloaded. The `loaddefs.el' li-brary ontains hundreds of autoloaded fun tions, from bookmark-set towordstar-mode. Of ourse, you may ome to use a `rare' fun tion frequently.

Page 242: An Introduction to Programming in Emacs Lisp

224 Chapter 16: Your `.ema s' FileWhen you do, you should load that fun tion's �le with a load expression inyour `.ema s' �le.In my `.ema s' �le for Ema s version 21, I load 12 libraries that ontainfun tions that would otherwise be autoloaded. (A tually, it would have beenbetter to in lude these �les in my `dumped' Ema s when I built it, but Iforgot. See se tion \Building Ema s" in The GNU Ema s Lisp Referen eManual, and the `INSTALL' �le for more about dumping.)You may also want to in lude autoloaded expressions in your `.ema s'�le. autoload is a built-in fun tion that takes up to �ve arguments, the �nalthree of whi h are optional. The �rst argument is the name of the fun tionto be autoloaded; the se ond is the name of the �le to be loaded. The thirdargument is do umentation for the fun tion, and the fourth tells whetherthe fun tion an be alled intera tively. The �fth argument tells what typeof obje t|autoload an handle a keymap or ma ro as well as a fun tion(the default is a fun tion).Here is a typi al example:(autoload 'html-helper-mode"html-helper-mode" "Edit HTML do uments" t)(html-helper-mode is an alternative to html-mode, whi h is a standard partof the distribution).This expression autoloads the html-helper-mode fun tion. It takesit from the `html-helper-mode.el' �le (or from the byte ompiled�le `html-helper-mode.el ', if it exists.) The �le must be lo atedin a dire tory spe i�ed by load-path. The do umentation says thatthis is a mode to help you edit do uments written in the HyperTextMarkup Language. You an all this mode intera tively by typingM-x html-helper-mode. (You need to dupli ate the fun tion's regulardo umentation in the autoload expression be ause the regular fun tion isnot yet loaded, so its do umentation is not available.)See se tion \Autoload" in The GNU Ema s Lisp Referen e Manual, formore information.16.11 A Simple Extension: line-to-top-of-windowHere is a simple extension to Ema s that moves the line point is on tothe top of the window. I use this all the time, to make text easier to read.You an put the following ode into a separate �le and then load it fromyour `.ema s' �le, or you an in lude it within your `.ema s' �le.

Page 243: An Introduction to Programming in Emacs Lisp

A Simple Extension: line-to-top-of-window 225Here is the de�nition:;;; Line to top of window;;;; repla e three keystroke sequen e C-u 0 C-l(defun line-to-top-of-window ()"Move the line point is on to top of window."(intera tive)(re enter 0))Now for the keybinding.Nowadays, fun tion keys as well as mouse button events and non-as ii hara ters are written within square bra kets, without quotation marks. (InEma s version 18 and before, you had to write di�erent fun tion key bindingsfor ea h di�erent make of terminal.)I bind line-to-top-of-window to my hF6i fun tion key like this:(global-set-key [f6℄ 'line-to-top-of-window)For more information, see se tion \Rebinding Keys in Your Init File" inThe GNU Ema s Manual.If you run two versions of GNU Ema s, su h as versions 20 and 21, anduse one `.ema s' �le, you an sele t whi h ode to evaluate with the following onditional:( ond((string-equal (number-to-string 20) (substring (ema s-version) 10 12));; evaluate version 20 ode( ... ))((string-equal (number-to-string 21) (substring (ema s-version) 10 12));; evaluate version 21 ode( ... )))For example, in ontrast to version 20, version 21 blinks its ursor bydefault. I hate su h blinking, as well as some other features in version 21,so I pla ed the following in my `.ema s' �le2:(if (string-equal "21" (substring (ema s-version) 10 12))(progn(blink- ursor-mode 0);; Insert newline when you press `C-n' (next-line);; at the end of the buffer(setq next-line-add-newlines t);; Turn on image viewing(auto-image-file-mode t)2 When I start instan es of Ema s that do not load my `.ema s' �le or any site �le, Ialso turn o� blinking:ema s -q --no-site-file -eval '(blink- ursor-mode nil)'

Page 244: An Introduction to Programming in Emacs Lisp

226 Chapter 16: Your `.ema s' File;; Turn on menu bar (this bar has text);; (Use numeri argument to turn on)(menu-bar-mode 1);; Turn off tool bar (this bar has i ons);; (Use numeri argument to turn on)(tool-bar-mode nil);; Turn off tooltip mode for tool bar;; (This mode auses i on explanations to pop up);; (Use numeri argument to turn on)(tooltip-mode nil);; If tooltips turned on, make tips appear promptly(setq tooltip-delay 0.1) ; default is one se ond))(You will note that instead of typing (number-to-string 21), I de ided tosave typing and wrote `21' as a string, "21", rather than onvert it froman integer to a string. In this instan e, this expression is better than thelonger, but more general (number-to-string 21). However, if you do notknow ahead of time what type of information will be returned, then thenumber-to-string fun tion will be needed.)16.12 X11 ColorsYou an spe ify olors when you use Ema s with the MIT X Windowingsystem.I dislike the default olors and spe ify my own.Here are the expressions in my `.ema s' �le that set values:;; Set ursor olor(set- ursor- olor "white");; Set mouse olor(set-mouse- olor "white");; Set foreground and ba kground(set-foreground- olor "white")(set-ba kground- olor "darkblue");;; Set highlighting olors for isear h and drag(set-fa e-foreground 'highlight "white")(set-fa e-ba kground 'highlight "blue")(set-fa e-foreground 'region " yan")(set-fa e-ba kground 'region "blue")(set-fa e-foreground 'se ondary-sele tion "skyblue")(set-fa e-ba kground 'se ondary-sele tion "darkblue")

Page 245: An Introduction to Programming in Emacs Lisp

A Modi�ed Mode Line 227;; Set alendar highlighting olors(setq alendar-load-hook'(lambda ()(set-fa e-foreground 'diary-fa e "skyblue")(set-fa e-ba kground 'holiday-fa e "slate blue")(set-fa e-foreground 'holiday-fa e "white")))The various shades of blue soothe my eye and prevent me from seeing thes reen i ker.Alternatively, I ould have set my spe i� ations in various X initialization�les. For example, I ould set the foreground, ba kground, ursor, andpointer (i.e., mouse) olors in my `~/.Xresour es' �le like this:Ema s*foreground: whiteEma s*ba kground: darkblueEma s* ursorColor: whiteEma s*pointerColor: whiteIn any event, sin e it is not part of Ema s, I set the root olor of my Xwindow in my `~/.xinitr ' �le, like this3:# I use TWM for window manager.xsetroot -solid Navy -fg white &16.13 Mis ellaneous Settings for a `.ema s' FileHere are a few mis ellaneous settings:� Set the shape and olor of the mouse ursor:; Cursor shapes are defined in; `/usr/in lude/X11/ ursorfont.h';; for example, the `target' ursor is number 128;; the `top_left_arrow' ursor is number 132.(let ((mpointer (x-get-resour e "*mpointer""*ema s*mpointer")));; If you have not set your mouse pointer;; then set it, otherwise leave as is:(if (eq mpointer nil)(setq mpointer "132")) ; top_left_arrow(setq x-pointer-shape (string-to-int mpointer))(set-mouse- olor "white"))3 I o asionally run more modern window managers, su h as Saw�sh with GNOME,Enlightenment, SCWM, or KDE; in those ases, I often spe ify an image rather thana plain olor.

Page 246: An Introduction to Programming in Emacs Lisp

228 Chapter 16: Your `.ema s' File16.14 A Modi�ed Mode LineFinally, a feature I really like: a modi�ed mode line.When I work over a network, I forget whi h ma hine I am using. Also, Itend to I lose tra k of where I am, and whi h line point is on.So I reset my mode line to look like this:-:-- foo.texi rattlesnake:/home/bob/ Line 1 (Texinfo Fill) TopI am visiting a �le alled `foo.texi', on my ma hine `rattlesnake' inmy `/home/bob' bu�er. I am on line 1, in Texinfo mode, and am at the topof the bu�er.My `.ema s' �le has a se tion that looks like this:;; Set a Mode Line that tells me whi h ma hine, whi h dire tory,;; and whi h line I am on, plus the other ustomary information.(setq default-mode-line-format(quote(#("-" 0 1(help-e ho"mouse-1: sele t window, mouse-2: delete others ..."))mode-line-mule-infomode-line-modifiedmode-line-frame-identifi ation" "mode-line-buffer-identifi ation" "(:eval (substring(system-name) 0 (string-mat h "\\..+" (system-name))))":"default-dire tory#(" " 0 1(help-e ho"mouse-1: sele t window, mouse-2: delete others ..."))(line-number-mode " Line %l ")global-mode-string

Page 247: An Introduction to Programming in Emacs Lisp

A Modi�ed Mode Line 229#(" %[(" 0 6(help-e ho"mouse-1: sele t window, mouse-2: delete others ..."))(:eval (mode-line-mode-name))mode-line-pro essminor-mode-alist#("%n" 0 2 (help-e ho "mouse-2: widen" lo al-map (keymap ...)))")%℄ "(-3 . "%P");; "-%-")))Here, I rede�ne the default mode line. Most of the parts are from the original;but I make a few hanges. I set the default mode line format so as to permitvarious modes, su h as Info, to override it.Many elements in the list are self-explanatory: mode-line-modified isa variable that tells whether the bu�er has been modi�ed, mode-name tellsthe name of the mode, and so on. However, the format looks ompli atedbe ause of two features we have not dis ussed.The �rst string in the mode line is a dash or hyphen, `-'. In the old days,it would have been spe i�ed simply as "-". But nowadays, Ema s an addproperties to a string, su h as highlighting or, as in this ase, a help feature.If you pla e your mouse ursor over the hyphen, some help information ap-pears (By default, you must wait one se ond before the information appears.You an hange that timing by hanging the value of tooltip-delay.)The new string format has a spe ial syntax:#("-" 0 1 (help-e ho "mouse-1: sele t window, ..."))The #( begins a list. The �rst element of the list is the string itself, just one`-'. The se ond and third elements spe ify the range over whi h the fourthelement applies. A range starts after a hara ter, so a zero means the rangestarts just before the �rst hara ter; a 1 means that the range ends justafter the �rst hara ter. The third element is the property for the range.It onsists of a property list, a property name, in this ase, `help-e ho',followed by a value, in this ase, a string. The se ond, third, and fourthelements of this new string format an be repeated.See se tion \Text Properties in String" in The GNU Ema s Lisp Refer-en e Manual, and see se tion \Mode Line Format" in The GNU Ema s LispReferen e Manual, for more information.mode-line-buffer-identifi ation displays the urrent bu�er name.It is a list beginning (#("%12b" 0 4 .... The #( begins the list.The `"%12b"' displays the urrent bu�er name, using the buffer-namefun tion with whi h we are familiar; the `12' spe i�es the maximum numberof hara ters that will be displayed. When a name has fewer hara ters,whitespa e is added to �ll out to this number. (Bu�er names an and often

Page 248: An Introduction to Programming in Emacs Lisp

230 Chapter 16: Your `.ema s' Fileshould be longer than 12 hara ters; this length works well in a typi al 80 olumn wide window.):eval is a new feature in GNU Ema s version 21. It says to evaluatethe following form and use the result as a string to display. In this ase, theexpression displays the �rst omponent of the full system name. The end ofthe �rst omponent is a `.' (`period'), so I use the string-mat h fun tionto tell me the length of the �rst omponent. The substring from the zeroth hara ter to that length is the name of the ma hine.This is the expression:(:eval (substring(system-name) 0 (string-mat h "\\..+" (system-name))))`%[' and `%℄' ause a pair of square bra kets to appear for ea h re ursiveediting level. `%n' says `Narrow' when narrowing is in e�e t. `%P' tells youthe per entage of the bu�er that is above the bottom of the window, or`Top', `Bottom', or `All'. (A lower ase `p' tell you the per entage above thetop of the window.) `%-' inserts enough dashes to �ll out the line.Remember, \You don't have to like Ema s to like it" | your own Ema s an have di�erent olors, di�erent ommands, and di�erent keys than adefault Ema s.On the other hand, if you want to bring up a plain `out of the box' Ema s,with no ustomization, type:ema s -qThis will start an Ema s that does not load your `~/.ema s' initialization�le. A plain, default Ema s. Nothing more.

Page 249: An Introduction to Programming in Emacs Lisp

debug 23117 DebuggingGNU Ema s has two debuggers, debug and edebug. The �rst is builtinto the internals of Ema s and is always with you; the se ond requires thatyou instrument a fun tion before you an use it.Both debuggers are des ribed extensively in se tion \Debugging Lisp Pro-grams" in The GNU Ema s Lisp Referen e Manual. In this hapter, I willwalk through a short example of ea h.17.1 debugSuppose you have written a fun tion de�nition that is intended to returnthe sum of the numbers 1 through a given number. (This is the trianglefun tion dis ussed earlier. See \Example with De rementing Counter",page 129, for a dis ussion.)However, your fun tion de�nition has a bug. You have mistyped `1=' for`1-'. Here is the broken de�nition:(defun triangle-bugged (number)"Return sum of numbers 1 through NUMBER in lusive."(let ((total 0))(while (> number 0)(setq total (+ total number))(setq number (1= number))) ; Error here.total))If you are reading this in Info, you an evaluate this de�nition in thenormal fashion. You will see triangle-bugged appear in the e ho area.Now evaluate the triangle-bugged fun tion with an argument of 4:(triangle-bugged 4)In GNU Ema s version 21, you will reate and enter a `*Ba ktra e*' bu�erthat says:---------- Buffer: *Ba ktra e* ----------Debugger entered--Lisp error: (void-fun tion 1=)(1= number)(setq number (1= number))(while (> number 0) (setq total (+ total number))(setq number (1= number)))(let ((total 0)) (while (> number 0) (setq total ...)(setq number ...)) total)triangle-bugged(4)

Page 250: An Introduction to Programming in Emacs Lisp

232 Chapter 17: Debuggingeval((triangle-bugged 4))eval-last-sexp-1(nil)eval-last-sexp(nil) all-intera tively(eval-last-sexp)---------- Buffer: *Ba ktra e* ----------(I have reformatted this example slightly; the debugger does not fold longlines. As usual, you an quit the debugger by typing q in the `*Ba ktra e*'bu�er.)In pra ti e, for a bug as simple as this, the `Lisp error' line will tell youwhat you need to know to orre t the de�nition. The fun tion 1= is `void'.In GNU Ema s 20 and before, you will see:Symbol's fun tion definition is void: 1=whi h has the same meaning as the `*Ba ktra e*' bu�er line in version 21.However, suppose you are not quite ertain what is going on? You anread the omplete ba ktra e.In this ase, you need to run GNU Ema s 21, whi h automati ally startsthe debugger that puts you in the `*Ba ktra e*' bu�er; or else, you need tostart the debugger manually as des ribed below.Read the `*Ba ktra e*' bu�er from the bottom up; it tells you whatEma s did that led to the error. Ema s made an intera tive all to C-x C-e (eval-last-sexp), whi h led to the evaluation of the triangle-buggedexpression. Ea h line above tells you what the Lisp interpreter evaluatednext.The third line from the top of the bu�er is(setq number (1= number))Ema s tried to evaluate this expression; in order to do so, it tried to evaluatethe inner expression shown on the se ond line from the top:(1= number)This is where the error o urred; as the top line says:Debugger entered--Lisp error: (void-fun tion 1=)You an orre t the mistake, re-evaluate the fun tion de�nition, and thenrun your test again.17.2 debug-on-entryGNU Ema s 21 starts the debugger automati ally when your fun tionhas an error. GNU Ema s version 20 and before did not; it simply presentedyou with an error message. You had to start the debugger manually.You an start the debugger manually for all versions of Ema s; the ad-vantage is that the debugger runs even if you do not have a bug in your ode. Sometimes your ode will be free of bugs!

Page 251: An Introduction to Programming in Emacs Lisp

debug-on-entry 233You an enter the debugger when you all the fun tion by alling debug-on-entry.Type:M-x debug-on-entry RET triangle-bugged RETNow, evaluate the following:(triangle-bugged 5)All versions of Ema s will reate a `*Ba ktra e*' bu�er and tell you that itis beginning to evaluate the triangle-bugged fun tion:---------- Buffer: *Ba ktra e* ----------Debugger entered--entering a fun tion:* triangle-bugged(5)eval((triangle-bugged 5))eval-last-sexp-1(nil)eval-last-sexp(nil) all-intera tively(eval-last-sexp)---------- Buffer: *Ba ktra e* ----------In the `*Ba ktra e*' bu�er, type d. Ema s will evaluate the �rst expres-sion in triangle-bugged; the bu�er will look like this:---------- Buffer: *Ba ktra e* ----------Debugger entered--beginning evaluation of fun tion all form:* (let ((total 0)) (while (> number 0) (setq total ...)(setq number ...)) total)* triangle-bugged(5)eval((triangle-bugged 5))eval-last-sexp-1(nil)eval-last-sexp(nil) all-intera tively(eval-last-sexp)---------- Buffer: *Ba ktra e* ----------Now, type d again, eight times, slowly. Ea h time you type d, Ema s willevaluate another expression in the fun tion de�nition.

Page 252: An Introduction to Programming in Emacs Lisp

234 Chapter 17: DebuggingEventually, the bu�er will look like this:---------- Buffer: *Ba ktra e* ----------Debugger entered--beginning evaluation of fun tion all form:* (setq number (1= number))* (while (> number 0) (setq total (+ total number))(setq number (1= number)))* (let ((total 0)) (while (> number 0) (setq total ...)(setq number ...)) total)* triangle-bugged(5)eval((triangle-bugged 5))eval-last-sexp-1(nil)eval-last-sexp(nil) all-intera tively(eval-last-sexp)---------- Buffer: *Ba ktra e* ----------Finally, after you type d two more times, Ema s will rea h the error, andthe top two lines of the `*Ba ktra e*' bu�er will look like this:---------- Buffer: *Ba ktra e* ----------Debugger entered--Lisp error: (void-fun tion 1=)* (1= number)...---------- Buffer: *Ba ktra e* ----------By typing d, you were able to step through the fun tion.You an quit a `*Ba ktra e*' bu�er by typing q in it; this quits the tra e,but does not an el debug-on-entry.To an el the e�e t of debug-on-entry, all an el-debug-on-entryand the name of the fun tion, like this:M-x an el-debug-on-entry RET triangle-bugged RET(If you are reading this in Info, an el debug-on-entry now.)17.3 debug-on-quit and (debug)In addition to setting debug-on-error or alling debug-on-entry, thereare two other ways to start debug.You an start debug whenever you type C-g (keyboard-quit) by settingthe variable debug-on-quit to t. This is useful for debugging in�nite loops.

Page 253: An Introduction to Programming in Emacs Lisp

The edebug Sour e Level Debugger 235Or, you an insert a line that says (debug) into your ode where youwant the debugger to start, like this:(defun triangle-bugged (number)"Return sum of numbers 1 through NUMBER in lusive."(let ((total 0))(while (> number 0)(setq total (+ total number))(debug) ; Start debugger.(setq number (1= number))) ; Error here.total))The debug fun tion is des ribed in detail in se tion \The Lisp Debugger"in The GNU Ema s Lisp Referen e Manual.17.4 The edebug Sour e Level DebuggerEdebug is a sour e level debugger. Edebug normally displays the sour eof the ode you are debugging, with an arrow at the left that shows whi hline you are urrently exe uting.You an walk through the exe ution of a fun tion, line by line, or runqui kly until rea hing a breakpoint where exe ution stops.Edebug is des ribed in se tion \Edebug" in The GNU Ema s Lisp Ref-eren e Manual.Here is a bugged fun tion de�nition for triangle-re ursively. SeeSe tion 11.3.4, \Re ursion in pla e of a ounter", page 137, for a review ofit. (defun triangle-re ursively-bugged (number)"Return sum of numbers 1 through NUMBER in lusive.Uses re ursion."(if (= number 1)1(+ number(triangle-re ursively-bugged(1= number))))) ; Error here.Normally, you would install this de�nition by positioning your ursor afterthe fun tion's losing parenthesis and typing C-x C-e (eval-last-sexp) orelse by positioning your ursor within the de�nition and typing C-M-x (eval-defun). (By default, the eval-defun ommand works only in Ema s Lispmode or in Lisp Intera tive mode.)

Page 254: An Introduction to Programming in Emacs Lisp

236 Chapter 17: DebuggingHowever, to prepare this fun tion de�nition for Edebug, you must �rstinstrument the ode using a di�erent ommand. You an do this by posi-tioning your ursor within the de�nition and typingM-x edebug-defun RETThis will ause Ema s to load Edebug automati ally if it is not alreadyloaded, and properly instrument the fun tion.After instrumenting the fun tion, pla e your ursor after the followingexpression and type C-x C-e (eval-last-sexp):(triangle-re ursively-bugged 3)You will be jumped ba k to the sour e for triangle-re ursively-buggedand the ursor positioned at the beginning of the if line of the fun tion.Also, you will see an arrowhead at the left hand side of that line. Thearrowhead marks the line where the fun tion is exe uting. (In the followingexamples, we show the arrowhead with `=>'; in a windowing system, youmay see the arrowhead as a solid triangle in the window `fringe'.)=>?(if (= number 1)In the example, the lo ation of point is displayed with a star, `?' (in Info, itis displayed as `-!-').If you now press hSPCi, point will move to the next expression to beexe uted; the line will look like this:=>(if ?(= number 1)As you ontinue to press hSPCi, point will move from expression to expression.At the same time, whenever an expression returns a value, that value will bedisplayed in the e ho area. For example, after you move point past number,you will see the following:Result: 3 = C- This means the value of number is 3, whi h is as ii ` ontrol- ' (the thirdletter of the alphabet).You an ontinue moving through the ode until you rea h the line withthe error. Before evaluation, that line looks like this:=> ?(1= number))))) ; Error here.When you press hSPCi on e again, you will produ e an error message thatsays:Symbol's fun tion definition is void: 1=This is the bug.Press q to quit Edebug.To remove instrumentation from a fun tion de�nition, simply re-evaluateit with a ommand that does not instrument it. For example, you ouldpla e your ursor after the de�nition's losing parenthesis and type C-x C-e.Edebug does a great deal more than walk with you through a fun tion.You an set it so it ra es through on its own, stopping only at an error or atspe i�ed stopping points; you an ause it to display the hanging values of

Page 255: An Introduction to Programming in Emacs Lisp

Debugging Exer ises 237various expressions; you an �nd out how many times a fun tion is alled,and more.Edebug is des ribed in se tion \Edebug" in The GNU Ema s Lisp Ref-eren e Manual.17.5 Debugging Exer ises� Install the ount-words-region fun tion and then ause it to enterthe built-in debugger when you all it. Run the ommand on a region ontaining two words. You will need to press d a remarkable number oftimes. On your system, is a `hook' alled after the ommand �nishes?(For information on hooks, see se tion \Command Loop Overview" inThe GNU Ema s Lisp Referen e Manual.)� Copy ount-words-region into the `*s rat h*' bu�er, instrument thefun tion for Edebug, and walk through its exe ution. The fun tion doesnot need to have a bug, although you an introdu e one if you wish. Ifthe fun tion la ks a bug, the walk-through ompletes without problems.� While running Edebug, type ? to see a list of all the Edebug ommands.(The global-edebug-prefix is usually C-x X, i.e. hCTLi-x followed byan upper ase X; use this pre�x for ommands made outside of theEdebug debugging bu�er.)� In the Edebug debugging bu�er, use the p (edebug-boun e-point) ommand to see where in the region the ount-words-region is work-ing.� Move point to some spot further down fun tion and then type the h(edebug-goto-here) ommand to jump to that lo ation.� Use the t (edebug-tra e-mode) ommand to ause Edebug to walkthrough the fun tion on its own; use an upper ase T for edebug-Tra e-fast-mode.� Set a breakpoint, then run Edebug in Tra e mode until it rea hes thestopping point.

Page 256: An Introduction to Programming in Emacs Lisp

238 Chapter 17: Debugging

Page 257: An Introduction to Programming in Emacs Lisp

Con lusion 23918 Con lusionWe have now rea hed the end of this Introdu tion. You have now learnedenough about programming in Ema s Lisp to set values, to write simple`.ema s' �les for yourself and your friends, and write simple ustomizationsand extensions to Ema s.This is a pla e to stop. Or, if you wish, you an now go onward, andtea h yourself.You have learned some of the basi nuts and bolts of programming. Butonly some. There are a great many more bra kets and hinges that are easyto use that we have not tou hed.A path you an follow right now lies among the sour es to GNU Ema sand in The GNU Ema s Lisp Referen e Manual.The Ema s Lisp sour es are an adventure. When you read the sour esand ome a ross a fun tion or expression that is unfamiliar, you need to�gure out or �nd out what it does.Go to the Referen e Manual. It is a thorough, omplete, and fairly easy-to-read des ription of Ema s Lisp. It is written not only for experts, butfor people who know what you know. (The Referen e Manual omes withthe standard GNU Ema s distribution. Like this introdu tion, it omes asa Texinfo sour e �le, so you an read it on-line and as a typeset, printedbook.)Go to the other on-line help that is part of GNU Ema s: the on-linedo umentation for all fun tions, and find-tags, the program that takesyou to sour es.Here is an example of how I explore the sour es. Be ause of its name,`simple.el' is the �le I looked at �rst, a long time ago. As it happens someof the fun tions in `simple.el' are ompli ated, or at least look ompli atedat �rst sight. The open-line fun tion, for example, looks ompli ated.You may want to walk through this fun tion slowly, as we did withthe forward-senten e fun tion. (See Se tion 12.3, \forward-senten e",page 151.) Or you may want to skip that fun tion and look at another,su h as split-line. You don't need to read all the fun tions. A ordingto ount-words-in-defun, the split-line fun tion ontains 27 words andsymbols.Even though it is short, split-line ontains four expressions we havenot studied: skip- hars-forward, indent-to, urrent- olumn and `?\n'.Consider the skip- hars-forward fun tion. (It is part of the fun tionde�nition for ba k-to-indentation, whi h is shown in Se tion 3.11, \Re-view", page 46.)In GNU Ema s, you an �nd out more about skip- hars-forward bytyping C-h f (des ribe-fun tion) and the name of the fun tion. This givesyou the fun tion do umentation.

Page 258: An Introduction to Programming in Emacs Lisp

240 Chapter 18: Con lusionYou may be able to guess what is done by a well named fun tion su h asindent-to; or you an look it up, too. In identally, the des ribe-fun tionfun tion itself is in `help.el'; it is one of those long, but de ipherable fun -tions. You an look up des ribe-fun tion using the C-h f ommand!In this instan e, sin e the ode is Lisp, the `*Help*' bu�er ontains thename of the library ontaining the fun tion's sour e. You an put point overthe name of the library and press the RET key, whi h in this situation isbound to help-follow, and be taken dire tly to the sour e, in the same wayas M-. (find-tag).The de�nition for des ribe-fun tion illustrates how to ustomize theintera tive expression without using the standard hara ter odes; and itshows how to reate a temporary bu�er.(The indent-to fun tion is written in C rather than Ema s Lisp; it is a`built-in' fun tion. help-follow only provides you with the do umentationof a built-in fun tion; it does not take you to the sour e. But find-tag willtake you to the sour e, if properly set up.)You an look at a fun tion's sour e using find-tag, whi h is bound toM-. Finally, you an �nd out what the Referen e Manual has to say byvisiting the manual in Info, and typing i (Info-index) and the name of thefun tion, or by looking up skip- hars-forward in the index to a printed opy of the manual.Similarly, you an �nd out what is meant by `?\n'. You an try usingInfo-index with `?\n'. It turns out that this a tion won't help; but don'tgive up. If you sear h the index for `\n' without the `?', you will be takendire tly to the relevant se tion of the manual. (See se tion \Chara ter Type"in The GNU Ema s Lisp Referen e Manual. `?\n' stands for the newline hara ter.)Other interesting sour e �les in lude `paragraphs.el', `loaddefs.el',and `loadup.el'. The `paragraphs.el' �le in ludes short, easily understoodfun tions as well as longer ones. The `loaddefs.el' �le ontains the manystandard autoloads and many keymaps. I have never looked at it all; only atparts. `loadup.el' is the �le that loads the standard parts of Ema s; it tellsyou a great deal about how Ema s is built. (See se tion \Building Ema s"in The GNU Ema s Lisp Referen e Manual, for more about building.)As I said, you have learned some nuts and bolts; however, and veryimportantly, we have hardly tou hed major aspe ts of programming; I havesaid nothing about how to sort information, ex ept to use the prede�nedsort fun tion; I have said nothing about how to store information, ex eptto use variables and lists; I have said nothing about how to write programsthat write programs. These are topi s for another, and di�erent kind ofbook, a di�erent kind of learning.What you have done is learn enough for mu h pra ti al work with GNUEma s. What you have done is get started. This is the end of a beginning.

Page 259: An Introduction to Programming in Emacs Lisp

The the-the Fun tion 241Appendix A The the-the Fun tionSometimes when you you write text, you dupli ate words|as with \youyou" near the beginning of this senten e. I �nd that most frequently, Idupli ate \the'; hen e, I all the fun tion for dete ting dupli ated words,the-the.As a �rst step, you ould use the following regular expression to sear hfor dupli ates:\\(\\w+[ \t\n℄+\\)\\1This regexp mat hes one or more word- onstituent hara ters followed byone or more spa es, tabs, or newlines. However, it does not dete t dupli atedwords on di�erent lines, sin e the ending of the �rst word, the end of theline, is di�erent from the ending of the se ond word, a spa e. (For moreinformation about regular expressions, see Chapter 12, \Regular ExpressionSear hes", page 149, as well as se tion \Syntax of Regular Expressions" inThe GNU Ema s Manual, and se tion \Regular Expressions" in The GNUEma s Lisp Referen e Manual.)You might try sear hing just for dupli ated word- onstituent hara tersbut that does not work sin e the pattern dete ts doubles su h as the twoo urren es of `th' in `with the'.Another possible regexp sear hes for word- onstituent hara ters followedby non-word- onstituent hara ters, redupli ated. Here, `\\w+' mat hes oneor more word- onstituent hara ters and `\\W*' mat hes zero or more non-word- onstituent hara ters.\\(\\(\\w+\\)\\W*\\)\\1Again, not useful.Here is the pattern that I use. It is not perfe t, but good enough. `\\b'mat hes the empty string, provided it is at the beginning or end of a word;`[^� \n\t℄+' mat hes one or more o urren es of any hara ters that arenot an �-sign, spa e, newline, or tab.\\b\\([^� \n\t℄+\\)[ \n\t℄+\\1\\bOne an write more ompli ated expressions, but I found that this ex-pression is good enough, so I use it.Here is the the-the fun tion, as I in lude it in my `.ema s' �le, alongwith a handy global key binding:(defun the-the ()"Sear h forward for for a dupli ated word."(intera tive)(message "Sear hing for for dupli ated words ...")(push-mark)

Page 260: An Introduction to Programming in Emacs Lisp

242 Appendix A: The the-the Fun tion;; This regexp is not perfe t;; but is fairly good over all:(if (re-sear h-forward"\\b\\([^� \n\t℄+\\)[ \n\t℄+\\1\\b" nil 'move)(message "Found dupli ated word.")(message "End of buffer")));; Bind `the-the' to C- \(global-set-key "\C- \\" 'the-the)Here is test text:one two two three four fivefive six sevenYou an substitute the other regular expressions shown above in the fun -tion de�nition and try ea h of them on this list.

Page 261: An Introduction to Programming in Emacs Lisp

The rotate-yank-pointer Fun tion 243Appendix B Handling the Kill RingThe kill ring is a list that is transformed into a ring by the workings of therotate-yank-pointer fun tion. The yank and yank-pop ommands use therotate-yank-pointer fun tion. This appendix des ribes the rotate-yank-pointer fun tion as well as both the yank and the yank-pop ommands.B.1 The rotate-yank-pointer Fun tionThe rotate-yank-pointer fun tion hanges the element in the kill ringto whi h kill-ring-yank-pointer points. For example, it an hangekill-ring-yank-pointer from pointing to the se ond element to point tothe third element.Here is the ode for rotate-yank-pointer:(defun rotate-yank-pointer (arg)"Rotate the yanking point in the kill ring."(intera tive "p")(let ((length (length kill-ring)))(if (zerop length);; then-part(error "Kill ring is empty");; else-part(setq kill-ring-yank-pointer(nth dr (% (+ arg(- length(lengthkill-ring-yank-pointer)))length)kill-ring)))))The rotate-yank-pointer fun tion looks omplex, but as usual, it anbe understood by taking it apart pie e by pie e. First look at it in skeletalform:(defun rotate-yank-pointer (arg)"Rotate the yanking point in the kill ring."(intera tive "p")(let varlistbody...)This fun tion takes one argument, alled arg. It has a brief do umen-tation string; and it is intera tive with a small `p', whi h means that theargument must be a pro essed pre�x passed to the fun tion as a number.The body of the fun tion de�nition is a let expression, whi h itself hasa body as well as a varlist.

Page 262: An Introduction to Programming in Emacs Lisp

244 Appendix B: Handling the Kill RingThe let expression de lares a variable that will be only usable withinthe bounds of this fun tion. This variable is alled length and is bound toa value that is equal to the number of items in the kill ring. This is doneby using the fun tion alled length. (Note that this fun tion has the samename as the variable alled length; but one use of the word is to name thefun tion and the other is to name the variable. The two are quite distin t.Similarly, an English speaker will distinguish between the meanings of theword `ship' when he says: "I must ship this pa kage immediately." and "Imust get aboard the ship immediately.")The fun tion length tells the number of items there are in a list, so(length kill-ring) returns the number of items there are in the kill ring.B.1.1 The Body of rotate-yank-pointerThe body of rotate-yank-pointer is a let expression and the body ofthe let expression is an if expression.The purpose of the if expression is to �nd out whether there is anythingin the kill ring. If the kill ring is empty, the error fun tion stops evaluationof the fun tion and prints a message in the e ho area. On the other hand, ifthe kill ring has something in it, the work of the fun tion is done.Here is the if-part and then-part of the if expression:(if (zerop length) ; if-part(error "Kill ring is empty") ; then-part...If there is not anything in the kill ring, its length must be zero and an errormessage sent to the user: `Kill ring is empty'. The if expression uses thefun tion zerop whi h returns true if the value it is testing is zero. Whenzerop tests true, the then-part of the if is evaluated. The then-part isa list starting with the fun tion error, whi h is a fun tion that is similarto the message fun tion (see Se tion 1.8.5, \message", page 16), in that itprints a one-line message in the e ho area. However, in addition to printinga message, error also stops evaluation of the fun tion within whi h it isembedded. This means that the rest of the fun tion will not be evaluated ifthe length of the kill ring is zero.(In my opinion, it is slightly misleading, at least to humans, to use theterm `error' as the name of the error fun tion. A better term would be` an el'. Stri tly speaking, of ourse, you annot point to, mu h less rotatea pointer to a list that has no length, so from the point of view of the omputer, the word `error' is orre t. But a human expe ts to attempt thissort of thing, if only to �nd out whether the kill ring is full or empty. Thisis an a t of exploration.(From the human point of view, the a t of exploration and dis overy isnot ne essarily an error, and therefore should not be labelled as one, even inthe bowels of a omputer. As it is, the ode in Ema s implies that a humanwho is a ting virtuously, by exploring his or her environment, is making an

Page 263: An Introduction to Programming in Emacs Lisp

The else-part of the if expression 245error. This is bad. Even though the omputer takes the same steps as itdoes when there is an `error', a term su h as ` an el' would have a learer onnotation.)The else-part of the if expressionThe else-part of the if expression is dedi ated to setting the value ofkill-ring-yank-pointer when the kill ring has something in it. The odelooks like this:(setq kill-ring-yank-pointer(nth dr (% (+ arg(- length(length kill-ring-yank-pointer)))length)kill-ring)))))This needs some examination. Clearly, kill-ring-yank-pointer is be-ing set to be equal to some dr of the kill ring, using the nth dr fun tionthat is des ribed in an earlier se tion. (See Se tion 8.5, \ opy-region-as-kill",page 102.) But exa tly how does it do this?Before looking at the details of the ode let's �rst onsider the purposeof the rotate-yank-pointer fun tion.The rotate-yank-pointer fun tion hanges what kill-ring-yank-pointer points to. If kill-ring-yank-pointer starts by pointing to the�rst element of a list, a all to rotate-yank-pointer auses it to point tothe se ond element; and if kill-ring-yank-pointer points to the se ondelement, a all to rotate-yank-pointer auses it to point to the third ele-ment. (And if rotate-yank-pointer is given an argument greater than 1,it jumps the pointer that many elements.)The rotate-yank-pointer fun tion uses setq to reset what the kill-ring-yank-pointer points to. If kill-ring-yank-pointer points to the�rst element of the kill ring, then, in the simplest ase, the rotate-yank-pointer fun tion must ause it to point to the se ond element. Put anotherway, kill-ring-yank-pointer must be reset to have a value equal to the dr of the kill ring.That is, under these ir umstan es,(setq kill-ring-yank-pointer("some text" "a different pie e of text" "yet more text"))(setq kill-ring("some text" "a different pie e of text" "yet more text"))

Page 264: An Introduction to Programming in Emacs Lisp

246 Appendix B: Handling the Kill Ringthe ode should do this:(setq kill-ring-yank-pointer ( dr kill-ring))As a result, the kill-ring-yank-pointer will look like this:kill-ring-yank-pointer) ("a different pie e of text" "yet more text"))The a tual setq expression uses the nth dr fun tion to do the job.As we have seen before (see Se tion 7.3, \nth dr", page 85), the nth drfun tion works by repeatedly taking the dr of a list|it takes the dr ofthe dr of the dr . . .The two following expressions produ e the same result:(setq kill-ring-yank-pointer ( dr kill-ring))(setq kill-ring-yank-pointer (nth dr 1 kill-ring))In the rotate-yank-pointer fun tion, however, the �rst argument tonth dr is a rather omplex looking expression with lots of arithmeti insideof it:(% (+ arg(- length(length kill-ring-yank-pointer)))length)As usual, we need to look at the most deeply embedded expression �rstand then work our way towards the light.The most deeply embedded expression is (length kill-ring-yank-pointer). This �nds the length of the urrent value of the kill-ring-yank-pointer. (Remember that the kill-ring-yank-pointer is the nameof a variable whose value is a list.)The measurement of the length is inside the expression:(- length (length kill-ring-yank-pointer))In this expression, the �rst length is the variable that was assigned thelength of the kill ring in the let statement at the beginning of the fun tion.(One might think this fun tion would be learer if the variable length werenamed length-of-kill-ring instead; but if you look at the text of thewhole fun tion, you will see that it is so short that naming this variablelength is not a bother, unless you are pulling the fun tion apart into verytiny pie es as we are doing here.)So the line (- length (length kill-ring-yank-pointer)) tells the dif-feren e between the length of the kill ring and the length of the list whosename is kill-ring-yank-pointer.To see how all this �ts into the rotate-yank-pointer fun tion, let'sbegin by analyzing the ase where kill-ring-yank-pointer points to the�rst element of the kill ring, just as kill-ring does, and see what happenswhen rotate-yank-pointer is alled with an argument of 1.

Page 265: An Introduction to Programming in Emacs Lisp

The % remainder fun tion 247The variable length and the value of the expression (length kill-ring-yank-pointer) will be the same sin e the variable length is the length ofthe kill ring and the kill-ring-yank-pointer is pointing to the whole killring. Consequently, the value of(- length (length kill-ring-yank-pointer))will be zero. Sin e the value of arg will be 1, this will mean that the valueof the whole expression(+ arg (- length (length kill-ring-yank-pointer)))will be 1.Consequently, the argument to nth dr will be found as the result of theexpression(% 1 length)The % remainder fun tionTo understand (% 1 length), we need to understand %. A ording to itsdo umentation (whi h I just found by typing C-h f % hRETi), the % fun tionreturns the remainder of its �rst argument divided by its se ond argument.For example, the remainder of 5 divided by 2 is 1. (2 goes into 5 twi e witha remainder of 1.)What surprises people who don't often do arithmeti is that a smallernumber an be divided by a larger number and have a remainder. In theexample we just used, 5 was divided by 2. We an reverse that and ask,what is the result of dividing 2 by 5? If you an use fra tions, the answeris obviously 2/5 or .4; but if, as here, you an only use whole numbers, theresult has to be something di�erent. Clearly, 5 an go into 2 zero times, butwhat of the remainder? To see what the answer is, onsider a ase that hasto be familiar from hildhood:� 5 divided by 5 is 1 with a remainder of 0;� 6 divided by 5 is 1 with a remainder of 1;� 7 divided by 5 is 1 with a remainder of 2.� Similarly, 10 divided by 5 is 2 with a remainder of 0;� 11 divided by 5 is 2 with a remainder of 1;� 12 divided by 5 is 1 with a remainder of 2.By onsidering the ases as parallel, we an see that� zero divided by 5 must be zero with a remainder of zero;� 1 divided by 5 must be zero with a remainder of 1;� 2 divided by 5 must be zero with a remainder of 2;and so on.

Page 266: An Introduction to Programming in Emacs Lisp

248 Appendix B: Handling the Kill RingSo, in this ode, if the value of length is 5, then the result of evaluating(% 1 5)is 1. (I just he ked this by pla ing the ursor after the expression and typingC-x C-e. Indeed, 1 is printed in the e ho area.)Using % in rotate-yank-pointerWhen the kill-ring-yank-pointer points to the beginning of the killring, and the argument passed to rotate-yank-pointer is 1, the % expres-sion returns 1:(- length (length kill-ring-yank-pointer))) 0therefore,(+ arg (- length (length kill-ring-yank-pointer)))) 1and onsequently:(% (+ arg (- length (length kill-ring-yank-pointer)))length)) 1regardless of the value of length.As a result of this, the setq kill-ring-yank-pointer expression simpli�esto: (setq kill-ring-yank-pointer (nth dr 1 kill-ring))What it does is now easy to understand. Instead of pointing as it did to the�rst element of the kill ring, the kill-ring-yank-pointer is set to pointto the se ond element.Clearly, if the argument passed to rotate-yank-pointer is two, thenthe kill-ring-yank-pointer is set to (nth dr 2 kill-ring); and so onfor di�erent values of the argument.Similarly, if the kill-ring-yank-pointer starts out pointing to the se -ond element of the kill ring, its length is shorter than the length of the killring by 1, so the omputation of the remainder is based on the expression(% (+ arg 1) length). This means that the kill-ring-yank-pointer ismoved from the se ond element of the kill ring to the third element if theargument passed to rotate-yank-pointer is 1.Pointing to the last elementThe �nal question is, what happens if the kill-ring-yank-pointer isset to the last element of the kill ring? Will a all to rotate-yank-pointermean that nothing more an be taken from the kill ring? The answer is no.What happens is di�erent and useful. The kill-ring-yank-pointer is setto point to the beginning of the kill ring instead.

Page 267: An Introduction to Programming in Emacs Lisp

yank 249Let's see how this works by looking at the ode, assuming the length ofthe kill ring is 5 and the argument passed to rotate-yank-pointer is 1.When the kill-ring-yank-pointer points to the last element of the killring, its length is 1. The ode looks like this:(% (+ arg (- length (length kill-ring-yank-pointer))) length)When the variables are repla ed by their numeri values, the expressionlooks like this:(% (+ 1 (- 5 1)) 5)This expression an be evaluated by looking at the most embedded innerexpression �rst and working outwards: The value of (- 5 1) is 4; the sumof (+ 1 4) is 5; and the remainder of dividing 5 by 5 is zero. So whatrotate-yank-pointer will do is(setq kill-ring-yank-pointer (nth dr 0 kill-ring))whi h will set the kill-ring-yank-pointer to point to the beginning ofthe kill ring.So what happens with su essive alls to rotate-yank-pointer is thatit moves the kill-ring-yank-pointer from element to element in the killring until it rea hes the end; then it jumps ba k to the beginning. And thisis why the kill ring is alled a ring, sin e by jumping ba k to the beginning,it is as if the list has no end! (And what is a ring, but an entity with noend?)B.2 yankAfter learning about rotate-yank-pointer, the ode for the yank fun -tion is almost easy. It has only one tri ky part, whi h is the omputation ofthe argument to be passed to rotate-yank-pointer.The ode looks like this:(defun yank (&optional arg)"Reinsert the last stret h of killed text.More pre isely, reinsert the stret h of killed text mostre ently killed OR yanked.With just C-U as argument, same but put point in front(and mark at end). With argument n, reinsert the nthmost re ently killed stret h of killed text.See also the ommand \\[yank-pop℄."

Page 268: An Introduction to Programming in Emacs Lisp

250 Appendix B: Handling the Kill Ring(intera tive "*P")(rotate-yank-pointer (if (listp arg) 0(if (eq arg '-) -1(1- arg))))(push-mark (point))(insert ( ar kill-ring-yank-pointer))(if ( onsp arg)(ex hange-point-and-mark)))Glan ing over this ode, we an understand the last few lines readilyenough. The mark is pushed, that is, remembered; then the �rst element(the ar) of what the kill-ring-yank-pointer points to is inserted; andthen, if the argument passed the fun tion is a ons, point and mark areex hanged so the point is put in the front of the inserted text rather than atthe end. This option is explained in the do umentation. The fun tion itselfis intera tive with "*P". This means it will not work on a read-only bu�er,and that the unpro essed pre�x argument is passed to the fun tion.Passing the argumentThe hard part of yank is understanding the omputation that determinesthe value of the argument passed to rotate-yank-pointer. Fortunately, itis not so diÆ ult as it looks at �rst sight.What happens is that the result of evaluating one or both of the ifexpressions will be a number and that number will be the argument passedto rotate-yank-pointer.Laid out with omments, the ode looks like this:(if (listp arg) ; if-part0 ; then-part(if (eq arg '-) ; else-part, inner if-1 ; inner if's then-part(1- arg)))) ; inner if's else-partThis ode onsists of two if expression, one the else-part of the other.The �rst or outer if expression tests whether the argument passed toyank is a list. Oddly enough, this will be true if yank is alled without anargument|be ause then it will be passed the value of nil for the optionalargument and an evaluation of (listp nil) returns true! So, if no argumentis passed to yank, the argument passed to rotate-yank-pointer inside ofyank is zero. This means the pointer is not moved and the �rst element towhi h kill-ring-yank-pointer points is inserted, as we expe t. Similarly,if the argument for yank is C-u, this will be read as a list, so again, a zero willbe passed to rotate-yank-pointer. (C-u produ es an unpro essed pre�xargument of (4), whi h is a list of one element.) At the same time, later inthe fun tion, this argument will be read as a ons so point will be put in the

Page 269: An Introduction to Programming in Emacs Lisp

Passing a negative argument 251front and mark at the end of the insertion. (The P argument to intera tiveis designed to provide these values for the ase when an optional argumentis not provided or when it is C-u.)The then-part of the outer if expression handles the ase when there isno argument or when it is C-u. The else-part handles the other situations.The else-part is itself another if expression.The inner if expression tests whether the argument is a minus sign. (Thisis done by pressing the hMETAi and - keys at the same time, or the hESCikey and then the - key). In this ase, the rotate-yank-pointer fun tionis passed -1 as an argument. This moves the kill-ring-yank-pointerba kwards, whi h is what is desired.If the true-or-false-test of the inner if expression is false (that is, if theargument is not a minus sign), the else-part of the expression is evaluated.This is the expression (1- arg). Be ause of the two if expressions, it willonly o ur when the argument is a positive number or when it is a negativenumber (not just a minus sign on its own). What (1- arg) does is de rementthe number and return it. (The 1- fun tion subtra ts one from its argument.)This means that if the argument to rotate-yank-pointer is 1, it is redu edto zero, whi h means the �rst element to whi h kill-ring-yank-pointerpoints is yanked ba k, as you would expe t.Passing a negative argumentFinally, the question arises, what happens if either the remainder fun -tion, %, or the nth dr fun tion is passed a negative argument, as they quitewell may?The answers an be found by a qui k test. When (% -1 5) is evaluated, anegative number is returned; and if nth dr is alled with a negative number,it returns the same value as if it were alled with a �rst argument of zero.This an be seen be evaluating the following ode.Here the `)' points to the result of evaluating the ode pre eding it.This was done by positioning the ursor after the ode and typing C-x C-e(eval-last-sexp) in the usual fashion. You an do this if you are readingthis in Info inside of GNU Ema s.(% -1 5)) -1(setq animals '( ats dogs elephants))) ( ats dogs elephants)(nth dr 1 animals)) (dogs elephants)(nth dr 0 animals)) ( ats dogs elephants)

Page 270: An Introduction to Programming in Emacs Lisp

252 Appendix B: Handling the Kill Ring(nth dr -1 animals)) ( ats dogs elephants)So, if a minus sign or a negative number is passed to yank, the kill-ring-yank-point is rotated ba kwards until it rea hes the beginning of thelist. Then it stays there. Unlike the other ase, when it jumps from the endof the list to the beginning of the list, making a ring, it stops. This makessense. You often want to get ba k to the most re ently lipped out pie e oftext, but you don't usually want to insert text from as many as thirty kill ommands ago. So you need to work through the ring to get to the end, butwon't y le around it inadvertently if you are trying to ome ba k to thebeginning.In identally, any number passed to yank with a minus sign pre edingit will be treated as �1. This is evidently a simpli� ation for writing theprogram. You don't need to jump ba k towards the beginning of the killring more than one pla e at a time and doing this is easier than writing afun tion to determine the magnitude of the number that follows the minussign.B.3 yank-popAfter understanding yank, the yank-pop fun tion is easy. Leaving outthe do umentation to save spa e, it looks like this:(defun yank-pop (arg)(intera tive "*p")(if (not (eq last- ommand 'yank))(error "Previous ommand was not a yank"))(setq this- ommand 'yank)(let ((before (< (point) (mark))))(delete-region (point) (mark))(rotate-yank-pointer arg)(set-mark (point))(insert ( ar kill-ring-yank-pointer))(if before (ex hange-point-and-mark))))The fun tion is intera tive with a small `p' so the pre�x argument ispro essed and passed to the fun tion. The ommand an only be used aftera previous yank; otherwise an error message is sent. This he k uses thevariable last- ommandwhi h is dis ussed elsewhere. (See Se tion 8.5, \ opy-region-as-kill", page 102.)The let lause sets the variable before to true or false depending whetherpoint is before or after mark and then the region between point and markis deleted. This is the region that was just inserted by the previous yankand it is this text that will be repla ed. Next the kill-ring-yank-pointeris rotated so that the previously inserted text is not reinserted yet again.Mark is set at the beginning of the pla e the new text will be inserted and

Page 271: An Introduction to Programming in Emacs Lisp

yank-pop 253then the �rst element to whi h kill-ring-yank-pointer points is inserted.This leaves point after the new text. If in the previous yank, point was leftbefore the inserted text, point and mark are now ex hanged so point is againleft in front of the newly inserted text. That is all there is to it!

Page 272: An Introduction to Programming in Emacs Lisp

254 Appendix B: Handling the Kill Ring

Page 273: An Introduction to Programming in Emacs Lisp

A Graph with Labelled Axes 255Appendix C A Graph with Labelled AxesPrinted axes help you understand a graph. They onvey s ale. In anearlier hapter (see Chapter 15, \Readying a Graph", page 203), we wrotethe ode to print the body of a graph. Here we write the ode for printingand labelling verti al and horizontal axes, along with the body itself.Sin e insertions �ll a bu�er to the right and below point, the new graphprinting fun tion should �rst print the Y or verti al axis, then the body ofthe graph, and �nally the X or horizontal axis. This sequen e lays out forus the ontents of the fun tion:1. Set up ode.2. Print Y axis.3. Print body of graph.4. Print X axis.Here is an example of how a �nished graph should look:10 - ** ** *** ***5 - * ******** *** ***********************************1 - ****************| | | |1 5 10 15In this graph, both the verti al and the horizontal axes are labelled withnumbers. However, in some graphs, the horizontal axis is time and wouldbe better labelled with months, like this:5 - ** ** ****************** **1 - **************| ^ |Jan June JanIndeed, with a little thought, we an easily ome up with a variety ofverti al and horizontal labelling s hemes. Our task ould be ome ompli- ated. But ompli ations breed onfusion. Rather than permit this, it isbetter hoose a simple labelling s heme for our �rst e�ort, and to modify orrepla e it later.

Page 274: An Introduction to Programming in Emacs Lisp

256 Appendix C: A Graph with Labelled AxesThese onsiderations suggest the following outline for the print-graphfun tion:(defun print-graph (numbers-list)"do umentation..."(let ((height ......))(print-Y-axis height ... )(graph-body-print numbers-list)(print-X-axis ... )))We an work on ea h part of the print-graph fun tion de�nition in turn.C.1 The print-graph VarlistIn writing the print-graph fun tion, the �rst task is to write the varlist inthe let expression. (We will leave aside for the moment any thoughts aboutmaking the fun tion intera tive or about the ontents of its do umentationstring.)The varlist should set several values. Clearly, the top of the label forthe verti al axis must be at least the height of the graph, whi h means thatwe must obtain this information here. Note that the print-graph-bodyfun tion also requires this information. There is no reason to al ulate theheight of the graph in two di�erent pla es, so we should hange print-graph-body from the way we de�ned it earlier to take advantage of the al ulation.Similarly, both the fun tion for printing the X axis labels and the print-graph-body fun tion need to learn the value of the width of ea h symbol.We an perform the al ulation here and hange the de�nition for print-graph-body from the way we de�ned it in the previous hapter.The length of the label for the horizontal axis must be at least as longas the graph. However, this information is used only in the fun tion thatprints the horizontal axis, so it does not need to be al ulated here.These thoughts lead us dire tly to the following form for the varlist inthe let for print-graph:(let ((height (apply 'max numbers-list)) ; First version.(symbol-width (length graph-blank)))As we shall see, this expression is not quite right.C.2 The print-Y-axis Fun tionThe job of the print-Y-axis fun tion is to print a label for the verti alaxis that looks like this:

Page 275: An Introduction to Programming in Emacs Lisp

Side Trip: Compute a Remainder 25710 -5 -1 -The fun tion should be passed the height of the graph, and then should onstru t and insert the appropriate numbers and marks.It is easy enough to see in the �gure what the Y axis label should looklike; but to say in words, and then to write a fun tion de�nition to do thejob is another matter. It is not quite true to say that we want a numberand a ti every �ve lines: there are only three lines between the `1' and the`5' (lines 2, 3, and 4), but four lines between the `5' and the `10' (lines 6, 7,8, and 9). It is better to say that we want a number and a ti mark on thebase line (number 1) and then that we want a number and a ti on the �fthline from the bottom and on every line that is a multiple of �ve.The next issue is what height the label should be? Suppose the maximumheight of tallest olumn of the graph is seven. Should the highest label onthe Y axis be `5 -', and should the graph sti k up above the label? Or shouldthe highest label be `7 -', and mark the peak of the graph? Or should thehighest label be 10 -, whi h is a multiple of �ve, and be higher than thetopmost value of the graph?The latter form is preferred. Most graphs are drawn within re tangleswhose sides are an integral number of steps long|5, 10, 15, and so on for astep distan e of �ve. But as soon as we de ide to use a step height for the ver-ti al axis, we dis over that the simple expression in the varlist for omputingthe height is wrong. The expression is (apply 'max numbers-list). Thisreturns the pre ise height, not the maximum height plus whatever is ne es-sary to round up to the nearest multiple of �ve. A more omplex expressionis required.As usual in ases like this, a omplex problem be omes simpler if it isdivided into several smaller problems.First, onsider the ase when the highest value of the graph is an integralmultiple of �ve|when it is 5, 10, 15 ,or some higher multiple of �ve. We an use this value as the Y axis height.A fairly simply way to determine whether a number is a multiple of �veis to divide it by �ve and see if the division results in a remainder. If there isno remainder, the number is a multiple of �ve. Thus, seven divided by �vehas a remainder of two, and seven is not an integral multiple of �ve. Put inslightly di�erent language, more reminis ent of the lassroom, �ve goes into

Page 276: An Introduction to Programming in Emacs Lisp

258 Appendix C: A Graph with Labelled Axesseven on e, with a remainder of two. However, �ve goes into ten twi e, withno remainder: ten is an integral multiple of �ve.C.2.1 Side Trip: Compute a RemainderIn Lisp, the fun tion for omputing a remainder is %. The fun tion returnsthe remainder of its �rst argument divided by its se ond argument. Asit happens, % is a fun tion in Ema s Lisp that you annot dis over usingapropos: you �nd nothing if you type M-x apropos hRETi remainder hRETi.The only way to learn of the existen e of % is to read about it in a booksu h as this or in the Ema s Lisp sour es. The % fun tion is used in the ode for rotate-yank-pointer, whi h is des ribed in an appendix. (SeeSe tion B.1.1, \The Body of rotate-yank-pointer", page 244.)You an try the % fun tion by evaluating the following two expressions:(% 7 5)(% 10 5)The �rst expression returns 2 and the se ond expression returns 0.To test whether the returned value is zero or some other number, we anuse the zerop fun tion. This fun tion returns t if its argument, whi h mustbe a number, is zero.(zerop (% 7 5))) nil(zerop (% 10 5))) tThus, the following expression will return t if the height of the graph isevenly divisible by �ve:(zerop (% height 5))(The value of height, of ourse, an be found from (apply 'max numbers-list).)On the other hand, if the value of height is not a multiple of �ve, we wantto reset the value to the next higher multiple of �ve. This is straightforwardarithmeti using fun tions with whi h we are already familiar. First, wedivide the value of height by �ve to determine how many times �ve goesinto the number. Thus, �ve goes into twelve twi e. If we add one to thisquotient and multiply by �ve, we will obtain the value of the next multipleof �ve that is larger than the height. Five goes into twelve twi e. Add oneto two, and multiply by �ve; the result is �fteen, whi h is the next multipleof �ve that is higher than twelve. The Lisp expression for this is:(* (1+ (/ height 5)) 5)For example, if you evaluate the following, the result is 15:(* (1+ (/ 12 5)) 5)

Page 277: An Introduction to Programming in Emacs Lisp

Constru t a Y Axis Element 259All through this dis ussion, we have been using `�ve' as the value forspa ing labels on the Y axis; but we may want to use some other value. Forgenerality, we should repla e `�ve' with a variable to whi h we an assigna value. The best name I an think of for this variable is Y-axis-label-spa ing.Using this term, and an if expression, we produ e the following:(if (zerop (% height Y-axis-label-spa ing))height;; else(* (1+ (/ height Y-axis-label-spa ing))Y-axis-label-spa ing))This expression returns the value of height itself if the height is an evenmultiple of the value of the Y-axis-label-spa ing or else it omputes andreturns a value of height that is equal to the next higher multiple of thevalue of the Y-axis-label-spa ing.We an now in lude this expression in the let expression of the print-graph fun tion (after �rst setting the value of Y-axis-label-spa ing):(defvar Y-axis-label-spa ing 5"Number of lines from one Y axis label to next.")...(let* ((height (apply 'max numbers-list))(height-of-top-line(if (zerop (% height Y-axis-label-spa ing))height;; else(* (1+ (/ height Y-axis-label-spa ing))Y-axis-label-spa ing)))(symbol-width (length graph-blank))))...(Note use of the let* fun tion: the initial value of height is omputed on eby the (apply 'max numbers-list) expression and then the resulting valueof height is used to ompute its �nal value. See \The let* expression",page 156, for more about let*.)C.2.2 Constru t a Y Axis ElementWhen we print the verti al axis, we want to insert strings su h as `5 -'and `10 - ' every �ve lines. Moreover, we want the numbers and dashes toline up, so shorter numbers must be padded with leading spa es. If someof the strings use two digit numbers, the strings with single digit numbersmust in lude a leading blank spa e before the number.To �gure out the length of the number, the length fun tion is used. Butthe length fun tion works only with a string, not with a number. So the

Page 278: An Introduction to Programming in Emacs Lisp

260 Appendix C: A Graph with Labelled Axesnumber has to be onverted from being a number to being a string. This isdone with the number-to-string fun tion. For example,(length (number-to-string 35))) 2(length (number-to-string 100))) 3(number-to-string is also alled int-to-string; you will see this alterna-tive name in various sour es.)In addition, in ea h label, ea h number is followed by a string su h as` - ', whi h we will all the Y-axis-ti marker. This variable is de�nedwith defvar:(defvar Y-axis-ti " - ""String that follows number in a Y axis label.")The length of the Y label is the sum of the length of the Y axis ti markand the length of the number of the top of the graph.(length ( on at (number-to-string height) Y-axis-ti )))This value will be al ulated by the print-graph fun tion in its varlist asfull-Y-label-width and passed on. (Note that we did not think to in ludethis in the varlist when we �rst proposed it.)To make a omplete verti al axis label, a ti mark is on atenated witha number; and the two together may be pre eded by one or more spa esdepending on how long the number is. The label onsists of three parts:the (optional) leading spa es, the number, and the ti mark. The fun tionis passed the value of the number for the spe i� row, and the value of thewidth of the top line, whi h is al ulated (just on e) by print-graph.(defun Y-axis-element (number full-Y-label-width)"Constru t a NUMBERed label element.A numbered element looks like this ` 5 - ',and is padded as needed so all line up withthe element for the largest number."(let* ((leading-spa es(- full-Y-label-width(length( on at (number-to-string number)Y-axis-ti )))))( on at(make-string leading-spa es ? )(number-to-string number)Y-axis-ti )))The Y-axis-element fun tion on atenates together the leading spa es,if any; the number, as a string; and the ti mark.

Page 279: An Introduction to Programming in Emacs Lisp

The Not Quite Final Version of print-Y-axis 261To �gure out how many leading spa es the label will need, the fun tionsubtra ts the a tual length of the label|the length of the number plus thelength of the ti mark|from the desired label width.Blank spa es are inserted using the make-string fun tion. This fun tiontakes two arguments: the �rst tells it how long the string will be and these ond is a symbol for the hara ter to insert, in a spe ial format. Theformat is a question mark followed by a blank spa e, like this, `? '. Seese tion \Chara ter Type" in The GNU Ema s Lisp Referen e Manual, for ades ription of the syntax for hara ters.The number-to-string fun tion is used in the on atenation expression,to onvert the number to a string that is on atenated with the leadingspa es and the ti mark.C.2.3 Create a Y Axis ColumnThe pre eding fun tions provide all the tools needed to onstru t a fun -tion that generates a list of numbered and blank strings to insert as the labelfor the verti al axis:(defun Y-axis- olumn (height width-of-label)"Constru t list of Y axis labels and blank strings.For HEIGHT of line above base and WIDTH-OF-LABEL."(let (Y-axis)(while (> height 1)(if (zerop (% height Y-axis-label-spa ing));; Insert label.(setq Y-axis( ons(Y-axis-element height width-of-label)Y-axis));; Else, insert blanks.(setq Y-axis( ons(make-string width-of-label ? )Y-axis)))(setq height (1- height)));; Insert base line.(setq Y-axis( ons (Y-axis-element 1 width-of-label) Y-axis))(nreverse Y-axis)))In this fun tion, we start with the value of height and repetitively sub-tra t one from its value. After ea h subtra tion, we test to see whetherthe value is an integral multiple of the Y-axis-label-spa ing. If it is,we onstru t a numbered label using the Y-axis-element fun tion; if not,

Page 280: An Introduction to Programming in Emacs Lisp

262 Appendix C: A Graph with Labelled Axeswe onstru t a blank label using the make-string fun tion. The base line onsists of the number one followed by a ti mark.C.2.4 The Not Quite Final Version of print-Y-axisThe list onstru ted by the Y-axis- olumn fun tion is passed to theprint-Y-axis fun tion, whi h inserts the list as a olumn.(defun print-Y-axis (height full-Y-label-width)"Insert Y axis using HEIGHT and FULL-Y-LABEL-WIDTH.Height must be the maximum height of the graph.Full width is the width of the highest label element.";; Value of height and full-Y-label-width;; are passed by `print-graph'.(let ((start (point)))(insert-re tangle(Y-axis- olumn height full-Y-label-width));; Pla e point ready for inserting graph.(goto- har start);; Move point forward by value of full-Y-label-width(forward- har full-Y-label-width)))The print-Y-axis uses the insert-re tangle fun tion to insert the Yaxis labels reated by the Y-axis- olumn fun tion. In addition, it pla espoint at the orre t position for printing the body of the graph.You an test print-Y-axis:1. InstallY-axis-label-spa ingY-axis-ti Y-axis-elementY-axis- olumnprint-Y-axis2. Copy the following expression:(print-Y-axis 12 5)3. Swit h to the `*s rat h*' bu�er and pla e the ursor where you wantthe axis labels to start.4. Type M-: (eval-expression).5. Yank the graph-body-print expression into the minibu�er with C-y(yank).6. Press hRETi to evaluate the expression.Ema s will print labels verti ally, the top one being `10 - '. (The print-graph fun tion will pass the value of height-of-top-line, whi h in this ase would end up as 15.)

Page 281: An Introduction to Programming in Emacs Lisp

X Axis Ti Marks 263C.3 The print-X-axis Fun tionX axis labels are mu h like Y axis labels, ex ept that the ti s are on aline above the numbers. Labels should look like this:| | | |1 5 10 15The �rst ti is under the �rst olumn of the graph and is pre eded byseveral blank spa es. These spa es provide room in rows above for the Yaxis labels. The se ond, third, fourth, and subsequent ti s are all spa edequally, a ording to the value of X-axis-label-spa ing.The se ond row of the X axis onsists of numbers, pre eded by severalblank spa es and also separated a ording to the value of the variable X-axis-label-spa ing.The value of the variable X-axis-label-spa ing should itself be mea-sured in units of symbol-width, sin e you may want to hange the widthof the symbols that you are using to print the body of the graph without hanging the ways the graph is labelled.The print-X-axis fun tion is onstru ted in more or less the same fash-ion as the print-Y-axis fun tion ex ept that it has two lines: the line ofti marks and the numbers. We will write a separate fun tion to print ea hline and then ombine them within the print-X-axis fun tion.This is a three step pro ess:1. Write a fun tion to print the X axis ti marks, print-X-axis-ti -line.2. Write a fun tion to print the X numbers, print-X-axis-numbered-line.3. Write a fun tion to print both lines, the print-X-axis fun tion, usingprint-X-axis-ti -line and print-X-axis-numbered-line.C.3.1 X Axis Ti MarksThe �rst fun tion should print the X axis ti marks. We must spe ify theti marks themselves and their spa ing:(defvar X-axis-label-spa ing(if (boundp 'graph-blank)(* 5 (length graph-blank)) 5)"Number of units from one X axis label to next.")(Note that the value of graph-blank is set by another defvar. Theboundp predi ate he ks whether it has already been set; boundp returnsnil if it has not. If graph-blank were unbound and we did not usethis onditional onstru tion, in GNU Ema s 21, we would enter the de-bugger and see an error message saying `Debugger entered--Lisp error:(void-variable graph-blank)'.)

Page 282: An Introduction to Programming in Emacs Lisp

264 Appendix C: A Graph with Labelled AxesHere is the defvar for X-axis-ti -symbol:(defvar X-axis-ti -symbol "|""String to insert to point to a olumn in X axis.")The goal is to make a line that looks like this:| | | |The �rst ti is indented so that it is under the �rst olumn, whi h isindented to provide spa e for the Y axis labels.A ti element onsists of the blank spa es that stret h from one ti to thenext plus a ti symbol. The number of blanks is determined by the width ofthe ti symbol and the X-axis-label-spa ing.The ode looks like this:;;; X-axis-ti -element...( on at(make-string;; Make a string of blanks.(- (* symbol-width X-axis-label-spa ing)(length X-axis-ti -symbol))? );; Con atenate blanks with ti symbol.X-axis-ti -symbol)...Next, we determine how many blanks are needed to indent the �rst ti mark to the �rst olumn of the graph. This uses the value of full-Y-label-width passed it by the print-graph fun tion.The ode to make X-axis-leading-spa es looks like this:;; X-axis-leading-spa es...(make-string full-Y-label-width ? )...We also need to determine the length of the horizontal axis, whi h is thelength of the numbers list, and the number of ti s in the horizontal axis:;; X-length...(length numbers-list);; ti -width...(* symbol-width X-axis-label-spa ing)

Page 283: An Introduction to Programming in Emacs Lisp

X Axis Ti Marks 265;; number-of-X-ti s(if (zerop (% (X-length ti -width)))(/ (X-length ti -width))(1+ (/ (X-length ti -width))))All this leads us dire tly to the fun tion for printing the X axis ti line:(defun print-X-axis-ti -line(number-of-X-ti s X-axis-leading-spa es X-axis-ti -element)"Print ti s for X axis."(insert X-axis-leading-spa es)(insert X-axis-ti -symbol) ; Under �rst olumn.;; Insert se ond ti in the right spot.(insert ( on at(make-string(- (* symbol-width X-axis-label-spa ing);; Insert white spa e up to se ond ti symbol.(* 2 (length X-axis-ti -symbol)))? )X-axis-ti -symbol));; Insert remaining ti s.(while (> number-of-X-ti s 1)(insert X-axis-ti -element)(setq number-of-X-ti s (1- number-of-X-ti s))))The line of numbers is equally straightforward:First, we reate a numbered element with blank spa es before ea h num-ber: (defun X-axis-element (number)"Constru t a numbered X axis element."(let ((leading-spa es(- (* symbol-width X-axis-label-spa ing)(length (number-to-string number)))))( on at (make-string leading-spa es ? )(number-to-string number))))Next, we reate the fun tion to print the numbered line, starting withthe number \1" under the �rst olumn:(defun print-X-axis-numbered-line(number-of-X-ti s X-axis-leading-spa es)"Print line of X-axis numbers"(let ((number X-axis-label-spa ing))(insert X-axis-leading-spa es)(insert "1")

Page 284: An Introduction to Programming in Emacs Lisp

266 Appendix C: A Graph with Labelled Axes(insert ( on at(make-string;; Insert white spa e up to next number.(- (* symbol-width X-axis-label-spa ing) 2)? )(number-to-string number)));; Insert remaining numbers.(setq number (+ number X-axis-label-spa ing))(while (> number-of-X-ti s 1)(insert (X-axis-element number))(setq number (+ number X-axis-label-spa ing))(setq number-of-X-ti s (1- number-of-X-ti s)))))Finally, we need to write the print-X-axis that uses print-X-axis-ti -line and print-X-axis-numbered-line.The fun tion must determine the lo al values of the variables used by bothprint-X-axis-ti -line and print-X-axis-numbered-line, and then itmust all them. Also, it must print the arriage return that separates thetwo lines.The fun tion onsists of a varlist that spe i�es �ve lo al variables, and alls to ea h of the two line printing fun tions:(defun print-X-axis (numbers-list)"Print X axis labels to length of NUMBERS-LIST."(let* ((leading-spa es(make-string full-Y-label-width ? ));; symbol-width is provided by graph-body-print(ti -width (* symbol-width X-axis-label-spa ing))(X-length (length numbers-list))(X-ti ( on at(make-string;; Make a string of blanks.(- (* symbol-width X-axis-label-spa ing)(length X-axis-ti -symbol))? );; Con atenate blanks with ti symbol.X-axis-ti -symbol))(ti -number(if (zerop (% X-length ti -width))(/ X-length ti -width)(1+ (/ X-length ti -width)))))(print-X-axis-ti -line ti -number leading-spa es X-ti )(insert "\n")(print-X-axis-numbered-line ti -number leading-spa es)))

Page 285: An Introduction to Programming in Emacs Lisp

Printing the Whole Graph 267You an test print-X-axis:1. Install X-axis-ti -symbol, X-axis-label-spa ing, print-X-axis-ti -line, as well as X-axis-element, print-X-axis-numbered-line,and print-X-axis.2. Copy the following expression:(progn(let ((full-Y-label-width 5)(symbol-width 1))(print-X-axis'(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16))))3. Swit h to the `*s rat h*' bu�er and pla e the ursor where you wantthe axis labels to start.4. Type M-: (eval-expression).5. Yank the test expression into the minibu�er with C-y (yank).6. Press hRETi to evaluate the expression.Ema s will print the horizontal axis like this:| | | | |1 5 10 15 20C.4 Printing the Whole GraphNow we are nearly ready to print the whole graph.The fun tion to print the graph with the proper labels follows the out-line we reated earlier (see Appendix C, \A Graph with Labelled Axes",page 255), but with additions.Here is the outline:(defun print-graph (numbers-list)"do umentation..."(let ((height ......))(print-Y-axis height ... )(graph-body-print numbers-list)(print-X-axis ... )))The �nal version is di�erent from what we planned in two ways: �rst, it ontains additional values al ulated on e in the varlist; se ond, it arriesan option to spe ify the labels' in rement per row. This latter feature turnsout to be essential; otherwise, a graph may have more rows than �t on adisplay or on a sheet of paper.

Page 286: An Introduction to Programming in Emacs Lisp

268 Appendix C: A Graph with Labelled AxesThis new feature requires a hange to the Y-axis- olumn fun tion, toadd verti al-step to it. The fun tion looks like this:;;; Final version.(defun Y-axis- olumn(height width-of-label &optional verti al-step)"Constru t list of labels for Y axis.HEIGHT is maximum height of graph.WIDTH-OF-LABEL is maximum width of label.VERTICAL-STEP, an option, is a positive integerthat spe ifies how mu h a Y axis label in rementsfor ea h line. For example, a step of 5 meansthat ea h line is five units of the graph."(let (Y-axis(number-per-line (or verti al-step 1)))(while (> height 1)(if (zerop (% height Y-axis-label-spa ing));; Insert label.(setq Y-axis( ons(Y-axis-element(* height number-per-line)width-of-label)Y-axis));; Else, insert blanks.(setq Y-axis( ons(make-string width-of-label ? )Y-axis)))(setq height (1- height)));; Insert base line.(setq Y-axis ( ons (Y-axis-element(or verti al-step 1)width-of-label)Y-axis))(nreverse Y-axis)))The values for the maximum height of graph and the width of a symbolare omputed by print-graph in its let expression; so graph-body-printmust be hanged to a ept them.

Page 287: An Introduction to Programming in Emacs Lisp

Printing the Whole Graph 269;;; Final version.(defun graph-body-print (numbers-list height symbol-width)"Print a bar graph of the NUMBERS-LIST.The numbers-list onsists of the Y-axis values.HEIGHT is maximum height of graph.SYMBOL-WIDTH is number of ea h olumn."(let (from-position)(while numbers-list(setq from-position (point))(insert-re tangle( olumn-of-graph height ( ar numbers-list)))(goto- har from-position)(forward- har symbol-width);; Draw graph olumn by olumn.(sit-for 0)(setq numbers-list ( dr numbers-list)));; Pla e point for X axis labels.(forward-line height)(insert "\n")))Finally, the ode for the print-graph fun tion:;;; Final version.(defun print-graph(numbers-list &optional verti al-step)"Print labelled bar graph of the NUMBERS-LIST.The numbers-list onsists of the Y-axis values.Optionally, VERTICAL-STEP, a positive integer,spe ifies how mu h a Y axis label in rements forea h line. For example, a step of 5 means thatea h row is five units."(let* ((symbol-width (length graph-blank));; height is both the largest number;; and the number with the most digits.(height (apply 'max numbers-list))(height-of-top-line(if (zerop (% height Y-axis-label-spa ing))height;; else(* (1+ (/ height Y-axis-label-spa ing))Y-axis-label-spa ing)))(verti al-step (or verti al-step 1))(full-Y-label-width(length

Page 288: An Introduction to Programming in Emacs Lisp

270 Appendix C: A Graph with Labelled Axes( on at(number-to-string(* height-of-top-line verti al-step))Y-axis-ti ))))(print-Y-axisheight-of-top-line full-Y-label-width verti al-step)(graph-body-printnumbers-list height-of-top-line symbol-width)(print-X-axis numbers-list)))C.4.1 Testing print-graphWe an test the print-graph fun tion with a short list of numbers:1. Install the �nal versions of Y-axis- olumn, graph-body-print, andprint-graph (in addition to the rest of the ode.)2. Copy the following expression:(print-graph '(3 2 5 6 7 5 3 4 6 4 3 2 1))3. Swit h to the `*s rat h*' bu�er and pla e the ursor where you wantthe axis labels to start.4. Type M-: (eval-expression).5. Yank the test expression into the minibu�er with C-y (yank).6. Press hRETi to evaluate the expression.Ema s will print a graph that looks like this:10 - *** *5 - **** ***** **** *********************1 - *************| | | |1 5 10 15On the other hand, if you pass print-graph a verti al-step value of2, by evaluating this expression:(print-graph '(3 2 5 6 7 5 3 4 6 4 3 2 1) 2)

Page 289: An Introduction to Programming in Emacs Lisp

Graphing Numbers of Words and Symbols 271The graph looks like this:20 - *** *10 - **** ***** **** *********************2 - *************| | | |1 5 10 15(A question: is the `2' on the bottom of the verti al axis a bug or a feature?If you think it is a bug, and should be a `1' instead, (or even a `0'), you anmodify the sour es.)C.4.2 Graphing Numbers of Words and SymbolsNow for the graph for whi h all this ode was written: a graph that showshow many fun tion de�nitions ontain fewer than 10 words and symbols, howmany ontain between 10 and 19 words and symbols, how many ontainbetween 20 and 29 words and symbols, and so on.This is a multi-step pro ess. First make sure you have loaded all therequisite ode.It is a good idea to reset the value of top-of-ranges in ase you haveset it to some di�erent value. You an evaluate the following:(setq top-of-ranges'(10 20 30 40 5060 70 80 90 100110 120 130 140 150160 170 180 190 200210 220 230 240 250260 270 280 290 300)Next reate a list of the number of words and symbols in ea h range.

Page 290: An Introduction to Programming in Emacs Lisp

272 Appendix C: A Graph with Labelled AxesEvaluate the following:(setq list-for-graph(defuns-per-range(sort(re ursive-lengths-list-many-files(dire tory-files "/usr/lo al/ema s/lisp"t ".+el$"))'<)top-of-ranges))On my ma hine, this takes about an hour. It looks though 303 Lisp �les inmy opy of Ema s version 19.23. After all that omputing, the list-for-graph has this value:(537 1027 955 785 594 483 349 292 224 199 166 120 116 9990 80 67 48 52 45 41 33 28 26 25 20 12 28 11 13 220)This means that my opy of Ema s has 537 fun tion de�nitions with fewerthan 10 words or symbols in them, 1,027 fun tion de�nitions with 10 to 19words or symbols in them, 955 fun tion de�nitions with 20 to 29 words orsymbols in them, and so on.Clearly, just by looking at this list we an see that most fun tion de�ni-tions ontain ten to thirty words and symbols.Now for printing. We do not want to print a graph that is 1,030 lineshigh . . . Instead, we should print a graph that is fewer than twenty-�velines high. A graph that height an be displayed on almost any monitor,and easily printed on a sheet of paper.This means that ea h value in list-for-graph must be redu ed to one-�ftieth its present value.Here is a short fun tion to do just that, using two fun tions we have notyet seen, map ar and lambda.(defun one-fiftieth (full-range)"Return list, ea h number one-fiftieth of previous."(map ar '(lambda (arg) (/ arg 50)) full-range))C.4.3 A lambda Expression: Useful Anonymitylambda is the symbol for an anonymous fun tion, a fun tion without aname. Every time you use an anonymous fun tion, you need to in lude itswhole body.

Page 291: An Introduction to Programming in Emacs Lisp

The map ar Fun tion 273Thus,(lambda (arg) (/ arg 50))is a fun tion de�nition that says `return the value resulting from dividingwhatever is passed to me as arg by 50'.Earlier, for example, we had a fun tion multiply-by-seven; it multipliedits argument by 7. This fun tion is similar, ex ept it divides its argument by50; and, it has no name. The anonymous equivalent of multiply-by-sevenis: (lambda (number) (* 7 number))(See Se tion 3.1, \The defun Spe ial Form", page 29.)If we want to multiply 3 by 7, we an write:(multiply-by-seven 3)

function argumentThis expression returns 21.Similarly, we an write:((lambda (number) (* 7 number)) 3)

anonymous function argumentIf we want to divide 100 by 50, we an write:((lambda (arg) (/ arg 50)) 100)

anonymous function argumentThis expression returns 2. The 100 is passed to the fun tion, whi h dividesthat number by 50.See se tion \Lambda Expressions" in The GNU Ema s Lisp Referen eManual, for more about lambda. Lisp and lambda expressions derive fromthe Lambda Cal ulus.

Page 292: An Introduction to Programming in Emacs Lisp

274 Appendix C: A Graph with Labelled AxesC.4.4 The map ar Fun tionmap ar is a fun tion that alls its �rst argument with ea h element of itsse ond argument, in turn. The se ond argument must be a sequen e.The `map' part of the name omes from the mathemati al phrase, `map-ping over a domain', meaning to apply a fun tion to ea h of the elements ina domain. The mathemati al phrase is based on the metaphor of a surveyorwalking, one step at a time, over an area he is mapping. And ` ar', of ourse, omes from the Lisp notion of the �rst of a list.For example,(map ar '1+ '(2 4 6))) (3 5 7)The fun tion 1+ whi h adds one to its argument, is exe uted on ea h elementof the list, and a new list is returned.Contrast this with apply, whi h applies its �rst argument to all the re-maining. (See Chapter 15, \Readying a Graph", page 203, for a explanationof apply.)In the de�nition of one-fiftieth, the �rst argument is the anonymousfun tion:(lambda (arg) (/ arg 50))and the se ond argument is full-range, whi h will be bound to list-for-graph.The whole expression looks like this:(map ar '(lambda (arg) (/ arg 50)) full-range))See se tion \Mapping Fun tions" in The GNU Ema s Lisp Referen eManual, for more about map ar.Using the one-fiftieth fun tion, we an generate a list in whi h ea helement is one-�ftieth the size of the orresponding element in list-for-graph.(setq fiftieth-list-for-graph(one-fiftieth list-for-graph))The resulting list looks like this:(10 20 19 15 11 9 6 5 4 3 3 2 21 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 4)This, we are almost ready to print! (We also noti e the loss of information:many of the higher ranges are 0, meaning that fewer than 50 defuns hadthat many words or symbols|but not ne essarily meaning that none hadthat many words or symbols.)C.4.5 Another Bug . . . Most InsidiousI said `almost ready to print' ! Of ourse, there is a bug in the print-graph fun tion . . . It has a verti al-step option, but not a horizontal-

Page 293: An Introduction to Programming in Emacs Lisp

Another Bug . . . Most Insidious 275step option. The top-of-range s ale goes from 10 to 300 by tens. But theprint-graph fun tion will print only by ones.This is a lassi example of what some onsider the most insidious typeof bug, the bug of omission. This is not the kind of bug you an �nd bystudying the ode, for it is not in the ode; it is an omitted feature. Yourbest a tions are to try your program early and often; and try to arrange,as mu h as you an, to write ode that is easy to understand and easy to hange. Try to be aware, whenever you an, that whatever you have written,will be rewritten, if not soon, eventually. A hard maxim to follow.It is the print-X-axis-numbered-line fun tion that needs the work;and then the print-X-axis and the print-graph fun tions need to beadapted. Not mu h needs to be done; there is one ni ety: the numbersought to line up under the ti marks. This takes a little thought.Here is the orre ted print-X-axis-numbered-line:(defun print-X-axis-numbered-line(number-of-X-ti s X-axis-leading-spa es&optional horizontal-step)"Print line of X-axis numbers"(let ((number X-axis-label-spa ing)(horizontal-step (or horizontal-step 1)))(insert X-axis-leading-spa es);; Delete extra leading spa es.(delete- har(- (1-(length (number-to-string horizontal-step)))))(insert ( on at(make-string;; Insert white spa e.(- (* symbol-widthX-axis-label-spa ing)(1-(length(number-to-string horizontal-step)))2)? )(number-to-string(* number horizontal-step))));; Insert remaining numbers.(setq number (+ number X-axis-label-spa ing))(while (> number-of-X-ti s 1)(insert (X-axis-element(* number horizontal-step)))(setq number (+ number X-axis-label-spa ing))(setq number-of-X-ti s (1- number-of-X-ti s)))))

Page 294: An Introduction to Programming in Emacs Lisp

276 Appendix C: A Graph with Labelled AxesIf you are reading this in Info, you an see the new versions of print-X-axis print-graph and evaluate them. If you are reading this in a printedbook, you an see the hanged lines here (the full text is too mu h to print).(defun print-X-axis (numbers-list horizontal-step)...(print-X-axis-numbered-lineti -number leading-spa es horizontal-step))(defun print-graph(numbers-list&optional verti al-step horizontal-step)...(print-X-axis numbers-list horizontal-step))

Page 295: An Introduction to Programming in Emacs Lisp

The Printed Graph 277C.4.6 The Printed GraphWhen made and installed, you an all the print-graph ommand likethis:(print-graph fiftieth-list-for-graph 50 10)Here is the graph:1000 - *********750 - ****************500 - ******************************250 - ***************** ************ ************** *50 - ***************** * *| | | | | | | |10 50 100 150 200 250 300 350The largest group of fun tions ontain 10 { 19 words and symbols ea h.

Page 296: An Introduction to Programming in Emacs Lisp

278 Appendix C: A Graph with Labelled Axes

Page 297: An Introduction to Programming in Emacs Lisp

GNU Free Do umentation Li ense 279Appendix D GNU Free Do umentationLi enseVersion 1.1, Mar h 2000Copyright 2000 Free Software Foundation, In .59 Temple Pla e, Suite 330, Boston, MA 02111-1307, USAEveryone is permitted to opy and distribute verbatim opiesof this li ense do ument, but hanging it is not allowed.0. PREAMBLEThe purpose of this Li ense is to make a manual, textbook, or otherwritten do ument free in the sense of freedom: to assure everyone thee�e tive freedom to opy and redistribute it, with or without modifyingit, either ommer ially or non ommer ially. Se ondarily, this Li ensepreserves for the author and publisher a way to get redit for theirwork, while not being onsidered responsible for modi� ations made byothers.This Li ense is a kind of \ opyleft", whi h means that derivative worksof the do ument must themselves be free in the same sense. It om-plements the GNU General Publi Li ense, whi h is a opyleft li ensedesigned for free software.We have designed this Li ense in order to use it for manuals for free soft-ware, be ause free software needs free do umentation: a free programshould ome with manuals providing the same freedoms that the soft-ware does. But this Li ense is not limited to software manuals; it anbe used for any textual work, regardless of subje t matter or whether itis published as a printed book. We re ommend this Li ense prin ipallyfor works whose purpose is instru tion or referen e.1. APPLICABILITY AND DEFINITIONSThis Li ense applies to any manual or other work that ontains a noti epla ed by the opyright holder saying it an be distributed under theterms of this Li ense. The \Do ument", below, refers to any su h man-ual or work. Any member of the publi is a li ensee, and is addressedas \you".A \Modi�ed Version" of the Do ument means any work ontaining theDo ument or a portion of it, either opied verbatim, or with modi� a-tions and/or translated into another language.A \Se ondary Se tion" is a named appendix or a front-matter se tionof the Do ument that deals ex lusively with the relationship of the pub-lishers or authors of the Do ument to the Do ument's overall subje t(or to related matters) and ontains nothing that ould fall dire tlywithin that overall subje t. (For example, if the Do ument is in parta textbook of mathemati s, a Se ondary Se tion may not explain any

Page 298: An Introduction to Programming in Emacs Lisp

280 Appendix D: GNU Free Do umentation Li ensemathemati s.) The relationship ould be a matter of histori al onne -tion with the subje t or with related matters, or of legal, ommer ial,philosophi al, ethi al or politi al position regarding them.The \Invariant Se tions" are ertain Se ondary Se tions whose titles aredesignated, as being those of Invariant Se tions, in the noti e that saysthat the Do ument is released under this Li ense.The \Cover Texts" are ertain short passages of text that are listed, asFront-Cover Texts or Ba k-Cover Texts, in the noti e that says that theDo ument is released under this Li ense.A \Transparent" opy of the Do ument means a ma hine-readable opy,represented in a format whose spe i� ation is available to the generalpubli , whose ontents an be viewed and edited dire tly and straight-forwardly with generi text editors or (for images omposed of pixels)generi paint programs or (for drawings) some widely available drawingeditor, and that is suitable for input to text formatters or for automati translation to a variety of formats suitable for input to text formatters.A opy made in an otherwise Transparent �le format whose markuphas been designed to thwart or dis ourage subsequent modi� ation byreaders is not Transparent. A opy that is not \Transparent" is alled\Opaque".Examples of suitable formats for Transparent opies in lude plain as iiwithout markup, Texinfo input format, LaTEX input format, sgmlor xml using a publi ly available dtd, and standard- onforming sim-ple html designed for human modi� ation. Opaque formats in ludePostS ript, pdf, proprietary formats that an be read and edited onlyby proprietary word pro essors, sgml or xml for whi h the dtd and/orpro essing tools are not generally available, and the ma hine-generatedhtml produ ed by some word pro essors for output purposes only.The \Title Page" means, for a printed book, the title page itself, plussu h following pages as are needed to hold, legibly, the material thisLi ense requires to appear in the title page. For works in formats whi hdo not have any title page as su h, \Title Page" means the text near themost prominent appearan e of the work's title, pre eding the beginningof the body of the text.2. VERBATIM COPYINGYou may opy and distribute the Do ument in any medium, either om-mer ially or non ommer ially, provided that this Li ense, the opyrightnoti es, and the li ense noti e saying this Li ense applies to the Do u-ment are reprodu ed in all opies, and that you add no other onditionswhatsoever to those of this Li ense. You may not use te hni al mea-sures to obstru t or ontrol the reading or further opying of the opiesyou make or distribute. However, you may a ept ompensation in ex- hange for opies. If you distribute a large enough number of opies youmust also follow the onditions in se tion 3.

Page 299: An Introduction to Programming in Emacs Lisp

GNU Free Do umentation Li ense 281You may also lend opies, under the same onditions stated above, andyou may publi ly display opies.3. COPYING IN QUANTITYIf you publish printed opies of the Do ument numbering more than100, and the Do ument's li ense noti e requires Cover Texts, you musten lose the opies in overs that arry, learly and legibly, all these CoverTexts: Front-Cover Texts on the front over, and Ba k-Cover Texts onthe ba k over. Both overs must also learly and legibly identify you asthe publisher of these opies. The front over must present the full titlewith all words of the title equally prominent and visible. You may addother material on the overs in addition. Copying with hanges limitedto the overs, as long as they preserve the title of the Do ument andsatisfy these onditions, an be treated as verbatim opying in otherrespe ts.If the required texts for either over are too voluminous to �t legibly,you should put the �rst ones listed (as many as �t reasonably) on thea tual over, and ontinue the rest onto adja ent pages.If you publish or distribute Opaque opies of the Do ument numberingmore than 100, you must either in lude a ma hine-readable Transpar-ent opy along with ea h Opaque opy, or state in or with ea h Opaque opy a publi ly-a essible omputer-network lo ation ontaining a om-plete Transparent opy of the Do ument, free of added material, whi hthe general network-using publi has a ess to download anonymouslyat no harge using publi -standard network proto ols. If you use thelatter option, you must take reasonably prudent steps, when you begindistribution of Opaque opies in quantity, to ensure that this Transpar-ent opy will remain thus a essible at the stated lo ation until at leastone year after the last time you distribute an Opaque opy (dire tly orthrough your agents or retailers) of that edition to the publi .It is requested, but not required, that you onta t the authors of theDo ument well before redistributing any large number of opies, to givethem a han e to provide you with an updated version of the Do ument.4. MODIFICATIONSYou may opy and distribute a Modi�ed Version of the Do ument underthe onditions of se tions 2 and 3 above, provided that you releasethe Modi�ed Version under pre isely this Li ense, with the Modi�edVersion �lling the role of the Do ument, thus li ensing distribution andmodi� ation of the Modi�ed Version to whoever possesses a opy of it.In addition, you must do these things in the Modi�ed Version:A. Use in the Title Page (and on the overs, if any) a title distin tfrom that of the Do ument, and from those of previous versions(whi h should, if there were any, be listed in the History se tion ofthe Do ument). You may use the same title as a previous versionif the original publisher of that version gives permission.

Page 300: An Introduction to Programming in Emacs Lisp

282 Appendix D: GNU Free Do umentation Li enseB. List on the Title Page, as authors, one or more persons or enti-ties responsible for authorship of the modi� ations in the Modi�edVersion, together with at least �ve of the prin ipal authors of theDo ument (all of its prin ipal authors, if it has less than �ve).C. State on the Title page the name of the publisher of the Modi�edVersion, as the publisher.D. Preserve all the opyright noti es of the Do ument.E. Add an appropriate opyright noti e for your modi� ations adja- ent to the other opyright noti es.F. In lude, immediately after the opyright noti es, a li ense noti egiving the publi permission to use the Modi�ed Version under theterms of this Li ense, in the form shown in the Addendum below.G. Preserve in that li ense noti e the full lists of Invariant Se tionsand required Cover Texts given in the Do ument's li ense noti e.H. In lude an unaltered opy of this Li ense.I. Preserve the se tion entitled \History", and its title, and add to itan item stating at least the title, year, new authors, and publisherof the Modi�ed Version as given on the Title Page. If there is nose tion entitled \History" in the Do ument, reate one stating thetitle, year, authors, and publisher of the Do ument as given on itsTitle Page, then add an item des ribing the Modi�ed Version asstated in the previous senten e.J. Preserve the network lo ation, if any, given in the Do ument forpubli a ess to a Transparent opy of the Do ument, and likewisethe network lo ations given in the Do ument for previous versionsit was based on. These may be pla ed in the \History" se tion. Youmay omit a network lo ation for a work that was published at leastfour years before the Do ument itself, or if the original publisher ofthe version it refers to gives permission.K. In any se tion entitled \A knowledgments" or \Dedi ations", pre-serve the se tion's title, and preserve in the se tion all the substan eand tone of ea h of the ontributor a knowledgments and/or dedi- ations given therein.L. Preserve all the Invariant Se tions of the Do ument, unaltered intheir text and in their titles. Se tion numbers or the equivalent arenot onsidered part of the se tion titles.M. Delete any se tion entitled \Endorsements". Su h a se tion maynot be in luded in the Modi�ed Version.N. Do not retitle any existing se tion as \Endorsements" or to on i tin title with any Invariant Se tion.If the Modi�ed Version in ludes new front-matter se tions or appendi esthat qualify as Se ondary Se tions and ontain no material opied fromthe Do ument, you may at your option designate some or all of these

Page 301: An Introduction to Programming in Emacs Lisp

GNU Free Do umentation Li ense 283se tions as invariant. To do this, add their titles to the list of InvariantSe tions in the Modi�ed Version's li ense noti e. These titles must bedistin t from any other se tion titles.You may add a se tion entitled \Endorsements", provided it ontainsnothing but endorsements of your Modi�ed Version by various parties|for example, statements of peer review or that the text has been ap-proved by an organization as the authoritative de�nition of a standard.You may add a passage of up to �ve words as a Front-Cover Text, and apassage of up to 25 words as a Ba k-Cover Text, to the end of the list ofCover Texts in the Modi�ed Version. Only one passage of Front-CoverText and one of Ba k-Cover Text may be added by (or through ar-rangements made by) any one entity. If the Do ument already in ludesa over text for the same over, previously added by you or by arrange-ment made by the same entity you are a ting on behalf of, you may notadd another; but you may repla e the old one, on expli it permissionfrom the previous publisher that added the old one.The author(s) and publisher(s) of the Do ument do not by this Li ensegive permission to use their names for publi ity for or to assert or implyendorsement of any Modi�ed Version.5. COMBINING DOCUMENTSYou may ombine the Do ument with other do uments released underthis Li ense, under the terms de�ned in se tion 4 above for modi�edversions, provided that you in lude in the ombination all of the Invari-ant Se tions of all of the original do uments, unmodi�ed, and list themall as Invariant Se tions of your ombined work in its li ense noti e.The ombined work need only ontain one opy of this Li ense, andmultiple identi al Invariant Se tions may be repla ed with a single opy.If there are multiple Invariant Se tions with the same name but di�erent ontents, make the title of ea h su h se tion unique by adding at the endof it, in parentheses, the name of the original author or publisher of thatse tion if known, or else a unique number. Make the same adjustmentto the se tion titles in the list of Invariant Se tions in the li ense noti eof the ombined work.In the ombination, you must ombine any se tions entitled \History"in the various original do uments, forming one se tion entitled \His-tory"; likewise ombine any se tions entitled \A knowledgments", andany se tions entitled \Dedi ations". You must delete all se tions enti-tled \Endorsements."6. COLLECTIONS OF DOCUMENTSYou may make a olle tion onsisting of the Do ument and other do u-ments released under this Li ense, and repla e the individual opies ofthis Li ense in the various do uments with a single opy that is in ludedin the olle tion, provided that you follow the rules of this Li ense forverbatim opying of ea h of the do uments in all other respe ts.

Page 302: An Introduction to Programming in Emacs Lisp

284 Appendix D: GNU Free Do umentation Li enseYou may extra t a single do ument from su h a olle tion, and distributeit individually under this Li ense, provided you insert a opy of thisLi ense into the extra ted do ument, and follow this Li ense in all otherrespe ts regarding verbatim opying of that do ument.7. AGGREGATION WITH INDEPENDENT WORKSA ompilation of the Do ument or its derivatives with other separateand independent do uments or works, in or on a volume of a storageor distribution medium, does not as a whole ount as a Modi�ed Ver-sion of the Do ument, provided no ompilation opyright is laimed forthe ompilation. Su h a ompilation is alled an \aggregate", and thisLi ense does not apply to the other self- ontained works thus ompiledwith the Do ument, on a ount of their being thus ompiled, if they arenot themselves derivative works of the Do ument.If the Cover Text requirement of se tion 3 is appli able to these opiesof the Do ument, then if the Do ument is less than one quarter of theentire aggregate, the Do ument's Cover Texts may be pla ed on oversthat surround only the Do ument within the aggregate. Otherwise theymust appear on overs around the whole aggregate.8. TRANSLATIONTranslation is onsidered a kind of modi� ation, so you may distributetranslations of the Do ument under the terms of se tion 4. Repla ingInvariant Se tions with translations requires spe ial permission fromtheir opyright holders, but you may in lude translations of some or allInvariant Se tions in addition to the original versions of these InvariantSe tions. You may in lude a translation of this Li ense provided thatyou also in lude the original English version of this Li ense. In ase ofa disagreement between the translation and the original English versionof this Li ense, the original English version will prevail.9. TERMINATIONYou may not opy, modify, subli ense, or distribute the Do ument ex- ept as expressly provided for under this Li ense. Any other attemptto opy, modify, subli ense or distribute the Do ument is void, and willautomati ally terminate your rights under this Li ense. However, par-ties who have re eived opies, or rights, from you under this Li ense willnot have their li enses terminated so long as su h parties remain in full omplian e.10. FUTURE REVISIONS OF THIS LICENSEThe Free Software Foundation may publish new, revised versionsof the GNU Free Do umentation Li ense from time to time. Su hnew versions will be similar in spirit to the present version, butmay di�er in detail to address new problems or on erns. Seehttp://www.gnu.org/ opyleft/.Ea h version of the Li ense is given a distinguishing version number.If the Do ument spe i�es that a parti ular numbered version of this

Page 303: An Introduction to Programming in Emacs Lisp

GNU Free Do umentation Li ense 285Li ense \or any later version" applies to it, you have the option offollowing the terms and onditions either of that spe i�ed version orof any later version that has been published (not as a draft) by theFree Software Foundation. If the Do ument does not spe ify a versionnumber of this Li ense, you may hoose any version ever published (notas a draft) by the Free Software Foundation.

Page 304: An Introduction to Programming in Emacs Lisp

286 Appendix D: GNU Free Do umentation Li ense

Page 305: An Introduction to Programming in Emacs Lisp

Index 287Index%% (remainder fun tion) . . . . . . . . . . . . . . 258((debug) in ode . . . . . . . . . . . . . . . . . . . . 235** (multipli ation) . . . . . . . . . . . . . . . . . . . . 31* for read-only bu�er. . . . . . . . . . . . . . . . . 65`*s rat h*' bu�er . . . . . . . . . . . . . . . . . . 123.̀.ema s' �le . . . . . . . . . . . . . . . . . . . . . . . . 213`.ema s' �le, beginning of . . . . . . . . . . . 216// (division) . . . . . . . . . . . . . . . . . . . . . . . . . . 72>> (greater than) . . . . . . . . . . . . . . . . . . . . 40<<= (less than or equal) . . . . . . . . . . . . . . 127AA umulate, type of re ursive pattern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142add-hook. . . . . . . . . . . . . . . . . . . . . . . . . . . 218and. . . . . . . . . . . . . . . . . . . . . . . . . . . . 108, 156and, introdu ed . . . . . . . . . . . . . . . . . . . . 108Anonymous fun tion . . . . . . . . . . . . . . . . 272append-to-buffer . . . . . . . . . . . . . . . . . . . 56apply . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205apropos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203Argument as lo al variable . . . . . . . . . . 131`argument' de�ned . . . . . . . . . . . . . . . . . . . 12`argument list' de�ned . . . . . . . . . . . . . . 30Argument, wrong type of . . . . . . . . . . . . . 14

Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . 12Arguments' data types . . . . . . . . . . . . . . . 13Arguments, variable number of. . . . . . . . 14Asterisk for read-only bu�er . . . . . . . . . . 65Auto Fill mode turned on . . . . . . . . . . . 218autoload. . . . . . . . . . . . . . . . . . . . . . . . . . . 223Automati mode sele tion . . . . . . . . . . . 218Axis, print horizontal . . . . . . . . . . . . . . . 263Axis, print verti al . . . . . . . . . . . . . . . . . . 256Bbeginning-of-buffer . . . . . . . . . . . . . . . . 69`bind' de�ned . . . . . . . . . . . . . . . . . . . . . . . 17`body' de�ned . . . . . . . . . . . . . . . . . . . . . . . 30Body of graph . . . . . . . . . . . . . . . . . . . . . . 203Bu�er size . . . . . . . . . . . . . . . . . . . . . . . . . . . 27Bu�er, history of word . . . . . . . . . . . . . . . 24buffer-file-name . . . . . . . . . . . . . . . . . . . 23buffer-menu, bound to key . . . . . . . . . 221buffer-name . . . . . . . . . . . . . . . . . . . . . . . . 23Bug, most insidious type . . . . . . . . . . . . 274Building robots . . . . . . . . . . . . . . . . . . . . . 134Building Tags in the Ema s sour es . . 164Byte ompiling . . . . . . . . . . . . . . . . . . . . . . . 8CC language primitives . . . . . . . . . . . . . . . . 29C, a digression into . . . . . . . . . . . . . . . . . . 98` all' de�ned . . . . . . . . . . . . . . . . . . . . . . . 27 an el-debug-on-entry. . . . . . . . . . . . . 234 ar, introdu ed . . . . . . . . . . . . . . . . . . . . . 81 dr, introdu ed . . . . . . . . . . . . . . . . . . . . . 81Changing a fun tion de�nition . . . . . . . . 32Chest of Drawers, metaphor for a symbol. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115Clipping text . . . . . . . . . . . . . . . . . . . . . . . . 89Code installation . . . . . . . . . . . . . . . . . . . . 36` ommand' de�ned . . . . . . . . . . . . . . . . . . . . 23Comments in Lisp ode . . . . . . . . . . . . . . 32Common Lisp. . . . . . . . . . . . . . . . . . . . . . . xiii ompare-windows . . . . . . . . . . . . . . . . . . . 220 on at . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 ond . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 ondition- ase . . . . . . . . . . . . . . . . . . . . . 95

Page 306: An Introduction to Programming in Emacs Lisp

288 IndexConditional 'twixt two versions of Ema s. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225Conditional with if . . . . . . . . . . . . . . . . . . 39 ons, example. . . . . . . . . . . . . . . . . . . . . . 107 ons, introdu ed . . . . . . . . . . . . . . . . . . . . 83 opy-region-as-kill . . . . . . . . . . . . . . . 102 opy-to-buffer . . . . . . . . . . . . . . . . . . . . . 63Count words re ursively . . . . . . . . . . . . . 173 ount-words-in-defun . . . . . . . . . . . . . . 185 ount-words-region . . . . . . . . . . . . . . . . 167Counting . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19Counting words in a defun . . . . . . 181, 183 urrent-buffer . . . . . . . . . . . . . . . . . . . . . 25Customizing your `.ema s' �le . . . . . . . 213Cutting and storing text. . . . . . . . . . . . . . 89DData types . . . . . . . . . . . . . . . . . . . . . . . . . . 13debug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231debug-on-entry . . . . . . . . . . . . . . . . . . . . 232debug-on-quit . . . . . . . . . . . . . . . . . . . . . 234debugging . . . . . . . . . . . . . . . . . . . . . . . . . . 231default-mode-line-format . . . . . . . . . 228`default.el' init �le . . . . . . . . . . . . . . . . 213def ustom . . . . . . . . . . . . . . . . . . . . . . . . . 214Deferment in re ursion . . . . . . . . . . . . . . 143Defermentless solution . . . . . . . . . . . . . . 145De�nition installation . . . . . . . . . . . . . . . . 31De�nition writing . . . . . . . . . . . . . . . . . . . . 29De�nition, how to hange. . . . . . . . . . . . . 32defun . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29defvar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100defvar for a user ustomizable variable. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101defvar with an asterisk . . . . . . . . . . . . . 101delete-and-extra t-region . . . . . . 96, 98Deleting text . . . . . . . . . . . . . . . . . . . . . . . . 89des ribe-fun tion . . . . . . . . . . . . . . . . . . 53des ribe-fun tion, introdu ed . . . . . . 51Digression into C . . . . . . . . . . . . . . . . . . . . 98dire tory-files . . . . . . . . . . . . . . . . . . . 194Division . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72dolist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132dotimes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133Drawers, Chest of, metaphor for a symbol. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115Dupli ated words fun tion . . . . . . . . . . . 241

Eedebug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235edit-options . . . . . . . . . . . . . . . . . . . . . . 101Else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42Ema s version, hoosing . . . . . . . . . . . . . 225`empty list' de�ned . . . . . . . . . . . . . . . . . . 2`empty string' de�ned . . . . . . . . . . . . . . . 48eobp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159eq . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48eq (example of use) . . . . . . . . . . . . . . . . . 104equal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48Erasing text . . . . . . . . . . . . . . . . . . . . . . . . . 89error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244Error for symbol without fun tion . . . . . 11Error for symbol without value . . . . . . . 11Error message generation . . . . . . . . . . . . . . 4etags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163`evaluate' de�ned . . . . . . . . . . . . . . . . . . . . 4Evaluating inner lists . . . . . . . . . . . . . . . . . . 9Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . 8Evaluation pra ti e . . . . . . . . . . . . . . . . . . 23Every, type of re ursive pattern . . . . . . 141Example variable, fill- olumn . . . . . . . 10`expression' de�ned . . . . . . . . . . . . . . . . . . 2FFalsehood and truth in Ema s Lisp . . . . 43FDL, GNU Free Do umentation Li ense. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279files-in-below-dire tory . . . . . . . . . 194fill- olumn, an example variable . . . . 10Find a File . . . . . . . . . . . . . . . . . . . . . . . . . 187Find fun tion do umentation . . . . . . . . . 51Find sour e of fun tion . . . . . . . . . . . . . . . 51find-tags. . . . . . . . . . . . . . . . . . . . . . . . . . . 51Flowers in a �eld . . . . . . . . . . . . . . . . . . . . . 1Fo using attention (narrowing) . . . . . . . 77`form' de�ned. . . . . . . . . . . . . . . . . . . . . . . . . 2Formatting onvention . . . . . . . . . . . . . . . 58Formatting help . . . . . . . . . . . . . . . . . . . . . . 3forward-paragraph . . . . . . . . . . . . . . . . . 155forward-senten e . . . . . . . . . . . . . . . . . . 151`fun tion' de�ned . . . . . . . . . . . . . . . . . . 5, 6`fun tion definition' de�ned . . . . . . . . 29Fun tion de�nition installation . . . . . . . . 31Fun tion de�nition writing . . . . . . . . . . . 29Fun tion de�nition, how to hange . . . . 32Fun tions, primitive . . . . . . . . . . . . . . . . . . 29

Page 307: An Introduction to Programming in Emacs Lisp

Index 289GGenerate an error message . . . . . . . . . . . . . 4Getting a bu�er . . . . . . . . . . . . . . . . . . . . . 25Global set key . . . . . . . . . . . . . . . . . . . . . . 220global-set-key . . . . . . . . . . . . . . . . . . . . 220global-unset-key . . . . . . . . . . . . . . . . . . 221Graph prototype . . . . . . . . . . . . . . . . . . . . 203Graph, printing all . . . . . . . . . . . . . . . . . . 267graph-body-print . . . . . . . . . . . . . . . . . . 208graph-body-print Final version. . . . . . 268HHandling the kill ring . . . . . . . . . . . . . . . 243Help typing lists . . . . . . . . . . . . . . . . . . . . . . 3Horizontal axis printing . . . . . . . . . . . . . 263Iif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39`if-part' de�ned . . . . . . . . . . . . . . . . . . . . 40indent-tabs-mode . . . . . . . . . . . . . . . . . . 219Indentation for formatting . . . . . . . . . . . . 58Initialization �le . . . . . . . . . . . . . . . . . . . . 213Initializing a variable . . . . . . . . . . . . . . . . 100Inner list evaluation . . . . . . . . . . . . . . . . . . . 9insert-buffer . . . . . . . . . . . . . . . . . . . . . . 64insert-buffer-substring . . . . . . . . . . . 56Insidious type of bug . . . . . . . . . . . . . . . . 274Install a Fun tion De�nition . . . . . . . . . . 31Install ode permanently . . . . . . . . . . . . . 36intera tive . . . . . . . . . . . . . . . . . . . . . . . . 33`intera tive fun tion' de�ned. . . . . . . 23Intera tive fun tions . . . . . . . . . . . . . . . . . 33Intera tive options . . . . . . . . . . . . . . . . . . . 35intera tive, example use of . . . . . . . . . 65Interpreter, Lisp, explained . . . . . . . . . . . . 4Interpreter, what it does. . . . . . . . . . . . . . . 7KKeep, type of re ursive pattern . . . . . . 143Key setting globally . . . . . . . . . . . . . . . . . 220Key unbinding. . . . . . . . . . . . . . . . . . . . . . 221Keymaps . . . . . . . . . . . . . . . . . . . . . . . . . . . 221Keyword . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70Kill ring handling . . . . . . . . . . . . . . . . . . . 243Kill ring overview . . . . . . . . . . . . . . . . . . . 117kill-append . . . . . . . . . . . . . . . . . . . . . . . 104

kill-new. . . . . . . . . . . . . . . . . . . . . . . . . . . 105kill-region . . . . . . . . . . . . . . . . . . . . . . . . 94Killing text . . . . . . . . . . . . . . . . . . . . . . . . . . 89Llambda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272length . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84lengths-list-file . . . . . . . . . . . . . . . . . 188lengths-list-many-files . . . . . . . . . . 190let . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36let expression sample . . . . . . . . . . . . . . . . 38let expression, parts of . . . . . . . . . . . . . . 37let variables uninitialized . . . . . . . . . . . . 39Library, as term for `�le' . . . . . . . . . . . . . 52line-to-top-of-window. . . . . . . . . . . . . 224Lisp Atoms . . . . . . . . . . . . . . . . . . . . . . . . . . . 1Lisp history . . . . . . . . . . . . . . . . . . . . . . . . xiiiLisp interpreter, explained . . . . . . . . . . . . . 4Lisp interpreter, what it does . . . . . . . . . . 7Lisp Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1Lisp ma ro . . . . . . . . . . . . . . . . . . . . . . . . . . 97list-buffers, rebound . . . . . . . . . . . . . 221Lists in a omputer . . . . . . . . . . . . . . . . . 113load-library . . . . . . . . . . . . . . . . . . . . . . 223load-path . . . . . . . . . . . . . . . . . . . . . . . . . 223Loading �les. . . . . . . . . . . . . . . . . . . . . . . . 222`lo al variable' de�ned . . . . . . . . . . . . . 37Lo al variables list, per-bu�er, . . . . . . . 218Lo ation of point . . . . . . . . . . . . . . . . . . . . 27looking-at . . . . . . . . . . . . . . . . . . . . . . . . 159Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121Loops and re ursion. . . . . . . . . . . . . . . . . 121MMa lisp . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiiiMa ro, lisp . . . . . . . . . . . . . . . . . . . . . . . . . . 97Mail aliases . . . . . . . . . . . . . . . . . . . . . . . . 219make tags . . . . . . . . . . . . . . . . . . . . . . . . . . 164make-string . . . . . . . . . . . . . . . . . . . . . . . 261map ar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274mark . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44mark-whole-buffer . . . . . . . . . . . . . . . . . . 54mat h-beginning . . . . . . . . . . . . . . . . . . . 161max . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205message . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16min . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205Mode line format . . . . . . . . . . . . . . . . . . . 228

Page 308: An Introduction to Programming in Emacs Lisp

290 IndexMode sele tion, automati . . . . . . . . . . . 218Motion by senten e and paragraph . . . 149NNarrowing . . . . . . . . . . . . . . . . . . . . . . . . . . . 77`narrowing' de�ned . . . . . . . . . . . . . . . . . . 28nil . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43nil, history of word . . . . . . . . . . . . . . . . . . 24No deferment solution . . . . . . . . . . . . . . . 145nreverse. . . . . . . . . . . . . . . . . . . . . . . . . . . 199nth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86nth dr . . . . . . . . . . . . . . . . . . . . . . . . . 85, 102nth dr, example . . . . . . . . . . . . . . . . . . . 107number-to-string . . . . . . . . . . . . . . . . . . 259Oo ur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221optional . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70Optional arguments . . . . . . . . . . . . . . . . . . 70Options for intera tive . . . . . . . . . . . . . 35or . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67other-buffer . . . . . . . . . . . . . . . . . . . . . . . 25PParagraphs, movement by . . . . . . . . . . . 149Parts of a Re ursive De�nition . . . . . . . 135Parts of let expression . . . . . . . . . . . . . . . 37Passing information to fun tions . . . . . . 12Pasting text . . . . . . . . . . . . . . . . . . . . . . . . 117Patterns, sear hing for . . . . . . . . . . . . . . 149Per-bu�er, lo al variables list . . . . . . . . 218Permanent ode installation . . . . . . . . . . 36point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44`point' de�ned . . . . . . . . . . . . . . . . . . . . . . 27Point lo ation . . . . . . . . . . . . . . . . . . . . . . . 27Point, mark, bu�er preservation . . . . . . . 44Pra ti ing evaluation . . . . . . . . . . . . . . . . . 23Preserving point, mark, and bu�er . . . . 44Primitive fun tions. . . . . . . . . . . . . . . . . . . 29Primitives written in C . . . . . . . . . . . . . . . 29Print horizontal axis . . . . . . . . . . . . . . . . 263Print verti al axis . . . . . . . . . . . . . . . . . . . 256print-elements-of-list . . . . . . . . . . . 123print-elements-re ursively . . . . . . . 136print-graph Final version. . . . . . . . . . . 269print-graph varlist . . . . . . . . . . . . . . . . . 256

print-X-axis . . . . . . . . . . . . . . . . . . . . . . 266print-X-axis-numbered-line . . . . . . . 265print-X-axis-ti -line. . . . . . . . . . . . . 265print-Y-axis . . . . . . . . . . . . . . . . . . . . . . 262Printing the whole graph . . . . . . . . . . . . 267prog1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159progn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93Program, running one . . . . . . . . . . . . . . . . . 4Prototype graph . . . . . . . . . . . . . . . . . . . . 203Rre-sear h-forward . . . . . . . . . . . . . . . . . 150Read-only bu�er . . . . . . . . . . . . . . . . . . . . . 65Readying a graph . . . . . . . . . . . . . . . . . . . 203Rebinding keys . . . . . . . . . . . . . . . . . . . . . 221Re ursion . . . . . . . . . . . . . . . . . . . . . . . . . . 134Re ursion and loops. . . . . . . . . . . . . . . . . 121Re ursion without Deferments . . . . . . . 143Re ursive De�nition Parts . . . . . . . . . . . 135Re ursive pattern: a umulate . . . . . . . 142Re ursive pattern: every . . . . . . . . . . . . 141Re ursive pattern: keep . . . . . . . . . . . . . 143Re ursive Patterns . . . . . . . . . . . . . . . . . . 140re ursive- ount-words. . . . . . . . . . . . . 178re ursive-graph-body-print . . . . . . . 210re ursive-lengths-list-many-files. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192Re ursively ounting words . . . . . . . . . . 173regexp-quote . . . . . . . . . . . . . . . . . . . . . . 157Region, what it is . . . . . . . . . . . . . . . . . . . . 44Regular expression sear hes . . . . . . . . . . 149Regular expressions for word ounting. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167Remainder fun tion, %. . . . . . . . . . . . . . . 258Repetition (loops) . . . . . . . . . . . . . . . . . . 121Repetition for word ounting . . . . . . . . 167Retrieving text . . . . . . . . . . . . . . . . . . . . . 117reverse . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199Ring, making a list like a . . . . . . . . . . . . 243Robots, building . . . . . . . . . . . . . . . . . . . . 134rotate-yank-pointer . . . . . . . . . . 117, 243Run a program . . . . . . . . . . . . . . . . . . . . . . . 4

Page 309: An Introduction to Programming in Emacs Lisp

Index 291SSample let expression . . . . . . . . . . . . . . . 38save-ex ursion . . . . . . . . . . . . . . . . . . . . . 44save-restri tion . . . . . . . . . . . . . . . . . . . 77sear h-forward . . . . . . . . . . . . . . . . . . . . . 92Sear hes, illustrating . . . . . . . . . . . . . . . . 149senten e-end . . . . . . . . . . . . . . . . . . . . . . 149Senten es, movement by . . . . . . . . . . . . . 149set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17set-buffer . . . . . . . . . . . . . . . . . . . . . . . . . 26set ar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87set dr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88set dr, example . . . . . . . . . . . . . . . . . . . 107setq . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18Setting a key globally . . . . . . . . . . . . . . . 220Setting value of variable . . . . . . . . . . . . . . 17`side effe t' de�ned . . . . . . . . . . . . . . . . . 8Simple extension in `.ema s' �le . . . . . 224simplified-beginning-of-buffer . . . . 52`site-init.el' init �le . . . . . . . . . . . . . . 213`site-load.el' init �le . . . . . . . . . . . . . . 213Size of bu�er . . . . . . . . . . . . . . . . . . . . . . . . 27Solution without deferment . . . . . . . . . . 145sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193Sour e level debugger . . . . . . . . . . . . . . . 235Spe ial form . . . . . . . . . . . . . . . . . . . . . . . . . . 7Spe ial form of defun . . . . . . . . . . . . . . . . 29Storing and utting text . . . . . . . . . . . . . . 89`string' de�ned . . . . . . . . . . . . . . . . . . . . . . 3swit h-to-buffer . . . . . . . . . . . . . . . . . . . 26Swit hing to a bu�er . . . . . . . . . . . . . . . . . 26Symbol names . . . . . . . . . . . . . . . . . . . . . . . . 6Symbol without fun tion error . . . . . . . . 11Symbol without value error . . . . . . . . . . . 11Symboli expressions, introdu ed . . . . . . . 2Symbols as a Chest of Drawers. . . . . . . 115Syntax ategories and tables . . . . . . . . . 182TTabs, preventing . . . . . . . . . . . . . . . . . . . . 219`TAGS' �le, reate own . . . . . . . . . . . . . . . 163Tags in the Ema s sour es . . . . . . . . . . . 164TAGS table, spe ifying . . . . . . . . . . . . . . . 51Text between double quotation marks . . 3Text Mode turned on . . . . . . . . . . . . . . . 218Text retrieval . . . . . . . . . . . . . . . . . . . . . . . 117the-the . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241`then-part' de�ned . . . . . . . . . . . . . . . . . . 40

top-of-ranges . . . . . . . . . . . . . . . . . . . . . 198triangle-bugged . . . . . . . . . . . . . . . . . . . 231triangle-re ursively . . . . . . . . . . . . . . 137Truth and falsehood in Ema s Lisp . . . . 43Types of data . . . . . . . . . . . . . . . . . . . . . . . 13UUnbinding key . . . . . . . . . . . . . . . . . . . . . . 221Uninitialized let variables . . . . . . . . . . . . 39VVariable initialization . . . . . . . . . . . . . . . 100Variable number of arguments . . . . . . . . 14Variable, example of, fill- olumn . . . . 10Variable, setting value . . . . . . . . . . . . . . . . 17Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10`varlist' de�ned . . . . . . . . . . . . . . . . . . . . 37Version of Ema s, hoosing . . . . . . . . . . 225Verti al axis printing . . . . . . . . . . . . . . . . 256Wwhat-line. . . . . . . . . . . . . . . . . . . . . . . . . . . 78while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121Whitespa e in lists . . . . . . . . . . . . . . . . . . . . 3Whole graph printing . . . . . . . . . . . . . . . 267Widening . . . . . . . . . . . . . . . . . . . . . . . . . . . 77Widening, example of . . . . . . . . . . . . . . . . 78Word ounting in a defun . . . . . . . . . . . 181Words and symbols in defun . . . . . . . . . 181Words, ounted re ursively . . . . . . . . . . 173Words, dupli ated . . . . . . . . . . . . . . . . . . 241Writing a fun tion de�nition . . . . . . . . . . 29Wrong type of argument. . . . . . . . . . . . . . 14XX axis printing . . . . . . . . . . . . . . . . . . . . . 263X-axis-element . . . . . . . . . . . . . . . . . . . . 265YY axis printing . . . . . . . . . . . . . . . . . . . . . 256Y-axis- olumn . . . . . . . . . . . . . . . . . . . . . 261Y-axis- olumn Final version. . . . . . . . . 268Y-axis-label-spa ing . . . . . . . . . . . . . . 259Y-axis-ti . . . . . . . . . . . . . . . . . . . . . . . . 260

Page 310: An Introduction to Programming in Emacs Lisp

292 Indexyank . . . . . . . . . . . . . . . . . . . . . . . . . . 117, 249yank-pop. . . . . . . . . . . . . . . . . . . . . . . . . . . 252 Zzap-to- har . . . . . . . . . . . . . . . . . . . . . . . . 90zerop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244

Page 311: An Introduction to Programming in Emacs Lisp
Page 312: An Introduction to Programming in Emacs Lisp
Page 313: An Introduction to Programming in Emacs Lisp

About the AuthorRobert J. Chassell has worked with GNU Ema s sin e 1985. Hewrites and edits, tea hes Ema s and Ema s Lisp, and speaksthroughout the world on software freedom. Chassell was a found-ing Dire tor and Treasurer of the Free Software Foundation, In .He is o-author of the Texinfo manual, and has edited more thana dozen other books. He graduated from Cambridge University, inEngland. He has an abiding interest in so ial and e onomi historyand ies his own airplane.

Page 314: An Introduction to Programming in Emacs Lisp