There’s tons of detailed information about Emacs LISP — aka Emacs Lisp, elisp, ELisp, and “oh my god they love parentheses” — out there. I just want my old “Babysteps” approach, so all the detailed sites won’t be so intimidating.
Gotta do it myself, I guess.
So far I have treated elisp as an arcane configuration language. But it’s so much more than that. It’s also an arcane programming language. I do love learning programming languages.
I’ll have an easier time configuring Emacs, and most likely get strange new ideas for ways to extend my frenemy text editing environment.
Using Emacs, of course! A little bit with the deep integration for both evaluation and documentation_ of Lisp. Probably a bit more with Org Babel, which provides a layer for evaluating code and exporting the results — say, for example, to a blog post like this one.
Expect side notes about Doom Emacs, since that’s the flavor I use lately.
Let’s get started
I looked up “Hello World in ELisp” and found something like this.
Want to write some Emacs Lisp? Here you go.
- open Emacs
(message "Hey World!")
- put your cursor — the point — just outside the closing parenthesis.
- Hit [[C-x e]]
- Emacs prints
() indicate an s-expression. That’s a symbolic expression, or
sexpr if you’re cool. S-expressions aren’t quite the atoms of a Lisp
program. There are smaller bits, like the symbol
message or the value
"Hey World!". But it’s the smallest useful element. Oh I know. S-expressions
are the molecules of a Lisp program.
No? How about words vs sentences? Okay, whatever.
This particular s-expression holds an ordered pair,
"Hey World!". Pair because there are two items. Ordered because the order
When ELisp sees an ordered pair, it knows what to do:
- figure out what it gets from the second thing
- hand that to the first thing
- hand that result to you
The part that feels magic is each of the items in the pair can be s-expressions
(sqrt (* 37 37)).
* is for multiplication. So we’re multiplying
proving to ourselves that
sqrt hands us back
37. It’s a bit of a
pointless example, but hey welcome to me learning stuff. And there’s my first
A Lisp program is pretty much just infinitely nested s-expressions.
And macros. Macros, near as I can tell, are infinitely nested s-expressions with gloves and a nice hat.
BTW I don’t know Lisp. I hope you did not come here expecting a tutorial.
When we have a question about ELisp functions, we don’t need to look everything up online. Emacs comes with notes.
- put point over
(message "Hey world!")
- hit [[C-h f]]
- see the prompt asking me to specify a function, with
- hit [[ENTER]]
- Learn things!
ELisp in Org Babel
This is great and all, but I am less concerned about live evaluation of ELisp. Org mode is more interesting to me. I could make my config smarter. For example, only tangle a section if it’s relevant for that machine.
And, of course, really handy for blogging about ELisp.
I need a code block written in a language that Babel knows. It should not surprise us that Babel knows ELisp.
I press C-c C-c with point over the code block.
I can also write my ELisp inline:
Written like this, Babel replaces my code with its result when
exports the post.
All right. That’s the very basics of evaluating ELisp in Emacs generally and Org mode in particular.
Let’s get back to the code, please. How do I do variables?
Displaying a variable
setq to set a variable for my name. identifiers can be pretty
much whatever. I’ll use lowercase letters and a hyphen.
format can smush it into a string for
format does its work and hands the result back to
message, which displays
Thing is, now
my-name is floating around forever what with being a global
What if I used a local variable instead?
But back out here it doesn’t exist.
You don’t see anything out here, but when I tried to C-c C-c that, Emacs complained:
I consider that a good thing. Global variables make me nervous, especially in long-running applications.
So I know how to set global or local variables. I know how to display them.
How to get them from the user?
Getting user input
Xah Lee gives a nice rundown on how to get user input.
read-string is the one I want.
read-string returns whatever I answer.
Let’s make a question prompt. The inside-out approach of nested evaluation confuses me a bit, so I’ll happily let Emacs indent things however it wants.
I did some things.
read-string puts the cursor right after the
question prompt. So to help myself while I’m figuring all this out, I
created some local variables.
question holds the question to be answered.
message holds the —
Wait, there’s already a global standard function called
It’s cool. By the time I need the function,
let is done and my variable
doesn’t exist. Still. I shouldn’t make this a habit.
Wrapping it in a function
I wasn’t planning on looking at functions today, but I’m more than halfway there already.
Use the defun macro to define functions. It’s similar enough to function definitions in other languages.
Though there are some differences right off the bat.
user input. ELisp requires I mark those as interactive_.
Other than that it’s similar enough to function definitions in other languages.
I already know how to call a function.
Okay, time to take my own hint. Good night!