1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
|
---
language: elisp
contributors:
- ["Bastien Guerry", "https://bzg.fr"]
- ["Saurabh Sandav", "http://github.com/SaurabhSandav"]
translators:
- ["Bastien Guerry", "https://bzg.fr"]
filename: learn-emacs-lisp-fr.el
lang: fr-fr
---
```scheme
;; Ceci est une introduction à Emacs Lisp en 15 minutes (v0.2d)
;;
;; Auteur : Bastien / @bzg2 / https://bzg.fr
;;
;; Prenez d'abord le temps de lire ce texte en anglais de Peter Norvig :
;; http://norvig.com/21-days.html
;;
;; Ensuite installez GNU Emacs 24.3 (ou une version ultérieure) :
;;
;; Debian : apt-get install emacs (voir les instructions pour votre distribution)
;; MacOSX : http://emacsformacosx.com/emacs-builds/Emacs-24.3-universal-10.6.8.dmg
;; Windows : http://ftp.gnu.org/gnu/windows/emacs/emacs-24.3-bin-i386.zip
;;
;; Vous trouverez plus d'informations sur l'installation :
;; http://www.gnu.org/software/emacs/#Obtaining
;; Avertissement important :
;;
;; Suivre ce tutoriel ne risque pas d'endommager votre ordinateur,
;; sauf si vous vous énervez au point de le jeter par terre. En tout
;; cas, je décline toute responsabilité en cas de problème.
;; Amusez-vous bien !
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Lancez Emacs.
;;
;; Tapez la touche "q" pour enlever le message d'accueil.
;;
;; Maintenant regardez la ligne grise au pied de la fenêtre :
;;
;; "*scratch*" est le nom de l'espace d'édition dans lequel vous vous
;; trouvez. Cet espace d'édition est appelé un "buffer".
;;
;; Le buffer scratch est le buffer par défaut quand on ouvre Emacs.
;; Vous n'éditez jamais de fichier directement : vous éditez des
;; buffers que vous pouvez sauvegarder dans des fichiers.
;;
;; "Lisp interaction" désigne le jeu de commandes disponible ici.
;;
;; Emacs a un jeu de commandes par défaut pour chaque buffer, et
;; plusieurs autres jeux de commandes disponibles quand vous activez
;; un mode particulier. Ici nous utilisons `lisp-interaction-mode',
;; qui propose des commandes pour évaluer et naviguer dans du code
;; Elisp.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Le point-virgule commence un commentaire partout sur une ligne.
;;
;; Les programmes Elisp sont composés d'expressions symboliques aussi
;; appelées "sexps" :
(+ 2 2)
;; Cette expression symbolique se lit "Ajouter 2 à 2".
;; Les sexps sont placées entre parenthèses, possiblement sur
;; plusieurs niveaux :
(+ 2 (+ 1 1))
;; Une expression symbolique contient des atomes ou d'autres
;; expressions symboliques. Dans les exemples ci-dessus, 1 et 2 sont
;; des atomes et (+ 2 (+ 1 1)) et (+ 1 1) des expressions symboliques.
;; Dans le mode `lisp-interaction-mode' vous pouvez évaluer les sexps.
;; Placez le curseur juste après la parenthèse fermante, tenez la
;; touche "Control" enfoncée et appuyez sur la touche "j" (soit le
;; raccourci "C-j").
(+ 3 (+ 1 2))
;; ^ curseur ici
;; `C-j' => 6
;; `C-j' insère le résultat de l'évaluation dans le buffer.
;; `C-x C-e' affiche le même résultat dans la ligne tout en bas
;; d'Emacs, appelée l' "echo area". On utilise en général `C-x C-e',
;; pour ne pas encombrer le buffer avec du texte inutile.
;; `setq' assigne une valeur à une variable :
(setq my-name "Bastien")
;; `C-x C-e' => "Bastien" (affiché dans l'*echo area*)
;; `insert' va insérer "Hello!" là où se trouve le curseur :
(insert "Hello!")
;; `C-x C-e' => "Hello!"
;; Nous utilisons `insert' avec un seul argument "Hello!", mais
;; nous pouvons passer plus d'arguments - ici nous en passons deux :
(insert "Hello" " world!")
;; `C-x C-e' => "Hello world!"
;; Vous pouvez utiliser des variables au lieu de chaînes de caractères :
(insert "Hello, I am " my-name)
;; `C-x C-e' => "Hello, I am Bastien"
;; Vous pouvez combiner les sexps en fonctions :
(defun hello () (insert "Hello, I am " my-name))
;; `C-x C-e' => hello
;; Vous pouvez évaluer les fonctions :
(hello)
;; `C-x C-e' => Hello, I am Bastien
;; Les parenthèses vides dans la définition de la fonction signifient
;; qu'elle ne prend pas d'argument. Mais toujours utiliser `my-name'
;; est ennuyant, demandons à la fonction d'accepter un argument (ici
;; l'argument est appelé "name") :
(defun hello (name) (insert "Hello " name))
;; `C-x C-e' => hello
;; Maintenant appelons la fonction avec la chaîne de caractères "you"
;; comme valeur de son unique argument :
(hello "you")
;; `C-x C-e' => "Hello you"
;; Youpi!
;; Faites une pause.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Maintenant ouvrez un nouveau buffer appelé "*test*" dans une
;; nouvelle fenêtre :
(switch-to-buffer-other-window "*test*")
;; `C-x C-e'
;; => [l'écran a deux fenêtres et le curseur est dans le buffer *test*]
;; Placez la souris sur la fenêtre du haut et cliquez-gauche pour
;; retourner dans cette fenêtre. Ou bien utilisez `C-x o' (i.e. tenez
;; control-x appuyé et appuyez sur o) pour aller dans l'autre fenêtre
;; interactivement.
;; Vous pouvez combiner plusieurs sexps avec `progn' :
(progn
(switch-to-buffer-other-window "*test*")
(hello "you"))
;; `C-x C-e'
;; => [L'écran a deux fenêtres et le curseur est dans le buffer *test*]
;; Maintenant si ça ne vous dérange pas, je vais arrêter de vous
;; demander de faire `C-x C-e' : faites-le pour chaque sexp qui suit.
;; Retournez toujours dans le buffer *scratch* avec la souris ou `C-x o'.
;; Il est souvent utile d'effacer le contenu du buffer :
(progn
(switch-to-buffer-other-window "*test*")
(erase-buffer)
(hello "there"))
;; Ou d'aller à l'autre fenêtre :
(progn
(switch-to-buffer-other-window "*test*")
(erase-buffer)
(hello "you")
(other-window 1))
;; Vous pouvez associer une valeur à une variable locale avec `let' :
(let ((local-name "you"))
(switch-to-buffer-other-window "*test*")
(erase-buffer)
(hello local-name)
(other-window 1))
;; Dans ce cas pas besoin d'utiliser `progn' puisque `let' combine
;; aussi plusieurs sexps.
;; Mettons en forme une chaîne de caractères :
(format "Hello %s!\n" "visitor")
;; %s désigne l'emplacement de la chaîne, remplacé par "visitor".
;; \n est le caractère de saut de ligne.
;; Améliorons notre fonction en utilisant "format" :
(defun hello (name)
(insert (format "Hello %s!\n" name)))
(hello "you")
;; Créons une autre fonction qui utilise `let' :
(defun greeting (name)
(let ((your-name "Bastien"))
(insert (format "Hello %s!\n\nI am %s."
name ; l'argument de la fonction
your-name ; la variable "let-bindée" "Bastien"
))))
;; Et évaluons-la :
(greeting "you")
;; Certaines fonctions sont interactives :
(read-from-minibuffer "Enter your name: ")
;; Évaluer cette fonction va renvoyer ce que vous avez saisi dans le
;; minibuffer.
;; Faisons que notre fonction `greeting' vous demande votre nom :
(defun greeting (from-name)
(let ((your-name (read-from-minibuffer "Enter your name: ")))
(insert (format "Hello!\n\nI am %s and you are %s."
from-name ; l'argument de la fonction
your-name ; la variable "let-bindée", entrée dans le minibuffer
))))
(greeting "Bastien")
;; Complétons la fonction pour qu'elle affiche le résultat dans
;; l'autre fenêtre :
(defun greeting (from-name)
(let ((your-name (read-from-minibuffer "Enter your name: ")))
(switch-to-buffer-other-window "*test*")
(erase-buffer)
(insert (format "Hello %s!\n\nI am %s." your-name from-name))
(other-window 1)))
;; Maintenant testons :
(greeting "Bastien")
;; Faites une pause.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Stockons une liste de noms :
(setq list-of-names '("Sarah" "Chloe" "Mathilde"))
;; Récupérez le premier élément de la liste avec `car' :
(car list-of-names)
;; Récupérez tous les élements sauf le premier avec `cdr' :
(cdr list-of-names)
;; Ajoutez un élément au début avec `push' :
(push "Stephanie" list-of-names)
;; Note : `car' et `cdr' ne modifient pas la liste, mais `push' oui.
;; C'est une différence importante : certaines fonctions n'ont pas
;; d'effets de bord (comme `car') et d'autres oui (comme `push').
;; Évaluons `hello' pour tous les éléments dans `list-of-names' :
(mapcar 'hello list-of-names)
;; Améliorons `greeting' pour dire hello aux noms de `list-of-names' :
(defun greeting ()
(switch-to-buffer-other-window "*test*")
(erase-buffer)
(mapcar 'hello list-of-names)
(other-window 1))
(greeting)
;; Vous vous souvenez de la fonction `hello' définie ci-dessus ? Elle
;; prend seulement un argument, un nom. `mapcar' appelle `hello' en
;; utilisant successivement chaque élément de `list-of-names' comme
;; argument de `hello'.
;; Maintenant arrangeons un peu ce qui est affiché dans le buffer :
(defun replace-hello-by-bonjour ()
(switch-to-buffer-other-window "*test*")
(goto-char (point-min))
(while (search-forward "Hello")
(replace-match "Bonjour"))
(other-window 1))
;; (goto-char (point-min)) va au début du buffer.
;; (search-forward "Hello") cherche la chaîne "Hello".
;; (while x y) évalue la sexp(s) y tant que x renvoie quelque chose.
;; Si x renvoie `nil' (rien), nous sortons de la boucle.
(replace-hello-by-bonjour)
;; Vous devriez voir toutes les occurrences de "Hello" dans le buffer
;; *test* remplacées par "Bonjour".
;; Vous devriez aussi avoir une erreur : "Search failed: Hello".
;;
;; Pour éviter cette erreur, il faut dire à `search-forward' si la
;; recherche doit s'arrêter à un certain point du buffer, et si elle
;; doit s'arrêter silencieusement si aucune chaîne n'est trouvée.
;; (search-forward "Hello" nil t) fait ça :
;; L'argument `nil' indique que la recherche n'est pas limitée à une
;; position. L'argument `t' indique de s'arrêter silencieusement si
;; rien n'est trouvé.
;; Nous utilisons cette sexp dans la fonction ci-dessous, qui ne
;; renvoie pas d'erreur :
(defun hello-to-bonjour ()
(switch-to-buffer-other-window "*test*")
(erase-buffer)
;; Dit hello aux noms de `list-of-names'
(mapcar 'hello list-of-names)
(goto-char (point-min))
;; Remplace "Hello" par "Bonjour"
(while (search-forward "Hello" nil t)
(replace-match "Bonjour"))
(other-window 1))
(hello-to-bonjour)
;; Mettons les noms en gras :
(defun boldify-names ()
(switch-to-buffer-other-window "*test*")
(goto-char (point-min))
(while (re-search-forward "Bonjour \\(.+\\)!" nil t)
(add-text-properties (match-beginning 1)
(match-end 1)
(list 'face 'bold)))
(other-window 1))
;; Cette fonction introduit `re-search-forward' : au lieu de chercher
;; la chaîne "Bonjour", nous cherchons un motif ("pattern" en anglais)
;; en utilisant une "expression régulière" (le préfixe "re-" signifie
;; "regular expression").
;; L'expression régulière est "Bonjour \\(.+\\)!" et se lit :
;; la chaîne "Bonjour ", et
;; un groupe de | c'est la syntaxe \\( ... \\)
;; n'importe quel caractère | c'est le .
;; une ou plusieurs fois | c'est le +
;; et la chaîne "!".
;; Prêt ? Testons !
(boldify-names)
;; `add-text-properties' ajoute des propriétés textuelles telles que
;; des "faces" (une "face" définit la fonte, la couleur, la taille et
;; d'autres propriétés du texte.)
;; Et voilà, c'est fini. Happy hacking!
;; Si vous voulez en savoir plus sur une variable ou une fonction :
;;
;; C-h v une-variable RET
;; C-h f une-fonction RET
;;
;; Pour lire le manuel Emacs Lisp avec Emacs :
;;
;; C-h i m elisp RET
;;
;; Pour lire en ligne une introduction à Emacs Lisp :
;; https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html
;; Merci à ces personnes pour leurs retours et suggestions :
;; - Wes Hardaker
;; - notbob
;; - Kevin Montuori
;; - Arne Babenhauserheide
;; - Alan Schmitt
;; - LinXitoW
;; - Aaron Meurer
```
|