A macro for configuring Emacs
Bump version to 0.2.1
Use full name in header
Allow edebugging in :when-loaded body


browse  log 



You can also use your local clone with git send-email.


The setup macro simplifies repetitive configuration patterns, by providing context-sensitive local macros in setup bodies.

For example, these macros:

(setup shell
  (let ((key (kbd "C-c s")))
    (:global key shell)
    (:bind key bury-buffer)))

(setup dired
  (:also-load dired-x)
  (:option (prepend dired-guess-shell-alist-user) '("" "xdg-open")
           dired-dwim-target t)
  (:hook auto-revert-mode))

(setup (:package paredit)
  (:hook-into scheme-mode lisp-mode))

will be replaced with the functional equivalent of

(global-set-key (kbd "C-c s") #'shell)
(with-eval-after-load 'shell
  (define-key shell-mode-map (kbd "C-c s") #'bury-buffer))

(with-eval-after-load 'dired
  (require 'dired-x))
(customize-set-variable 'dired-guess-shell-alist-user
                        (cons '("" "xdg-open")
(customize-set-variable 'dired-dwim-target t)
(add-hook 'dired-mode-hook #'auto-revert-mode)

(unless (package-install-p 'paredit)
  (package-install 'paredit))
(setq minor-mode-alist
      (delq (assq 'paredit-mode minor-mode-alist)
(add-hook 'scheme-mode-hook #'paredit-mode)
(add-hook 'lisp-mode-hook #'paredit-mode)

Additional "keywords" can be defined using setup-define. All known keywords are documented in the docstring for setup.


setup.el is part of GNU ELPA, and can be installed using package.el.


The setup macro is autoloaded, and can be used directly. The code generated by setup does not depend on setup.el, meaning that your initialization file can be byte-compiled more efficiently.


  1. The first element of a setup body can but does not have to be a name. That can be exploited to use setup in your own macros. I have this macro in my personal configuration, when I'm only interested in modifying user options:

    (defmacro setc (&rest args)
      "Customize user options using ARGS like `setq'."
      (declare (debug setq))
      `(setup (:option ,@args)))
  2. If you wish to define you own macros, use setup-define. In case the syntax is too cumbersome, you can use a macro like this:

    (defmacro defsetup (name signature &rest body)
      "Shorthand for `setup-define'.
    NAME is the name of the local macro.  SIGNATURE is used as the
    argument list for FN.  If BODY starts with a string, use this as
    the value for :documentation.  Any following keywords are passed
    as OPTS to `setup-define'."
      (declare (debug defun))
      (let (opts)
        (when (stringp (car body))
          (setq opts (nconc (list :documentation (pop body))
        (while (keywordp (car body))
          (let* ((prop (pop body))
                 (val `',(pop body)))
            (setq opts (nconc (list prop val) opts))))
        `(setup-define ,name
           (cl-function (lambda ,signature ,@body))

    To declare local macros more like defun or defmacro. Here is how the definition for :package could be rewritten:

    (defsetup :package (package)
      "Install PACKAGE if it hasn't been installed yet."
      :repeatable t
      :shorthand #'cadr
      `(unless (package-installed-p ',package)
           (package-install ',package)))


Bugs or patches can be submitted to my public inbox or via the GitHub mirror. Note that non-trivial contributions require a copyright assignment to the FSF.

This package is still young, so wishes, impressions and criticism are very appreciated. If you have anything to say, feel free to send an email to the aforementioned public inbox.


setup.el is distributed under the GPL v3 license.