Tech Nuggets (15)

Elpaca を使う

Posted:

Emacs のパッケージマネージャ elpaca を使い始めた。好印象だ。

先日 この動画elpaca を知ったことがきっかけ。 今まで使っていたビルトインのパッケージマネージャ package.el に特別不満はなかったが、興味が湧いた。

package.el からの移行はとてもかんたんだった。

diff

early-init.el

early-init.el
+(setq package-enable-at-startup nil) ;; To use Elpaca as package manager

init.el
+;; Elpaca (replacement for built-in package.el)
+(defvar elpaca-installer-version 0.4)
+(defvar elpaca-directory (expand-file-name "elpaca/" user-emacs-directory))
+(defvar elpaca-builds-directory (expand-file-name "builds/" elpaca-directory))
+(defvar elpaca-repos-directory (expand-file-name "repos/" elpaca-directory))
+(defvar elpaca-order '(elpaca :repo "https://github.com/progfolio/elpaca.git"
+                              :ref nil
+                              :files (:defaults (:exclude "extensions"))
+                              :build (:not elpaca--activate-package)))
+(let* ((repo  (expand-file-name "elpaca/" elpaca-repos-directory))
+       (build (expand-file-name "elpaca/" elpaca-builds-directory))
+       (order (cdr elpaca-order))
+       (default-directory repo))
+  (add-to-list 'load-path (if (file-exists-p build) build repo))
+  (unless (file-exists-p repo)
+    (make-directory repo t)
+    (when (< emacs-major-version 28) (require 'subr-x))
+    (condition-case-unless-debug err
+        (if-let ((buffer (pop-to-buffer-same-window "*elpaca-bootstrap*"))
+                 ((zerop (call-process "git" nil buffer t "clone"
+                                       (plist-get order :repo) repo)))
+                 ((zerop (call-process "git" nil buffer t "checkout"
+                                       (or (plist-get order :ref) "--"))))
+                 (emacs (concat invocation-directory invocation-name))
+                 ((zerop (call-process emacs nil buffer nil "-Q" "-L" "." "--batch"
+                                       "--eval" "(byte-recompile-directory \".\" 0 'force)")))
+                 ((require 'elpaca))
+                 ((elpaca-generate-autoloads "elpaca" repo)))
+            (kill-buffer buffer)
+          (error "%s" (with-current-buffer buffer (buffer-string))))
+      ((error) (warn "%s" err) (delete-directory repo 'recursive))))
+  (unless (require 'elpaca-autoloads nil t)
+    (require 'elpaca)
+    (elpaca-generate-autoloads "elpaca" repo)
+    (load "./elpaca-autoloads")))
+(add-hook 'after-init-hook #'elpaca-process-queues)
+(elpaca `(,@elpaca-order))
+
+;; Install use-package support
+(elpaca elpaca-use-package
+  ;; Enable :elpaca use-package keyword.
+  (elpaca-use-package-mode)
+  ;; Assume :elpaca t unless otherwise specified.
+  (setq elpaca-use-package-by-default t))
+
+;; Block until current queue processed.
+(elpaca-wait)

-;; Initialize
-(require 'package)
-(setq package-archives
-      '(("melpa" . "https://melpa.org/packages/")
-        ("gnu" . "https://elpa.gnu.org/packages/")))
-
-(unless (package-installed-p 'use-package)
-  (package-install 'use-package))
-(require 'use-package)
 (setq use-package-always-ensure t)
 (setq use-package-always-defer t)
 (setq use-package-verbose t)
init.el
;; flyspell
 (use-package flyspell
+  :elpaca nil
   :init
   (cond ((eq system-type 'windows-nt)
          (add-to-list 'exec-path "C:/Program Files/Aspell/bin/")))

 (use-package org
   :demand t
   :init
+  :elpaca nil
   (setq org-startup-indented t
         org-hide-emphasis-markers t
         org-catch-invisible-edits 'smart


 (use-package doom-modeline
-  :hook (after-init . doom-modeline-mode))
+  :hook (elpaca-after-init . doom-modeline-mode))

-(use-package js)
+(use-package js :elpaca nil)

-  :load-path "~/.config/emacs/elisp")
+  :elpaca (kbd-mode :host github :repo "kmonad/kbd-mode"))


 ;;; custom.el
 (setq custom-file (locate-user-emacs-file "custom.el"))
-(load custom-file 'noerror 'nomessage)
+(add-hook 'elpaca-after-init-hook (lambda () (load custom-file 'noerror 'nomessage)))