Switching to straight.el from Emacs 26 builtin package.el
On switching to
straight.el from Emacs 26 builtin
Table of Contents
- Why switch?
- The process of changing over to
I’ve been using
package.el since emacs25. The
use-package notation came as part of the init files I’ve been using for YEARS from the Emacs Bootstrap website.
However, there were a couple of annoyances with
package.el, the top one being the
custom-set-variables` `package-selected-packages that would change each time packages were installed / reinstalled, and then again when you loaded the package list (which writes this variable to disk). And it’s in “alphabetical order” except that newly installed packages are placed at the head of the list. But then, when you restart emacs and loaded the package list, the whole list would be re-alphabetized again.
This was annoying for two reasons:
- The canonical package list was not maintained directly in user-specified files (i.e., my startup files), but indirectly in this variable maintained by emacs
- I sync my emacs startup files across multiple machines and platforms via a Git repo of my home directory dotfiles. The multiple iterations of removing or re/installing and synchronizing this package list on each platform and machine were updated was time-consuming busywork and imperfect at best.
straight.el solves the problem of maintaining package list directly in startup files, which solves both of those issues. Furthermore, seamless integrating git repositories of emacs packages, which can be locally edited, and even pointing to forked repos, is a strong appeal of
straight.el, when I am getting to the point of being comfortable reading and understanding Emacs Lisp in the package repositories.
The process of changing over to
There are two main steps to switch to
- Bootstrap the
straight.elinstall code snippet into your
- Convert and remove
package.elthings that are incompatible with
This post will not even delve into pointing to custom repos; see the
straight.el documentation for those details.
Step 1. Bootstrap
Using the “Getting started” in README.md as definitive guide, put the following code snippet into your Emacs
(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))
That’s it! And including this configuration here, since
straight.el has this nice property of being “backward compatible” with
package.el– all my current packages and settings were available directly via
straight.el by activating this functionality per:
;;;; Effectively replace use-package with straight-use-package ;;; https://github.com/raxod502/straight.el/blob/develop/README.md#integration-with-use-package (straight-use-package 'use-package) (setq straight-use-package-by-default t)
Again, that is placed in your
straight.el is bootstrapped. It effectively makes
use-package call sites in your startup files become
Step 2. Convert/Remove
You should remove any code that relates to
package.el; for example, references to
package-archives, and (if you’re using
use-package-always-ensure. While it is technically possible to use both
straight.elat the same time, there is no real reason to, and it might result in oddities like packages getting loaded more than once.
Below are the steps I took and representative edits I made to get my startup files switched over. Once the two main steps have been completed, (1. bootstrap and 2.
package.el removal parts) restart your Emacs session.
straight.el will happily clone all the package repositories referenced in your startup files, including any dependencies, and put those clone checkouts within
<user-emacs-directory>/striaght/. And it all just works, on both macOS and Ubuntu Linux. The first time takes a little longer to do all the network retrievals, of course…
All the following had to go. It was DELETED:
;;______________________________________________________________________ ;;;; package management related (require 'package) ;; (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/")) ;; for latest org-mode and org-plus-contrib (add-to-list 'package-archives '("org" . "https://orgmode.org/elpa/") t) ;; https://github.com/purcell/emacs.d/blob/master/lisp/init-elpa.el#L64 ;; (setq package-enable-at-startup nil) (package-initialize) (when (not package-archive-contents) (package-refresh-contents)) (unless (package-installed-p 'use-package) (package-install 'use-package)) ;; install packages automatically if not already present on your ;; system to be global for all packages (require 'use-package-ensure) (setq use-package-always-ensure t)
BUT WAIT… I still wanted to use MELPA and
M-x package-list-packages to peruse the MELPA repos… So I ended up with the following minimal
package.el config, placed after the
straight.el bootstrap and config:
;;;; package.el ;;; so package-list-packages includes them (require 'package) (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
This doesn’t harm the
straight.el installation, so for me it’s the best of both worlds.
I had numerous
:ensure t sprinkled through my startup files. And I sometimes had
:ensure <pkgname> or a specific load ordering placed in the file.
There is no need for
(use-package web-mode - :ensure t :after flycheck :bind (("C-c ]" . emmet-next-edit-point) ("C-c [" . emmet-prev-edit-point)
If there was a true dependency, I switched to
use-package, as it probably should have been handled that way anyway:
(use-package ivy-rich + :requires (counsel) :config (setq ivy-rich-path-style 'abbrev
;; https://github.com/raxod502/prescient.el (use-package company-prescient + :requires (prescient) :config (company-prescient-mode 1) (prescient-persist-mode 1)
Not strictly necessary, but startup speeds with
straight.el seem to have improved over
package.el so I ripped them out:
;; https://github.com/ardumont/markdown-toc ;; M-x markdown-toc-generate-or-refresh-toc -(use-package markdown-toc - :defer 2) +(use-package markdown-toc)
Get rid of
-;; keep packages updated automatically -;; https://github.com/rranelli/auto-package-update.el -(use-package auto-package-update - :init - (setq auto-package-update-last-update-day-filename (expand-file-name "last-package-update-day" temp-dir)) - :config - (setq auto-package-update-delete-old-versions t) - (auto-package-update-at-time "23:00") - ;; (setq auto-package-update-hide-results t) - ;; (setq auto-package-update-prompt-before-update t) - (auto-package-update-maybe)) -
straight.el has a bound method to sync all your locally specified package clones:
It can be executed directly
Refer to the docs at Automatic repository managment for more details.
Put in place
Straight from the
README: Installing Org with
-(use-package org + +;;______________________________________________________________________ +;;;; Installing Org with straight.el +;;; https://github.com/raxod502/straight.el/blob/develop/README.md#installing-org-with-straightel +(require 'subr-x) +(straight-use-package 'git) + +(defun org-git-version () + "The Git version of 'org-mode'. +Inserted by installing 'org-mode' or when a release is made." + (require 'git) + (let ((git-repo (expand-file-name + "straight/repos/org/" user-emacs-directory))) + (string-trim + (git-run "describe" + "--match=release\*" + "--abbrev=6" + "HEAD")))) + +(defun org-release () + "The release version of 'org-mode'. +Inserted by installing 'org-mode' or when a release is made." + (require 'git) + (let ((git-repo (expand-file-name + "straight/repos/org/" user-emacs-directory))) + (string-trim + (string-remove-prefix + "release_" + (git-run "describe" + "--match=release\*" + "--abbrev=0" + "HEAD"))))) + +(provide 'org-version) + +;; (straight-use-package 'org) ; or org-plus-contrib if desired + +(use-package org-plus-contrib :mode (("\\.org$" . org-mode)) - :ensure org-plus-contrib :bind ("C-c l" . org-store-link) ("C-c a" . org-agenda)
Note I can use
(use-package org-plus-contrib ... instead of
(straight-use-package org-plus-contrib ... since I’ve already configured it to behave that way (see above).
I didn’t know how difficult versus easy this was going to be before I started. Because of the nice “compatibility” features
straight.el has, it turned out to be rather trivially simple in my case… So if there’s editing emacs packages in your future, or some of the annoyances of
package.el have gotten to you, I’d recommend you take a look at
straight.el to replace