Giovanni's Diary > Programming > Emacs >

Emacs-lisp Exercises

Here is a collection of some emacs lisp exercises that I come up by myself when learning the syntax. Emacs lisp is quite a simple language, and It is very powerful because It integrates with emacs "natively". You can easily manage buffers, windows, keys and UI with ease, so I want to dedicate some time into this.

Basics

Define a variable a using setq with the value "Hello World". Variables are used to store the state such as the current configuration of a package, so changing a variable's value directly changes the configuration.

(setq a "Hello-World")

Lists are the most common data structures in lisp. To declare a list, you need to prepend the white space separated elements enclosed int parentheses ( ) with a ' character. By default, a list does not evaluate It's element when the list itself gets evaluated. To break this rule, you can use the ` character to represent a list that may be "escaped" with the , character.

'(1 2 3)

Functions

Sum two numbers together. You can use the + function which takes any number of arguments that are either numbers or markers. To call a function, you surround the function name and Its argument in parentheses (...).

(+ 1 2)  

Call the message function to write a message to the message buffer. The message function works similarly to libc's printf.

To get information about function, you can call describe-function from the minibuffer.

(message "Hello World")

Define a function to write hello and another to write bye to the message buffer. Use defun, followed by the function name, arguments, and body.

(defun print-hello ()
  (message "Hello World!"))
(defun print-bye ()
  (message "Bye bye!"))

Define a function that says either hello or bye depending on whether the number of iteration taken from the user is odd or even.

(defun hello-or-bye (iterations)
  (setq a iterations)
  (while (>= a 0)
    (if (= 0 (% a 2))
  (print-hello)
      (print-bye))
    (setq a (- a 1))))

Iteration

Define a function to iterate over a list supplied by the user and output to a buffer in another window.

(defun iterate-now (list)
  "Print elements of a list"
  (setq mybuff (generate-new-buffer "*my output*"))
  (while list
    (print (car list) mybuff)
    (setq list (cdr list)))
  (switch-to-buffer-other-window mybuff))

;; Call that function
;;(iterate-now '(c c++ rust c3))

Custom types

Define a variable with defvar.

(defvar food-list '(bread pasta pizza) "A list of Italian food")

Define a variable with defcustom.

(defgroup italian nil "Italian things")
(defcustom city-list '("Rome" "Milan" "Trento")
  "A list of Italian cities"
  :group 'italian
  :type '(repeat string))
;;(iterate-now city-list)

Define a function that returns true only if Its argument is a list of strings.

(require 'cl-lib)
(defun is-string-list (obj)
  "Find out if the argument is a list of string"
  (and (listp obj)
       (cl-every #'stringp obj)))

;; Test the function
(if (not (is-string-list city-list))
    (message "upsie")
  (message "ok"))
(if (is-string-list 123)
    (message "upsie 2")
  (message "ok"))

Of course, the language goes really deep and I barely scratched the surface. I will keep doing exercises until I feel satisfied.


Travel: Emacs, Index