We have covered a lot of ground in our quest to learn the intricacies of Emacs and we trust that you have found your long journey fulfilling. This is the last article in the series.
The GNU Emacs editor is written using Emacs Lisp and the C programming language. You can use GNU Emacs as an editor without knowing Emacs Lisp, but being familiar with it will help you customise it or extend it according to your needs. Emacs Lisp is a dialect of the Lisp programming language and is inspired by Maclisp and Common Lisp. The source files end with the file name extension .el and the byte-compiled files end with the .elc file name extension. You can also write scripts using Emacs Lisp and execute them as a batch operation. The code can thus be executed from the command line or from an executable file. Byte-compiling the source files can help you speed up the execution.
All comments begin with a semi-colon. An Emacs Lisp file usually has the following sections in the code, specified with three semi-colons. These always start in the left margin as shown below:
;;; Module --- Summary ;;; Commentary: ;;; Code: ;;; Module ends here
All comments outside functions begin with two semi-colons. The contents of the scratch buffer, shown below, are an example:
;; This buffer is for notes you dont want to save, and for Lisp evaluation. ;; If you want to create a file, visit that file with C-x C-f, ;; then enter the text in that files own buffer.
Comments inside functions use a single semi-colon, and if they span multiple lines, they must be neatly aligned. For example:
... (let* ((sexp (read (current-buffer))) ; using read here ; easier than regexp ; matching, esp. with ; different forms of ; MONTH ... ))
The basic data types are available in Emacs Lisp. Numbers can be represented by integers or floats. Integers can have their sign representation before the digit (+1, -2). Floating point numbers can be represented using a decimal point (3.1415) or with an exponent (314.15e-2). A character (S) is represented by its integer code (83), while a string is a list of characters enclosed within double quotes (A string).
A symbol is an object with a name. A keyword symbol is one that starts with a colon (:). A vector is an array and can contain different types ([1 two :three]). The Boolean values for true and false are t and nil respectively. A cons cell is an object with two slots. The first slot is called the CAR (Contents of the Address part of the Register number) and the second slot is called the CDR (Contents of the Decrement part of the Register number). A list is a series of linked cons cells. For example, in the list (A B), the CAR is A and the CDR is B.
Emacs Lisp uses prefix notation, which consists of an operation followed by operands (arguments). All programs are represented as symbolic expressions (sexp). For example, the + operation is applied to its arguments 1 and 2 in the following sexp:
(+ 1 2)
If you copy the above code in an Emacs buffer, you can evaluate the same by placing the cursor at the end of the expression and using the C-x C-e shortcut. The output 3 will be displayed in the mini buffer.
You can also have nested sexps, wherein the innermost expressions are evaluated first.
(+ 1 (* 2 3))
Similar to the + operation, you can use pre-defined keywords or functions in Emacs Lisp programs. The format function is similar to your printf statement in the C programming language.
(format Hello, World!)
You can store a value in a variable using the setq operation as shown below:
(setq IST Indian Standard Time) IST ; No enclosing parenthesis! ; produces Indian Standard Time
You can find the data type, using the type-of function. A few examples are shown below:
(type-of 1) ; produces integer (type-of 3.1415) ; produces float (type-of A string) ; produces string (type-of :foo) ; produces symbol (type-of t) ; produces symbol (type-of (1 2)) ; produces cons (type-of [1 two :three]) ; produces vector
In the Bash shell, you can escape evaluation by using the backslash. Similarly, you can prevent the Emacs Lisp interpreter from evaluating an expression using quotes. For example:
(+ 1 2) ; produces 3 (+ 1 2) ; produces the list (+ 1 2)
The progn statement is used to execute several sexps. For example:
(progn (setq title Introduction to Emacs Lisp) (setq author Robert J. Chassell) (format %s by %s title author)) ; produces Introduction to Emacs Lisp by Robert J. Chassell
You can define your own function using the defun built-in keyword. The say function simply prints the string Hello, World! in the following example:
(defun say () (format Hello, World!))
In order to execute the function, invoke it inside parenthesis, as shown below:
(say) ; produces Hello, World!
Arguments can be passed to a function. The square function is demonstrated below:
(defun square (x) (* x x)) (square 3) ; produces 9
You can also store a list of names and retrieve them using the car and cdr functions as illustrated below:
(setq teams (GL DD KKR MI SRH RPS RCB KXIP)) (car teams) ; produces GL (cdr teams) ; produces DD KKR MI SRH RPS RCB KXIP (car (cdr teams)) ; produces DD
The let statement allows you to bind a value to a variable in a local context. GNU Emacs 24 has lexical binding support. An example is given below:
(defun hello (name) (let ((new-name (concat Hello name))) new-name )) (hello Mark) ; produces Hello Mark
Conditions can be checked using the if and cond statements. The if statement takes a condition, and if the condition evaluates to true, the sexp immediately following the condition is executed. Otherwise, the else-form is evaluated. The syntax is:
(if condition then-form else-form)
Heres an example:
(if t (format True) (format False)) ; produces True
The when condition statement is a variant of the if statement written as a macro. Macros are an important feature of Lisp programming that allow you to extend the language. They are primarily code generators. If the when condition is true, then it evaluates the then-forms. The syntax and an example are given below:
(when condition then-forms) (when t (print Abracadabra!)) ; produces Abracadabra!
You can use the while statement to perform looping in Emacs Lisp. The body of the while loop is executed as long as the condition is true. An example that prints the numbers 0 to 4 is shown below:
(progn (setq i 0) (while (< i 5) (print i) (setq i (+ i 1))))
The dolist and dotimes macros can also be used for looping. The other approach is to use recursion. A literal definition in Emacs Lisp for computing the Fibonacci series is given below:
(defun fib (n) (cond ((= n 0) 0) ((= n 1) 1) (t (+ (fib (- n 1)) (fib (- n 2))))))
The cond control structure takes a series of clauses; each has a condition and a body-form. If any condition evaluates to true, the body-form is executed. Otherwise, it proceeds to the next clause.
An iterative version of the Fibonacci series is given below:
(defun fib (n) (fib-helper n 0 1)) (defun fib-helper (n a b) (if (= n 0) a (fib-helper (- n 1) b (+ a b)))) (fib 10) ; produces 55
The Emacs Lisp Cookbook is very handy (https://www.emacswiki.org/emacs/ElispCookbook).
You are encouraged to read An Introduction to Programming in Emacs Lisp at https://www.gnu.org/software/emacs/manual/eintr.html and the Emacs Lisp Reference Manual at https://www.gnu.org/software/emacs/manual/elisp.html.
The author is a free software developer at the Fedora project, and also a blogger. He co-maintains the Fedora Electronic Lab project.