learn-emacs-lisp.el 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. ;; This gives an introduction to Emacs Lisp in 15 minutes (v0.2d)
  2. ;;
  3. ;; Author: Bastien / @bzg2 / http://bzg.fr
  4. ;;
  5. ;; First make sure you read this text by Peter Norvig:
  6. ;; http://norvig.com/21-days.html
  7. ;;
  8. ;; Then install GNU Emacs 24.3:
  9. ;;
  10. ;; Debian: apt-get install emacs (or see your distro instructions)
  11. ;; OSX: http://emacsformacosx.com/emacs-builds/Emacs-24.3-universal-10.6.8.dmg
  12. ;; Windows: http://ftp.gnu.org/gnu/windows/emacs/emacs-24.3-bin-i386.zip
  13. ;;
  14. ;; More general information can be found at:
  15. ;; http://www.gnu.org/software/emacs/#Obtaining
  16. ;; Important warning:
  17. ;;
  18. ;; Going through this tutorial won't damage your computer unless
  19. ;; you get so angry that you throw it on the floor. In that case,
  20. ;; I hereby decline any responsibility. Have fun!
  21. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  22. ;;
  23. ;; Fire up Emacs.
  24. ;;
  25. ;; Hit the `q' key to dismiss the welcome message.
  26. ;;
  27. ;; Now look at the gray line at the bottom of the window:
  28. ;;
  29. ;; "*scratch*" is the name of the editing space you are now in.
  30. ;; This editing space is called a "buffer".
  31. ;;
  32. ;; The scratch buffer is the default buffer when opening Emacs.
  33. ;; You are never editing files: you are editing buffers that you
  34. ;; can save to a file.
  35. ;;
  36. ;; "Lisp interaction" refers to a set of commands available here.
  37. ;;
  38. ;; Emacs has a built-in set of commands available in every buffer,
  39. ;; and several subsets of commands available when you activate a
  40. ;; specific mode. Here we use the `lisp-interaction-mode', which
  41. ;; comes with commands to evaluate and navigate within Elisp code.
  42. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  43. ;;
  44. ;; Semi-colons start comments anywhere on a line.
  45. ;;
  46. ;; Elisp programs are made of symbolic expressions ("sexps"):
  47. (+ 2 2)
  48. ;; This symbolic expression reads as "Add 2 to 2".
  49. ;; Sexps are enclosed into parentheses, possibly nested:
  50. (+ 2 (+ 1 1))
  51. ;; A symbolic expression contains atoms or other symbolic
  52. ;; expressions. In the above examples, 1 and 2 are atoms,
  53. ;; (+ 2 (+ 1 1)) and (+ 1 1) are symbolic expressions.
  54. ;; From `lisp-interaction-mode' you can evaluate sexps.
  55. ;; Put the cursor right after the closing parenthesis then
  56. ;; hold down the control and hit the j keys ("C-j" for short).
  57. (+ 3 (+ 1 2))
  58. ;; ^ cursor here
  59. ;; `C-j' => 6
  60. ;; `C-j' inserts the result of the evaluation in the buffer.
  61. ;; `C-xC-e' displays the same result in Emacs bottom line,
  62. ;; called the "minibuffer". We will generally use `C-xC-e',
  63. ;; as we don't want to clutter the buffer with useless text.
  64. ;; `setq' stores a value into a variable:
  65. (setq my-name "Bastien")
  66. ;; `C-xC-e' => "Bastien" (displayed in the mini-buffer)
  67. ;; `insert' will insert "Hello!" where the cursor is:
  68. (insert "Hello!")
  69. ;; `C-xC-e' => "Hello!"
  70. ;; We used `insert' with only one argument "Hello!", but
  71. ;; we can pass more arguments -- here we use two:
  72. (insert "Hello" " world!")
  73. ;; `C-xC-e' => "Hello world!"
  74. ;; You can use variables instead of strings:
  75. (insert "Hello, I am " my-name)
  76. ;; `C-xC-e' => "Hello, I am Bastien"
  77. ;; You can combine sexps into functions:
  78. (defun hello () (insert "Hello, I am " my-name))
  79. ;; `C-xC-e' => hello
  80. ;; You can evaluate functions:
  81. (hello)
  82. ;; `C-xC-e' => Hello, I am Bastien
  83. ;; The empty parentheses in the function's definition means that
  84. ;; it does not accept arguments. But always using `my-name' is
  85. ;; boring, let's tell the function to accept one argument (here
  86. ;; the argument is called "name"):
  87. (defun hello (name) (insert "Hello " name))
  88. ;; `C-xC-e' => hello
  89. ;; Now let's call the function with the string "you" as the value
  90. ;; for its unique argument:
  91. (hello "you")
  92. ;; `C-xC-e' => "Hello you"
  93. ;; Yeah!
  94. ;; Take a breath.
  95. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  96. ;;
  97. ;; Now switch to a new buffer named "*test*" in another window:
  98. (switch-to-buffer-other-window "*test*")
  99. ;; `C-xC-e'
  100. ;; => [screen has two windows and cursor is in the *test* buffer]
  101. ;; Mouse over the top window and left-click to go back. Or you can
  102. ;; use `C-xo' (i.e. hold down control-x and hit o) to go to the other
  103. ;; window interactively.
  104. ;; You can combine several sexps with `progn':
  105. (progn
  106. (switch-to-buffer-other-window "*test*")
  107. (hello "you"))
  108. ;; `C-xC-e'
  109. ;; => [The screen has two windows and cursor is in the *test* buffer]
  110. ;; Now if you don't mind, I'll stop asking you to hit `C-xC-e': do it
  111. ;; for every sexp that follows.
  112. ;; Always go back to the *scratch* buffer with the mouse or `C-xo'.
  113. ;; It's often useful to erase the buffer:
  114. (progn
  115. (switch-to-buffer-other-window "*test*")
  116. (erase-buffer)
  117. (hello "there"))
  118. ;; Or to go back to the other window:
  119. (progn
  120. (switch-to-buffer-other-window "*test*")
  121. (erase-buffer)
  122. (hello "you")
  123. (other-window 1))
  124. ;; You can bind a value to a local variable with `let':
  125. (let ((local-name "you"))
  126. (switch-to-buffer-other-window "*test*")
  127. (erase-buffer)
  128. (hello local-name)
  129. (other-window 1))
  130. ;; No need to use `progn' in that case, since `let' also combines
  131. ;; several sexps.
  132. ;; Let's format a string:
  133. (format "Hello %s!\n" "visitor")
  134. ;; %s is a place-holder for a string, replaced by "visitor".
  135. ;; \n is the newline character.
  136. ;; Let's refine our function by using format:
  137. (defun hello (name)
  138. (insert (format "Hello %s!\n" name)))
  139. (hello "you")
  140. ;; Let's create another function which uses `let':
  141. (defun greeting (name)
  142. (let ((your-name "Bastien"))
  143. (insert (format "Hello %s!\n\nI am %s."
  144. name ; the argument of the function
  145. your-name ; the let-bound variable "Bastien"
  146. ))))
  147. ;; And evaluate it:
  148. (greeting "you")
  149. ;; Some function are interactive:
  150. (read-from-minibuffer "Enter your name: ")
  151. ;; Evaluating this function returns what you entered at the prompt.
  152. ;; Let's make our `greeting' function prompt for your name:
  153. (defun greeting (from-name)
  154. (let ((your-name (read-from-minibuffer "Enter your name: ")))
  155. (insert (format "Hello!\n\nI am %s and you are %s."
  156. from-name ; the argument of the function
  157. your-name ; the let-bound var, entered at prompt
  158. ))))
  159. (greeting "Bastien")
  160. ;; Let's complete it by displaying the results in the other window:
  161. (defun greeting (from-name)
  162. (let ((your-name (read-from-minibuffer "Enter your name: ")))
  163. (switch-to-buffer-other-window "*test*")
  164. (erase-buffer)
  165. (insert (format "Hello %s!\n\nI am %s." your-name from-name))
  166. (other-window 1)))
  167. ;; Now test it:
  168. (greeting "Bastien")
  169. ;; Take a breath.
  170. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  171. ;;
  172. ;; Let's store a list of names:
  173. (setq list-of-names '("Sarah" "Chloe" "Mathilde"))
  174. ;; Get the first element of this list with `car':
  175. (car list-of-names)
  176. ;; Get a list of all but the first element with `cdr':
  177. (cdr list-of-names)
  178. ;; Add an element to the beginning of a list with `push':
  179. (push "Stephanie" list-of-names)
  180. ;; NOTE: `car' and `cdr' don't modify the list, but `push' does.
  181. ;; This is an important difference: some functions don't have any
  182. ;; side-effects (like `car') while others have (like `push').
  183. ;; Let's call `hello' for each element in `list-of-names':
  184. (mapcar 'hello list-of-names)
  185. ;; Refine `greeting' to say hello to everyone in `list-of-names':
  186. (defun greeting ()
  187. (switch-to-buffer-other-window "*test*")
  188. (erase-buffer)
  189. (mapcar 'hello list-of-names)
  190. (other-window 1))
  191. (greeting)
  192. ;; Remember the `hello' function we defined above? It takes one
  193. ;; argument, a name. `mapcar' calls `hello', successively using each
  194. ;; element of `list-of-names' as the argument for `hello'.
  195. ;; Now let's arrange a bit what we have in the displayed buffer:
  196. (defun replace-hello-by-bonjour ()
  197. (switch-to-buffer-other-window "*test*")
  198. (goto-char (point-min))
  199. (while (search-forward "Hello")
  200. (replace-match "Bonjour"))
  201. (other-window 1))
  202. ;; (goto-char (point-min)) goes to the beginning of the buffer.
  203. ;; (search-forward "Hello") searches for the string "Hello".
  204. ;; (while x y) evaluates the y sexp(s) while x returns something.
  205. ;; If x returns `nil' (nothing), we exit the while loop.
  206. (replace-hello-by-bonjour)
  207. ;; You should see all occurrences of "Hello" in the *test* buffer
  208. ;; replaced by "Bonjour".
  209. ;; You should also get an error: "Search failed: Hello".
  210. ;;
  211. ;; To avoid this error, you need to tell `search-forward' whether it
  212. ;; should stop searching at some point in the buffer, and whether it
  213. ;; should silently fail when nothing is found:
  214. ;; (search-forward "Hello" nil 't) does the trick:
  215. ;; The `nil' argument says: the search is not bound to a position.
  216. ;; The `'t' argument says: silently fail when nothing is found.
  217. ;; We use this sexp in the function below, which doesn't throw an error:
  218. (defun hello-to-bonjour ()
  219. (switch-to-buffer-other-window "*test*")
  220. (erase-buffer)
  221. ;; Say hello to names in `list-of-names'
  222. (mapcar 'hello list-of-names)
  223. (goto-char (point-min))
  224. ;; Replace "Hello" by "Bonjour"
  225. (while (search-forward "Hello" nil 't)
  226. (replace-match "Bonjour"))
  227. (other-window 1))
  228. (hello-to-bonjour)
  229. ;; Let's colorize the names:
  230. (defun boldify-names ()
  231. (switch-to-buffer-other-window "*test*")
  232. (goto-char (point-min))
  233. (while (re-search-forward "Bonjour \\(.+\\)!" nil 't)
  234. (add-text-properties (match-beginning 1)
  235. (match-end 1)
  236. (list 'face 'bold)))
  237. (other-window 1))
  238. ;; This functions introduces `re-search-forward': instead of
  239. ;; searching for the string "Bonjour", you search for a pattern,
  240. ;; using a "regular expression" (abbreviated in the prefix "re-").
  241. ;; The regular expression is "Bonjour \\(.+\\)!" and it reads:
  242. ;; the string "Bonjour ", and
  243. ;; a group of | this is the \\( ... \\) construct
  244. ;; any character | this is the .
  245. ;; possibly repeated | this is the +
  246. ;; and the "!" string.
  247. ;; Ready? Test it!
  248. (boldify-names)
  249. ;; `add-text-properties' adds... text properties, like a face.
  250. ;; OK, we are done. Happy hacking!
  251. ;; If you want to know more about a variable or a function:
  252. ;;
  253. ;; C-h v a-variable RET
  254. ;; C-h f a-function RET
  255. ;;
  256. ;; To read the Emacs Lisp manual with Emacs:
  257. ;;
  258. ;; C-h i m elisp RET
  259. ;;
  260. ;; To read an online introduction to Emacs Lisp:
  261. ;; https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html
  262. ;; Thanks to these people for their feedback and suggestions:
  263. ;; - Wes Hardaker
  264. ;; - notbob
  265. ;; - Kevin Montuori
  266. ;; - Arne Babenhauserheide
  267. ;; - Alan Schmitt
  268. ;; - LinXitoW
  269. ;; - Aaron Meurer