🕷 zenspider.com

by ryan davis



sitemap
Looking for the Ruby Quickref?

My Emacs Setup, pt 2: packages

Published 2013-06-17 @ 12:00

Tagged emacs

This is part of the My Emacs Setup series.

OK… So this one I just figured out this week and have finally ironed out a lot of the wrinkles that was making me sour on elpa and el-get. I’m still sour on el-get. The damn thing is way too complex, poorly documented, and does too much. elpa (aka packages.el) does a much better job of doing one thing.

packages.el isn’t without its faults. I’ve found a number of functions that I’ve needed to be missing. I’ve added them and proposed them to the author so we’ll see how that goes.

Let’s dig in. This file is not loaded via autoload so that I can control exactly when it gets executed.

1
2
3
4
5
6
(require 'package)

(dolist (repo '(("elpa"      . "http://tromey.com/elpa/")
                ("marmalade" . "http://marmalade-repo.org/packages/")
                ("melpa"     . "http://melpa.milkbox.net/packages/")))
  (add-to-list 'package-archives repo))

This is totally normal boring stuff that gets all the repos I want added to the package-archives list.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
(unless (fboundp 'package-cleanup)
  (require 'cl)

  (defun package-version-for (package)
    (package-desc-vers (cdr (assoc package package-alist))))

  (defun package-delete-by-name (package)
    (package-delete (symbol-name package)
                    (package-version-join (package-version-for package))))

  (defun package-maybe-install (name)
    (or (package-installed-p name) (package-install name)))

  (defun package-cleanup (packages)
    "Remove packages not explicitly declared"
    (let ((removes (set-difference (mapcar 'car package-alist) packages)))
      (mapc 'package-delete-by-name removes))))

This defines package-maybe-install which will install a package if it isn’t installed already. It makes my emacs setup declarative and automatic and pretty. You’ll see it below.

It also defines package-cleanup which lets you remove any packages that are installed but not declared anymore. You’ll see why in a second.

The other two, package-version-for and package-delete-by-name are just make my life easier.

1
2
3
4
5
6
(defun rwd-package-manifest (&rest packages)
  (package-initialize)
  (condition-case nil ;; added to handle no-network situations
      (mapc 'package-maybe-install packages)
    (error (message "Couldn't install package. No network connection?")))
  (package-cleanup packages))

rwd-package-manifest lets me declare all my packages in a clean list, and ensures that any packages removed from the manifest are removed on the next run. This lets me keep all my packages under version control and spinning up a new login just consists of bringing up emacs and waiting for the installs to occur.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
(rwd-package-manifest 'ag
                      'expand-region
                      'magit
                      'mark-more-like-this
                      'mark-multiple
                      'p4
                      'paredit
                      'ruby-mode
                      'ssh
                      'window-number

                      ;; experimenting
                      'goto-last-change
                      'smex
                      'fuel

                      ;; questionable
                      ... lots of packages I installed in the past ...
                      )