Switching to straight.el
Some time after first hearing about it, then ignoring it, then seeing it mentioned everywhere, then understanding why it was useful, and then wanting to use it, I finally switched to the straight.el package manager. The primary reason was to better handle packages directly loaded from Git. The secondary reason was the attraction of a reproducible configuration.
The immediate impetus for the switch was finding a pair of packages I wanted to use that aren’t available on MELPA. I’ve encountered such packages before, but this time I was predisposed towards making the switch.
I was already loading packages with use-package, so, once
I had straight.el installed, I replaced :ensure t
with :straight t
. That left about a dozen
packages being loaded from cloned Git repositories with a homegrown :local
keyword in the
use-package
form. (I have a vague memory of there being a way to do that directly with
use-package, but if such a thing does exist, I must not have not known about it at the
time. use-package’s own :load-path
is similar but not
the same.) Before I updated those, I made sure I didn’t have
any uncommitted changes.
Once every :straight t
was in place, I restarted Emacs a few times, incrementally correcting the
order in which the packages were loaded as errors appeared. I had a bad habit of using nested
use-package
forms to conditionally load packages, but straight.el requires that reloading
your init-file must have the effect of running all of the same
,
so I updated all of those cases to use straight.el
-related functions
again:if
or
:after
instead of nesting. That seems like a more sensible approach in any case.
It took a few attempts to understand how to create the lockfile in my version-controlled Emacs
directory rather than the default application data directory. I ultimately needed to set
straight-profiles
before bootstrapping straight.el (shiv/local-dir
and shiv/my-file
being
unrelated helper functions that produce absolute paths):
Emacs Lisp(setf straight-build-dir (shiv/local-dir "straight")
straight-profiles `((nil . ,(shiv/my-file "straight.lockfile.el"))))
; normal straight.el bootstrap process follows
(defvar bootstrap-version)
(let ((bootstrap-file
(expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
(bootstrap-version 5))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously
"https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))
It took 20–25 minutes to build all the packages in my configuration from source, which I had to do twice because of a misunderstanding, and it took another two minutes to update the cache before producing a lockfile, which I also had to do multiple times as I searched for the right way to change the path.
There were a few packages with less simple requirements, which I had heretofore been loading in a more ad hoc fashion. Even then, the most complex—capnp-mode for Cap’n Proto files—took very little to configure correctly. Cloning the repository, narrowing it down to the Emacs Lisp code in a subdirectory, loading it, and associating the mode with the file extension is trivial:
Emacs Lisp(use-package capnp-mode
:straight (capnp-mode :host github :repo "capnproto/capnproto" :files ("highlighting/emacs/*.el"))
:mode "\\.capnp\\'")
On the whole, I’m very pleased to have been able to remove significant amounts of custom code and create a more reliable configuration in the bargain. I’m disappointed that pinning packages to tags isn’t possible yet, but recording Git revisions in the lockfile somewhat mitigates the omission.