A Beginner’s Guide to Useful Elisp Constructs: unless, file-directory-p, and More

Emacs Lisp (Elisp) is a small, elegant Lisp dialect that powers Emacs. Even if you’re not writing full Emacs packages, understanding a few essential constructs can help you automate tasks, customize your editor, and write smarter configuration code.

In this article, we’ll explore some of the most useful, everyday Elisp building blocks that every Emacs user should know — with small, practical examples you can immediately paste into your config.

1. unless — Execute Code Only When a Condition Is False

unless is the opposite of when.

  • when = do something if condition is true
  • unless = do something if condition is false

Syntax

(unless CONDITION
  BODY...)

Example: Load a theme only if it isn’t already active

(unless (member 'modus-operandi custom-enabled-themes)
  (load-theme 'modus-operandi t))

Example: Create a directory only if it does NOT exist

(unless (file-directory-p "~/.emacs.d/temp")
  (make-directory "~/.emacs.d/temp"))

2. file-directory-p — Check Whether a Path Is a Directory

Elisp provides several file-testing functions. One of the most frequently used is:

(file-directory-p "/path/")

It returns t if the path is a directory, nil otherwise.

Example: Verify a project folder

(if (file-directory-p "~/projects/my-app")
    (message "Project folder found!")
  (message "Directory missing!"))

Example: Create multiple directories if missing

(dolist (dir '("~/.cache/emacs" "~/.config/emacs/backups"))
  (unless (file-directory-p dir)
    (make-directory dir t)))

The t in make-directory allows creation of parent directories as well.

3. when — Run Code Conditionally (The Friendly if)

While if is the classic conditional, when is often easier to read when there is no “else” clause.

Syntax

(when CONDITION
  BODY...)

Example: Enable line numbers only in programming modes

(add-hook 'prog-mode-hook
          (lambda ()
            (when (not (bound-and-true-p display-line-numbers-mode))
              (display-line-numbers-mode 1))))

4. if — Two-Way Conditional Logic

When you need both “then” and “else” logic, stick with if.

Syntax

(if CONDITION
    THEN-BODY
  ELSE-BODY)

Example: Set a font depending on the system

(if (eq system-type 'darwin)
    (set-face-attribute 'default nil :font "Menlo-14")
  (set-face-attribute 'default nil :font "DejaVu Sans Mono-12"))

5. let — Create Local Variables

let is essential when you want to store values temporarily inside a function or block of code.

Syntax

(let ((var1 value1)
      (var2 value2))
  BODY...)

Example: Construct a file path dynamically

(let ((base-dir "~/.emacs.d/data")
      (filename "session.json"))
  (message "Loading %s" (expand-file-name filename base-dir)))

6. dolist — Loop Through a List

A clean way to iterate over items:

(dolist (item '(a b c))
  (message "Item: %s" item))

Example: Batch-create directories

(dolist (dir '("~/.emacs.d/logs" "~/.emacs.d/tmp" "~/.emacs.d/cache"))
  (unless (file-directory-p dir)
    (make-directory dir)))

7. and and or — Simple Logic Operators

Example: Only run if BOTH conditions are true

(when (and (file-exists-p "~/notes.org")
           (file-readable-p "~/notes.org"))
  (message "Notes are ready!"))

Example: Try multiple file locations

(or (file-exists-p "~/.emacs.d/init.el")
    (file-exists-p "~/.config/emacs/init.el")
    (message "No init file found!"))

8. Combining Them Into a Real-World Example

Here’s a practical snippet that uses everything we’ve covered:

(let ((cache-dir "~/.emacs.d/cache"))
  (unless (file-directory-p cache-dir)
    (make-directory cache-dir t))

  (when (file-exists-p "~/org/todo.org")
    (message "Todo file found!")))

This snippet:

  1. Creates a variable cache-dir
  2. Checks if the directory exists
  3. Creates it if missing
  4. Checks for a specific org-mode file
  5. Prints a message if it exists

These tiny constructs let you build surprisingly powerful Emacs customizations.

Conclusion

Learning a handful of simple Elisp constructs — such as unless, when, file-directory-p, if, and let — dramatically expands what you can automate and customize in Emacs. These are the everyday “bread and butter” tools used in nearly all Emacs configuration and package code.

If you understand these, you're already well on your way to writing clean, effective Emacs Lisp.

Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.
Please share this article on your favorite website or platform.