Syncing Required Packages in Emacs

December 30, 2013

I use Emacs on several different computers. To keep my configuration consistent across all of them, I do what many people do and made the ~/.emacs.d directory a git repository. I don’t like to keep copies of all of the Elisp extensions that I use, such as paredit and geiser, in this repository. Instead, I prefer to use package.el (introduced in Emacs 24) with the MELPA repository. This saves me from having to manually keep all of the extensions I use up-to-date, but requires another method to keep useful packages in sync between computers.

There’s a project called Pallet that solves this problem, but it was too heavy for my liking. Instead, I wrote a short function that simply iterates over a list of required packages and installs those that are not currently installed.

;; Additional packages that I use.
(setq required-packages
      '(better-defaults
        elfeed
        geiser
        ido-ubiquitous
        js2-mode
        magit
        paredit
        rainbow-delimiters
        smex))

(defun install-missing-packages ()
  "Install all required packages that haven’t been installed."
  (interactive)
  (mapc (lambda (package)
          (unless (package-installed-p package)
            (package-install package)))
        required-packages)
  (message "Installed all missing packages!"))

Now, it’s as easy as typing M-x install-missing-packages RET when starting Emacs for the first time on a new computer to download all of the extensions that I need. Note that before calling install-missing-packages you must have already initialized the package manager via the package-initialize function. This approach does require some manual bookkeeping in order to keep the required-packages list up-to-date with your workflow, but I haven’t found it to be problematic.

Update: If this solution is too simplistic for you, you should check out use-package, which reddit user lunayorn pointed out to me. Thanks!

Check out the comments on reddit.