-
-
Notifications
You must be signed in to change notification settings - Fork 25
Expand file tree
/
Copy pathelispelem.texi
More file actions
4212 lines (3615 loc) · 179 KB
/
elispelem.texi
File metadata and controls
4212 lines (3615 loc) · 179 KB
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
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\input texinfo @c -*- texinfo -*-
@c %**start of header
@setfilename elispelem.info
@settitle Emacs Lisp Elements
@documentencoding UTF-8
@documentlanguage en
@set MAINTAINERSITE @uref{https://protesilaos.com,maintainer webpage}
@set MAINTAINER Protesilaos Stavrou
@set MAINTAINEREMAIL @email{info@protesilaos.com}
@set MAINTAINERCONTACT @uref{mailto:info@protesilaos.com,contact the maintainer}
@c %**end of header
@copying
Copyright (C) 2025 Protesilaos Stavrou
@quotation
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with no
Invariant Sections, with the Front-Cover Texts being “A GNU Manual,” and
with the Back-Cover Texts as in (a) below. A copy of the license is
included in the section entitled “GNU Free Documentation License.”
(a) The FSF’s Back-Cover Text is: “You have the freedom to copy and
modify this GNU manual.”
@end quotation
@end copying
@dircategory Emacs misc features
@direntry
* Emacs Lisp Elements: (elispelem). A big picture view of Emacs Lisp.
@end direntry
@finalout
@titlepage
@title Emacs Lisp Elements
@author Protesilaos Stavrou (@email{info@@protesilaos.com})
@page
@vskip 0pt plus 1filll
@insertcopying
@end titlepage
@ifnottex
@node Top
@top Emacs Lisp Elements
@insertcopying
This book, written by Protesilaos Stavrou, also known as ``Prot'',
provides a big picture view of the Emacs Lisp programming language.
The information furnished herein corresponds to stable version
2.0.0, released on 2025-12-10.
@itemize
@item
Official page: @uref{https://protesilaos.com/emacs/emacs-lisp-elements}
@item
Git repository: @uref{https://github.com/protesilaos/emacs-lisp-elements}
@end itemize
@end ifnottex
@menu
* Getting started with Emacs Lisp::
* Basics of how Lisp works::
* Evaluate Emacs Lisp::
* Introspecting Emacs::
* Side effect and return value::
* Symbols, balanced expressions, and quoting: Symbols balanced expressions and quoting.
* Buffers as data::
* Text has its own properties::
* Add metadata to symbols::
* What are major and minor modes::
* Hooks and the advice mechanism::
* Evaluate some elements inside of a list::
* Evaluation inside of a macro or special form::
* Mapping over a list of elements::
* The match data of the last search::
* Switching to another buffer, window, or narrowed state: Switching to another buffer window or narrowed state.
* Basic control flow with @code{if}, @code{cond}, and others: Basic control flow with @code{if} @code{cond} and others.
* Control flow with @code{if-let*} and friends::
* Autoloading symbols::
* Pattern match with @code{pcase} and related::
* Run some code or fall back to some other code::
* When to use a named function or a lambda function::
* Make your interactive function also work from Lisp calls::
* Emacs as a computing environment::
* Acknowledgements::
* GNU Free Documentation License::
* Indices::
@detailmenu
--- The Detailed Node Listing ---
Indices
* Function index::
* Variable index::
* Concept index::
@end detailmenu
@end menu
@node Getting started with Emacs Lisp
@chapter Getting started with Emacs Lisp
The purpose of this book is to provide you with a big picture view of
Emacs Lisp, also known as ``Elisp'' (@ref{Basics of how Lisp works}). This is
the programming language you use to extend Emacs. Emacs is a
programmable text editor: it interprets Emacs Lisp and behaves
accordingly. You can use Emacs without ever writing a single line of
code: it already has lots of features. Though you can, at any time,
program it to do exactly what you want by evaluating some Elisp that
either you wrote yourself or got from another person, such as in the
form of a package.
Programming your own text editor is both useful and fun. You can, for
example, streamline a sequence of actions you keep doing by combining
them into a single command that you then assign to a key binding: type
the key and---bam!---perform all the intermediate tasks in one go.
This makes you more efficient while it turns the editor into a
comfortable working environment.
The fun part is how you go about writing the code. There are no duties
you have to conform with. None! You program for the sake of
programming. It is a recreational activity that expands your horizons.
Plus, you cultivate your Elisp skills, which can prove helpful in the
future, should you choose to modify some behaviour of Emacs in a more
refined way.
Tinkering with Emacs is part of the experience. It teaches you to be
unapologetically opinionated about how your editor works. The key is
to know enough Elisp so that you do not spend too much time getting
frustrated because something trivial does not work. I am writing this
as a tinkerer myself with no background in computer science or
neighbouring studies: I learnt Emacs Lisp through trial and error by
playing around with the editor. My nominal goal was to improve certain
micro-motions I was repeating over and over. I sought efficiency only
to discover something much more profound and rewarding. Learning to
extend my editor has been a fulfilling experience and I am more
productive as a result. Emacs does what I want it to do and I am happy
with it.
Each chapter herein is generally short and to-the-point. Some are more
friendly to beginners while others dive deeper into advanced topics.
The progression from one chapter to the other should be linear, such
that you have enough information to proceed. There are links between
the chapters, exactly how a reference manual is supposed to be done.
You may then go back and forth to find what you need.
The text you find here is a combination of prose and code. The latter
may be actual Elisp or pseudo-code which captures the underlying
pattern. I encourage you to read this book either inside of Emacs or
with Emacs readily available. This way, you can play around with the
functions I give you, to further appreciate their nuances. The code I
write here is simple, trivial even. I want you to make sense of the
given principle and to not distract you with irrelevant complexity.
The goal is to show you how the pieces are put together. It is then up
to you to write elaborate programs.
The ``big picture view'' approach I am adopting is about covering the
concepts that I encounter frequently while working with Emacs Lisp.
This book is no substitute for the Emacs Lisp Reference Manual and
should by no means be treated as the source of truth for any of the
Elisp forms I comment on.
Good luck and enjoy!
@node Basics of how Lisp works
@chapter Basics of how Lisp works
Emacs Lisp is a programming language whose basic form has a simple
syntax: there are fundamental objects and lists of them. For example,
we have numbers and strings of characters inside double quotes (also
known as ``strings''). These are some of the fundamental objects.
Symbols are another fundamental object: they are made up of
alphanumeric characters and/or symbols. They will often look like
ordinary words, though they are not inside a pair of double quotes,
otherwise they would be strings. A symbol is commonly used as the
proper name of some variable or function: they ``symbolise'' something
other than themselves. Though symbols can be self-referential, such
that they symbolise themselves. For example, the value of @code{nil} is
@code{nil}.
Every computation is expressed as a list. This is a list of
fundamental objects or, in other words, one or more fundamental
objects inside of a pair of parentheses. The first element of the list
is the symbol of the function. The remaining elements, if any, are the
arguments passed to the function. ``Arguments'' here means that they are
the exact values that correspond to the specified parameters of the
function. A function has ``parameters'', meaning that it expects certain
inputs with which to carry out its work. Functions can define zero or
more parameters and internally decide how to handle them. Some
parameters can be mandatory and others optional. The number of
arguments must match that of the mandatory parameters, otherwise we
get an error.
Let us take a look at a basic function call. For example, this is how
we print a message, which we can then find in the @samp{*Messages*} buffer:
@lisp
(message "Hello world, this is my message to you!")
;; => "Hello world, this is my message to you!"
@end lisp
@findex message
Look at the syntax we have used. Here @code{message} is a symbol. It is the
first element of the list, therefore @code{message} is interpreted as the
proper name of a function. The second element of the list is a string
which, in this case, is understood as the first argument passed to the
@code{message} function. The entire expression is a list, hence the
parentheses around it. This expression is a function call: it performs
a computation.
When we use the term ``evaluate'' and derivatives, we are effectively
describing how we ask the computer to perform some computation for us,
such as to get the value of a variable or call a function for the work
it does and get back whatever it returns. In the above example, I
wrote the list and then evaluated it with @kbd{C-x C-e}
(@code{eval-last-sexp}). The text on the second line is my way of
representing the return value of this computation (@ref{Side effect and return value}).
What you just read explains most of Emacs Lisp. Though it can still be
difficult to understand a program because of how all the parentheses
line up. It can be hard to figure out where something starts and where
it ends when you have something like this:
@lisp
(upcase (message "Hello world, the number is %s" (+ 1 1 1)))
;; => "HELLO WORLD, THE NUMBER IS 3"
@end lisp
What we have above are three function calls inside of each other. If
you look at the closing three parentheses, you may panic as they are
already more than what you are used to. Relax! Elisp is cool because
you learn it by keeping calm. Let me read it to you from left to
right. Put the previous code block on one side and the following
explanation on the other, so that you can follow along more easily.
@itemize
@item
I am asked to evaluate this piece of Emacs Lisp.
@item
I have found a parenthesis, which means that this is a list that
stands for a function call.
@item
Let me check the first element of this list.
@item
I found the symbol @code{upcase}. Fine, I will use this.
@item
I know that @code{upcase} will work on a string to make all its letters
upper case (@ref{Introspecting Emacs}).
@item
Now I will check the next element of this function call. It has to
be the argument passed to @code{upcase}.
@item
The argument I have found starts with a parenthesis. This means that
it is not a fundamental object, but a function call in its own
right.
@item
Before I do anything with @code{upcase}, I have to evaluate this function
call.
@item
I found @code{message}, so I will use that. Time to check the next
element of this list.
@item
I found the string. Good! It has a @samp{%s} placeholder, which means
that there is another argument whose value will go where @samp{%s} now
is.
@item
Here is another parenthesis. We have a third function call.
@item
The symbol I found here is @samp{+}. This is a valid name for a function.
I will check what the arguments are.
@item
I checked the arguments. They are all numbers. So I will apply @samp{+}
to them.
@item
I got the result of this function call, which is the number @samp{3}. Now
I can go back to @code{message} with @samp{3} as its second argument (the
first argument is that string I found which had the @samp{%s}
placeholder). I have all the values to make it work.
@item
Fine, I called @code{message}. It returns a string.
@item
With this string I got back, I am finally ready to run @code{upcase}.
@end itemize
What I just described is how Emacs Lisp code is expressed in its
simplest form. This is enough to write a program.
Though you will eventually want to control when something is
evaluated. To this end, Emacs Lisp has the concept of quoting, which
is done with the single quote @samp{'}. When the single quote is added as a
prefix to an object, then it means ``do not evaluate this right now and
take it as-is'' (@ref{Symbols balanced expressions and quoting, , Symbols@comma{} balanced expressions@comma{} and quoting}). Using the
example from earlier with @code{message}:
@lisp
(message "I got this: %s" '(one two three))
;; => "I got this: (one two three)"
@end lisp
When Emacs reads this, it now finds only one function call, which
starts with the opening parenthesis for @code{message}. Then it reads one
list of data, which starts with the quoted list of symbols we have
there. By using the quote, we have successfully controlled where
evaluation should happen and where it should just take what we give it
without trying to interpret it.
Remember that when we use ``quote'' and related words in Emacs Lisp, we
are referring to this single quote, which is always a prefix. We do
not have pairs of single quotes around words or lists. No. It is only
a prefix for the object that follows.
If we did not have the single quote there, then we would effectively
be telling Emacs to evaluate @samp{(one two three)} as a function call
where @samp{one} would be the name of the function and the rest would be
its arguments. Unless you have a function whose proper name is @samp{one},
this will result in an error.
Earlier in this chapter I wrote ``every computation is expressed as a
list''. When you are writing Emacs Lisp, you may find that this does
not seem to be the case. For example, you can have a variable that you
evaluate on its own. Let us first declare a variable and give it a
string value:
@lisp
(defvar my-name "Protesilaos")
;; => my-name
@end lisp
We have now defined the symbol @code{my-name}, whose value is the string of
characters @samp{Protesilaos}. What you read here looks exactly like the
function calls we discussed in the previous examples. This is what
Lisp is all about. Now you may wonder what happens if we evaluate
@code{my-name} without doing a function call. Like this:
@lisp
my-name
;; => "Protesilaos"
@end lisp
@findex symbol-value
We get back the value. So is what I wrote earlier about everything
being a list incorrect? While you do not have any parentheses there,
it is helpful to think that Emacs makes things easier for you by
internally using the @code{symbol-value} function to interpret the symbol
@code{my-name}:
@lisp
(symbol-value 'my-name)
;; => "Protesilaos"
@end lisp
Note that the @code{symbol-value} here is important because it is the
function that takes the @code{my-name} symbol as an argument. But you
cannot evaluate a variable by writing it as a function call. This is
erroneous:
@lisp
(my-name)
;; => ERROR...
@end lisp
The error pertains to the fact that @code{my-name} is not a function: it is
a variable. Emacs has different namespaces for functions and
variables, meaning that you can have @code{my-name} as a symbol of a
function and as the symbol of a variable. Those are two separate
objects that we distinguish by how they are called. Let me show you:
@lisp
(defun my-name nil
"I am the function that returns this string which includes Protesilaos")
;; => my-name
@end lisp
Again, you notice in the code above the idea of everything being a
list: @code{defun} is what we call to interpret all the other elements. We
now have defined @code{my-name} as a function. All this function does is
return a string, which in practice is not really useful: we could have
done this with a variable. Though what we are interested in at present
is to understand how we can have @code{my-name} be both a variable and a
function which we tell apart based on how they are used in context. It
is time to test our work:
@lisp
;; Here I am evaluating the variable. When you evaluate a variable
;; directly, it is helpful to think that internally Emacs translates
;; your request to something like this: (symbol-value 'my-name)
my-name
;; => "Protesilaos"
;; Here I am evaluating the function.
(my-name)
;; => "I am the function that returns this string which includes Protesilaos"
@end lisp
What we have discussed thus far should help you make sense of all
these nested parentheses you will be dealing with when working with
Emacs Lisp. As you gain more experience, you will discover cases where
the syntax varies slightly (@ref{Basic control flow with @code{if} @code{cond} and others, , Basic control flow with @code{if}@comma{} @code{cond}@comma{} and others}).
This is because programmers want to economise on typing the same
things over and over, so they design ``special forms'' or ``Lisp macros''
that handle some things internally (@ref{Evaluation inside of a macro or special form}).
Specifically, you will encounter cases where quoting seems to be
different than what you have learnt here. Worry not. The principles are
the same. Those exceptions will ultimately be easy to reason about.
To avoid complex language such as ``a list of list of lists with quoted
lists and fundamental objects'' we use the term ``expression''. In
general, an expression is anything that Emacs can evaluate, be it a
list, list of lists, or symbol (@ref{Symbols balanced expressions and quoting, , Symbols@comma{} balanced expressions@comma{} and quoting}).
@node Evaluate Emacs Lisp
@chapter Evaluate Emacs Lisp
@cindex The freedom and uniformity of Emacs
Everything you do in Emacs calls some function (@ref{Basics of how Lisp works}).
Click a button? That is a function. Write a few words? That is a
series of functions. Use the arrow keys to move around? Functions;
functions all the way down! Emacs evaluates Emacs Lisp code, reading
the return values while dealing with side effects (@ref{Side effect and return value}).
The fact that a computer program does computation is not peculiar to
Emacs. What is special is the combination of two qualities: (i) Emacs
is free software and (ii) it is extended in the same programming
language it is written in. Its inherent freedom means that every
single line of code that is evaluated is available to you for
potential inspection, modification, and redistribution (@ref{Introspecting Emacs}).
Nothing is hidden from you. While the uniform extensibility
through Emacs Lisp means that the code you are reading and the code
you are writing are treated the same way. You do not need to learn
different, typically incompatible, programming languages or
configuration formats to make Emacs perform the computations you
want. Emacs Lisp is all there is.
Freedom and uniformity of computation together give you maximum
control over your text editor (@ref{Emacs as a computing environment}). The
promise, then, is that learning to program in Elisp grants you access
to the full power of Emacs, such that you do exactly what you want
with it, given that you also understand some basic concepts such as
buffers and text manipulation (@ref{Buffers as data}).
@cindex Interactive functions are commands
You type a key on your keyboard and a character is written to the
current buffer at the point where the cursor is. This is a function
bound to a key. It actually is an interactive function, because you
are calling it via a key binding rather than through some other Emacs
Lisp program (the latter is also described as ``calling it from Lisp''
or ``Lisp call''). Interactive functions are known as ``commands''. They
are computations which we can invoke interactively on demand.
Though do not let the implementation detail of interactivity distract
you from the fact that every single action you perform in Emacs
involves the evaluation of Emacs Lisp. A command will typically rely
on the computations of other functions to do its work. For example, if
I have a function that increments a list of numbers, I am internally
calling another function for adding one number to another, and then
yet another function to apply this operation over each element of the
list (@ref{Mapping over a list of elements}).
@cindex M-x shows evaluated or autoloaded commands
@findex execute-extended-command
Apart from direct key bindings, the other pattern of interaction is
with the @kbd{M-x} (@code{execute-extended-command}) key: it produces
a minibuffer prompt that asks you to select a command by its name. You
press the @kbd{RET} key and Emacs proceeds to execute the command
you selected. What you get in this prompt is a list of all the
commands that have currently been evaluated or automatically loaded
(@ref{Autoloading symbols}).
@findex eval-last-sexp
@findex eval-buffer
@findex eval-region
Emacs can evaluate Elisp code from anywhere. Normally, you would want
to do this in a buffer whose major mode is designed for editing Emacs
Lisp (@ref{What are major and minor modes}). But Emacs will blithely
evaluate any Elisp expression from any buffer, including those whose
major mode is not designed to treat Elisp code in some special way. If
you have some Elisp in your buffer, you can place the cursor at the
end of its closing parenthesis and type @kbd{C-x C-e}
(@code{eval-last-sexp}). Similarly, you can use the commands @code{eval-buffer}
and @code{eval-region} to operate on the current buffer or highlighted
region, respectively. The @code{eval-buffer} only makes sense in a buffer
that contains only Elisp, otherwise you will probably get errors from
asking Emacs to evaluate text that does not correspond to known
functions or variables and whose syntax does not consist of lists.
To evaluate some code is to make its results available to the running
Emacs session. You are, in effect, teaching Emacs something new. It
will know about it for as long as the session is active and you have
not overwritten this knowledge, as it were, with some new definition
of it. This is how you add new functionality to Emacs, redefine
existing one, or simply get the value out of some code you are using.
@vindex buffer-file-name
The @code{eval-last-sexp} also works on symbols (@ref{Symbols balanced expressions and quoting, , Symbols@comma{} balanced expressions@comma{} and quoting}).
For example, if you place the cursor at the end of the variable
@code{buffer-file-name} and use @kbd{C-x C-e} (@code{eval-last-sexp}), you
will get the value of that variable, which is either @code{nil} or the file
system path to the file you are editing in the current buffer.
Internally, it is like evaluating @code{(symbol-value 'buffer-file-name)},
as we covered in the chapter about the basics of Lisp (@ref{Basics of how Lisp works}).
@findex eval-expression
Sometimes the above are not appropriate for what you are trying to do.
Suppose you intend to write a command that copies the file path of the
current buffer. To do that, you need your code to test the value of
the variable @code{buffer-file-name} (@ref{Buffers as data, , Buffers as data structures}). But you
do not want to type out @code{buffer-file-name} in your actual file, then
use one of the aforementioned commands for Elisp evaluation, and then
undo your edits. Such is a cumbersome way of doing what is needed,
plus it is prone to mistakes! The best way to run Elisp in the current
buffer is to type @kbd{M-:} (@code{eval-expression}): it opens the
minibuffer and expects you to write the code you want to evaluate.
Type @kbd{RET} from there to proceed. The evaluation is done with
the last buffer as current (the buffer that was current prior to
calling @code{eval-expression}). This is especially useful if you want to
do a quick test of some part of a bigger procedure you are working on.
Here is some Emacs Lisp you may want to try in (i) a buffer that
corresponds to a file versus (ii) a buffer that is not associated with
any file on disk, such as the @samp{*scratch*} buffer.
@lisp
;; Use `eval-expression' to evaluate this code in a file-visiting
;; buffer versus a buffer that does not visit any file.
(if buffer-file-name
(message "The path to this file is `%s'" buffer-file-name)
(message "Sorry mate, this buffer is not visiting a file"))
@end lisp
@findex ielm
When you are experimenting with code, you want to test how it behaves
and confirm you are getting the expected results out of it. Since Lisp
consists of lists that can feed into each other, you can evaluate
smaller snippets of code while working towards the final version of
the program. Use the command @code{ielm} to open an interactive shell for
Emacs Lisp evaluation. It puts you at a prompt where you can type any
Elisp and hit @kbd{RET} to evaluate it. The return value is
printed right below.
@findex lisp-interaction-mode
@vindex initial-major-mode
@findex eval-print-last-sexp
@findex eval-last-sexp
Alternatively, switch to the @samp{*scratch*} buffer. If it is using the
major mode @code{lisp-interaction-mode}, which is the default value of the
variable @code{initial-major-mode}, then you can move around freely in that
buffer and type @kbd{C-j} (@code{eval-print-last-sexp}) at the end of
some code to evaluate it. This works almost the same way as
@code{eval-last-sexp}, with the added effect of putting the return value
right below the expression you just evaluated.
@cindex Introspect Emacs Lisp
@vindex major-mode
@findex describe-variable
@findex describe-function
@findex describe-keymap
@findex describe-key
@findex describe-symbol
In addition to these, you can rely on the self-documenting nature of
Emacs to figure out what the current state is. For example, to learn
about the buffer-local value of the variable @code{major-mode}, you can do
@kbd{C-h v} (@code{describe-variable}), and then search for that
variable. The resulting @samp{*Help*} buffer will inform you about the
current value of @code{major-mode}. This help command and many others like
@code{describe-function}, @code{describe-keymap}, @code{describe-key}, and
@code{describe-symbol}, provide insight into what Emacs knows about a given
object. The @samp{*Help*} buffer will show relevant information, such as
the path to the file that defines the given function or whether a
variable is declared as buffer-local (@ref{Introspecting Emacs}).
@node Introspecting Emacs
@chapter Introspecting Emacs
@cindex Emacs is self-documenting
@findex describe-variable
Emacs is ``self-documenting'' because it is aware of its state and can
report on it. When you define a variable, such as @code{my-name}, Emacs
retains in its running memory the symbol @code{my-name} and its
corresponding value of, say, @samp{Protesilaos}. If you invoke the command
@code{describe-variable}, it will produce a minibuffer prompt from where
you can select @code{my-name} among all other known variables. Once you
select that, a @samp{*Help*} buffer will be displayed. There you will find
information about @code{my-name}, such as its current value, any
documentation it may have and whether it has a buffer-local value
(@ref{Buffers as data, , Buffers as data structures}).
At all times, you update the state of Emacs by evaluating Elisp code
(@ref{Evaluate Emacs Lisp}). Let us consider the example of a variable that
we define for the first time:
@lisp
(defvar my-name "Protesilaos"
"This is some documentation about my name.
A good Elisp program will document all the functions and variables it
provides. Emacs developers have a strong documentation culture. It
complements the software freedom we stand for, because it empowers users
to learn from the tools available to them and thus exercise their
freedom.")
@end lisp
@cindex The documentation culture of Emacs
@cindex Emacs is the epitome of the GNU project
@findex defvar
We use the special form @code{defvar} to declare @code{my-name} with an initial
value of @samp{Protesilaos} as a string (@ref{Evaluation inside of a macro or special form}).
The second line specifies the documentation of this variable.
Documentation strings, also known as ``docstrings'' are optional though
strongly recommended as a matter of convention. As you can tell from
the sample above, docstrings are how we make software freedom more
accessible to users. Like me, they can learn by reading this
information and then by trying to understand the code.
A combination of consistent reading habits and the ease of trial and
error that Emacs provides makes it possible to learn Elisp by doing
more with it, one small step at a time. This is how every Emacs user
can learn to program in Emacs Lisp or, at least, better understand
what their tool is doing. Such is the realisation of the promise of
free software: everyone, not just professional programmers, benefits
from it. And is why, in my opinion, Emacs epitomises the stated
objectives of the GNU project for software freedom: it incorporates
them and puts them to practice, all in one powerful program.
Once we evaluate the @code{defvar} for @code{my-name}, @code{describe-variable} will
produce a @samp{*Help*} buffer with the following contents about it:
@example
my-name’s value is "Protesilaos"
This is some documentation about my name.
A good Elisp program will document all the functions and variables it
provides. Emacs developers have a strong documentation culture. It
complements the software freedom we stand for, because it empowers users
to learn from the tools available to them and thus exercise their
freedom.
@end example
Now go to the source code of @code{my-name} and modify its value to @samp{Prot}
between double quotes. Then invoke the command @code{eval-defun} to
evaluate the definition anew. If you now call @code{describe-variable}, you
will get a @samp{*Help*} buffer with the updated value. This is how Emacs
works for all symbols it has evaluated. When the source code is in a
file, the @samp{*Help*} buffer will include a link to it. If you find such
a link, click on it to navigate to the file and at the locus where the
source code is.
@findex describe-variable
@findex describe-function
@findex describe-keymap
@findex describe-key
@findex describe-symbol
Depending on how the code is written, Emacs will have access to
metadata that can feed into those @samp{*Help*} buffers, among other uses.
For example, when a variable is defined, it can specify its original
value (@ref{Add metadata to symbols}). What matters at this point is that
Emacs will always know what the current state is. Make a habit out of
using the commands @code{describe-variable}, @code{describe-function},
@code{describe-keymap}, @code{describe-key}, and @code{describe-symbol}, among
others, whenever you have a question about what Emacs knows.
Do this before you search for further information online: it will
teach you to rely more on the primary source of Emacs and less on
secondary sources on the Internet. Plus, the resulting @samp{*Help*}
buffers will link you to the source code, from where you may learn
something more than just what you are searching for, such as how a
certain function is autoloaded (@ref{Autoloading symbols}). This is how you
build up your capacity for working with Elisp, which is how you get to
extend Emacs the way you want.
@node Side effect and return value
@chapter Side effect and return value
Emacs Lisp has functions. They take inputs and produce outputs. In its
purest form, a function is a computation that only returns a value: it
does not change anything in its environment. The return value of a
function can be used as input for another function, in what
effectively is a chain of computations. You can thus rely on a
function's return value to express something like ``if this works the
way I expect, then also do this other thing, otherwise do something
else or even nothing''.
Elisp is the language that extends and controls Emacs. This means that
it also affects the state of the editor. When you run a function, it
can make permanent changes, such as to insert some text at the point
of the cursor, delete a buffer, create a new window, permanently
change the value of some variable or function, and so on. These
changes may have an impact on future computations. For example, if the
previous function deleted a certain buffer, the next function which
was supposed to write to that same buffer can no longer do its job:
the buffer is gone! We call all these changes to the environment ``side
effects''. They are the byproducts of the computation, which itself
results in some value, i.e. the ``return value''.
When you write Elisp, you have to account for both the return value
and the side effects. If you are sloppy, you will get unintended
results caused by all those ill-considered changes to the environment.
But if you use side effects meticulously, you use Elisp to its full
potential. For instance, imagine you define a function that follows
the logic of ``create a buffer, go there, write some text, save the
buffer to a file at my preferred location, and then come back where I
was before I called this function, while leaving the created buffer
open''. All these are side effects and they are all instrumental to
your goal. Your function may have some meaningful return value as well
that you can employ as the input of another function. For example,
your function could return the buffer object it generated, so that the
next function can do something useful with it like display that buffer
in a separate frame and make its text larger.
The idea is to manipulate the state of the editor, to make Emacs do
what you envision. Sometimes this means your code has side effects. At
other times, side effects are useless or even run counter to your
intended patterns of behaviour. You will keep refining your intuition
about what needs to be done as you gain more experience and expand the
array of your skills (@ref{Symbols balanced expressions and quoting, , Symbols@comma{} balanced expressions@comma{} and quoting}). No
problem; no stress!
@node Symbols balanced expressions and quoting
@chapter Symbols, balanced expressions, and quoting
@cindex Define a simple function
To someone not familiar with Emacs Lisp, it is a language that has so
many nested parentheses (@ref{Basics of how Lisp works})! Here is a simple
function definition:
@lisp
(defun my-greet-person (name)
"Say hello to the person with NAME."
(message "Hello %s" name))
@end lisp
@findex message
@findex view-echo-area-messages
I just defined the function with the name @code{my-greet-person}. It has a
list of parameters, specifically, a list of one parameter, called
@samp{name}. Then is the optional documentation string, which is for users
to make sense of the code and/or understand the intent of the function
(@ref{Introspecting Emacs}).
By convention, we write in the imperative voice (``Say hello and do
THIS'' instead of ``Says hello and does THIS'') and use upper case
letters to refer to the parameters or something that works as a
placeholder. Even in that parenthetic comment I made about the
imperative voice I followed the convention of using all capital
letters to denote a variable/placeholder with @samp{THIS}. Looks neat!
@code{my-greet-person} takes @samp{name} as input and passes it to the function
@code{message} as an argument to ultimately print a greeting. The @code{message}
function returns the string it formats and also produces the side
effect of appending it to the @samp{*Messages*} buffer. You can visit the
@samp{*Messages*} buffer directly with @kbd{C-h e} (@code{view-echo-area-messages}).
At any rate, this is how you call @code{my-greet-person} with the one
argument it expects:
@lisp
(my-greet-person "Protesilaos")
@end lisp
Now do the same with more than one parameters:
@lisp
(defun my-greet-person-from-country (name country)
"Say hello to the person with NAME who lives in COUNTRY."
(message "Hello %s of %s" name country))
@end lisp
And call it thus:
@lisp
(my-greet-person-from-country "Protesilaos" "Cyprus")
@end lisp
Even for the most basic tasks, you have parentheses everywhere: the
uniformity of Lisp means that we have lists all the way down! These
actually establish a clear structure, which make it easier to reason
about your program. If Lisp does not feel easy right now, it is
because you are not used to it yet. Once you do, there is no going
back.
@cindex Lisp languages are all about lists
The basic idea of any dialect of Lisp, Emacs Lisp being one of them,
is that you have parentheses which delimit lists. A list consists of
elements. Lists are either evaluated to produce the results of some
computation or returned as they are for use in some other evaluation
(@ref{Side effect and return value}):
@table @asis
@item The list as a function call
When a list is evaluated, the first
element is the name of the function and the remaining elements are
the arguments passed to it. You already saw this play out above with
how I called @code{my-greet-person} with @samp{"Protesilaos"} as its argument.
Same principle for @code{my-greet-person-from-country}, with
@samp{"Protesilaos"} and @samp{"Cyprus"} as its arguments.
@item The list as data
When a list is not evaluated, then none of its
elements has any special meaning at the outset. They are all
returned as a list of elements without further changes. When you do
not want your code to be evaluated, you prefix it with a single
quote character. For example, @samp{'("Protesilaos" "Prot" "Cyprus")} is
a list of three elements that should be returned as-is. The quote
prefix can be applied to symbols as well, such as @code{(symbol-function
'my-greet-person)} to get the actual value out of the function
object whose symbol is @code{my-greet-person} (@ref{Basics of how Lisp works}).
@end table
@findex car
@findex cdr
Consider the latter case of lists as data, which you have not seen
yet. You have a list of elements and you want to get something out of
it. At the most basic level, the functions @code{car} and @code{cdr} return the
first element and the list of all remaining elements, respectively:
@lisp
(car '("Protesilaos" "Prot" "Cyprus"))
;; => "Protesilaos"
(cdr '("Protesilaos" "Prot" "Cyprus"))
;; => ("Prot" "Cyprus")
@end lisp
The single quote here is critical, because it instructs Emacs to not
evaluate the list. Otherwise, the evaluation of this list would treat
the first element, namely @samp{"Protesilaos"}, as the name of a function
and the remainder of the list as the arguments to that function. As
you do not have the definition of such a function, you get an error.
@findex list
@cindex Self-evaluating objects
Certain data types in Emacs Lisp are ``self-evaluating''. This means
that if you evaluate them, their return value is what you are already
working with. For example, the return value of the string of
characters @samp{"Protesilaos"} is @samp{"Protesilaos"}. This is true for
strings, numbers, keywords, symbols, and the special @code{nil} or @code{t}.
Here is a list with a sample of each of these, which you construct by
calling the function @code{list}:
@lisp
(list "Protesilaos" 1 :hello 'my-greet-person-from-country nil t)
;; => ("Protesilaos" 1 :hello my-greet-person-from-country nil t)
@end lisp
The @code{list} function evaluates the arguments passed to it, unless they
are quoted. The reason you get the return value without any apparent
changes is because of self-evaluation. Notice that @code{my-greet-person-from-country}
is quoted the same way we quote a list: we do not want to evaluate at
this moment, but only to include its symbol in the resulting list.
Without it, @code{my-greet-person-from-country} would be evaluated, which
would return an error of a void/undefined variable, unless that symbol
was also defined as a variable.
Pay close attention to the above code block and the resulting value I
included in the comment below. You will notice that @code{my-greet-person-from-country}
was quoted but is not quoted anymore. You can do this with any symbol
or list (@ref{Evaluate Emacs Lisp}). Every time you evaluate a quote
expression, you get back the expression without the quote. This means
that if you evaluate it again, you will get something different, such
as a function call, the value of a variable, or some error.
@cindex Quoting means to pass the expression to the next evaluation
@cindex Quoting means to avoid the evaluation right now
As such, it is helpful to think of the single quote prefix as an
instruction to ``do not evaluate this right now, but pass it over to
the next evaluation''. In its simplest form though, you can just say
``do not evaluate the following'', which is exactly what happens. More
specifically, it is an instruction to not perform evaluation if it
would have normally happened in that context (@ref{Evaluate some elements inside of a list}).
In other words, you do not want to quote something inside of a quoted
list, because that is the same as quoting it twice. The way the quote
prefix works is that it passes the ``do not evaluate'' instruction to
its entire form, which in the case of a list is from one parenthesis
all the way to the closing matching parenthesis, covering everything
in between.
@lisp
;; This is the correct way:
'(1 :hello my-greet-person-from-country)
;; It is wrong to quote `my-greet-person-from-country' because the
;; entire list would not have been evaluated anyway. The mistake here
;; is that you are quoting what is already quoted, like doing
;; ''my-greet-person-from-country.
'(1 :hello 'my-greet-person-from-country)
@end lisp
@cindex Self-quoting objects
@cindex Unquoted symbols are evaluated
@findex symbol-value
Now you may be wondering why did we quote @code{my-greet-person-from-country}
but nothing else? The reason is that everything else you saw there is
effectively ``self-quoting'', i.e. the flip-side of self-evaluation.
Whereas @code{my-greet-person-from-country} is a symbol. A ``symbol'' is
usually a reference to something other than itself: it either
represents some computation---a function---or the value of a variable.
The symbols @code{nil} and @code{t} are special as they always refer to
themselves, meaning that when you evaluate them you get back exactly
what you evaluated (@ref{Add metadata to symbols}).
If you write a symbol without quoting it, you are effectively telling
Emacs ``give me the value this symbol represents''. In the case of
@code{my-greet-person-from-country}, you will get an error if you try that
because this symbol is not a variable and thus trying to get a value
out of it (the @code{symbol-value} to be precise) is not going to work.
@findex electric-pair-mode
To make it easier to describe our actions, we say that we are
evaluating ``expressions''. These are the objects that Emacs can
evaluate, such as a list, a list of lists, or fundamental objects in
their own right, like strings and symbols. These expressions need to
be balanced, meaning that either they are self-contained (e.g. a
string) or have parentheses around them and start and end where they
are supposed to be.
A common error in Elisp programs is to have unbalanced parentheses,
such as by forgetting one parenthesis at the end or mistyping an extra
one. Some programmers use packages that automatically balance Elisp
code. The built-in @code{electric-pair-mode} minor mode can help in this
regard (@ref{What are major and minor modes}). It automatically inserts
delimiters as pairs, so you will probably have the correct number of
parentheses each time. You may like to write code this way. Though it
is a matter of style. I am among those who prefer to do things
manually. I find such ``electric'' behaviour to be more trouble than it
is worth, given how I like to move around in a buffer. Perhaps, then,
the name ``electric'' draws from the ability of this mode to shock you
at times.
Keep in mind that Emacs Lisp has a concept of ``macro'', which basically
is a templating system to write code that actually expands into some
other code which is then evaluated. Macros are not some other language
with its own syntax. They are Emacs Lisp as well, only they make more
advanced use of quoting to control how evaluation is done and where.
Inside of a macro, you specify what is evaluated now as opposed to
later, meaning that the aforementioned may not apply directly to calls
that involve the macro, even if they are still used inside of the
macro's expanded form (@ref{Evaluation inside of a macro or special form}).
@findex lambda
@findex symbol-value
@findex symbol-function
As you expose yourself to more Emacs Lisp code, you will encounter
quotes that are preceded by the hash sign, like @samp{#'some-symbol}. This
``sharp quote'', as it is called, is the same as the regular quote with
the added semantics of referring to a function in particular. The
programmer can thus better articulate the intent of a given
expression, while the byte compiler may internally perform the
requisite checks and optimisations.
This is not merely a matter of semantics though. When you define a
symbol, there is a difference between storing in it a value or a
closure. A ``closure'' is an object consisting of a @code{lambda} with its
parameters and the body of form. In other words, defining a variable
and defining a value leads to a different result. Consider how the
functions @code{symbol-value} and @code{symbol-function} work: they both examine
a symbol. @code{symbol-value} treats the symbol as a variable and will
return its value, if any. @code{symbol-function} treats the symbol as a
function and returns its closure, if any.
Here is how it works:
@lisp
(defvar my-name "Protesilaos")
;; => my-name
(symbol-value 'my-name)
;; => "Protesilaos"
(symbol-function 'my-name)
;; => nil
(defun my-greet (person)
(format "Hello %s" person))
;; => my-greet
(symbol-function 'my-greet)
;; => #[(person) ((format "Hello %s" person)) nil]
(symbol-value 'my-greet)