news

[Published in Open Source For You (OSFY) magazine, June 2016 edition.]

We have covered a lot of ground in our quest to learn the intricacies of GNU Emacs and we trust that you have found your long journey fulfilling. This is the last article in the series.

Introduction

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 customize it or extend it 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 filename extension .el and the byte-compiled files end with the .elc filename 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.

Comments

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 don't 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 file's 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
 ...
 ))

Literals

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.

Sexp

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 minibuffer.

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)

progn

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"

Functions

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"

let

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

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)

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!"

Looping

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.