この度、use-package.elからleaf.elに移行した。
どうして移行したのかや、その時の調査した周辺技術や、移行に関する知見を、せっかくだしメモしておく。
なお、内容を書くにあたって、Emacs 26.3とGitHubレポジトリのコードで調査している。
背景
Emacsのパッケージとその設定を、以下のように管理している。
- dotfiles全般の一部としてGitHubにてGit管理している
- package.elを使っている
- Emacs24から標準だしね
- use-package.elを使っている
- メジャーなパッケージ設定を構造的に管理するパッケージ
- 今年の春くらいに導入したばかり
- パッケージ設定が構造的に書けて最高の気持ち
- 野良パッケージを、
git add
やgit submodule add
を使って管理している- 野良パッケージはpackage.elの管理外のパッケージを指す
- MELPAに登録されてないものや既存パッケージを一部変更したものがある
- 例えば、手元のsml-modeにSML#のキーワードを追加している
問題点
- GitHubのbranchやforkなどの野良パッケージを、Emacs Lispでキレイに扱いたい
- use-package.elにこの機能はない
- この解決のためにgit submoduleを使っているが、
submoduleの初期化や更新など操作がフクザツなため止めたい
- use-package.elを導入したばかりなので、コストは低く解決したい
結論
- use-package.elとその拡張を使うのをやめた
- 今回の調査では、満足できるuse-package.elの拡張が見つからなかった
- use-package.elからleaf.elへ移行した
- コストはそこそこ高かったが、完全移行してよかった点が多かった
- leaf.elはいいぞ
- 一部のgit submoduleは止めれていない
- 今回は議論しないが、snippetのレポジトリをうまく扱う方法を考えていない
トライしたメモ
use-package.elはキーワードを拡張できるため、多数の統合拡張がある。
そこで、use-package.elの拡張を初めに調査した。
また、use-package.el以外にも良いパッケージ設定管理ツールがないか調査した。
特に、use-package.elとキーワードが似通っているとなお良い。
ざっくり調査すると以下の3つを見つけ、それぞれ試すことにした。
- use-package.el + quelpa.el
- use-package.el + straight.el
- leaf.el
なお、パッケージ管理のバックエンドとしてはpackage.elは使うことにし、
これ以外のバックエンドの調査はしていない。
use-package.el + quelpa.el
Quelpaはパッケージのビルド・インストールを行うツールである。
これ自身にはuse-package.elのようなパッケージ設定管理の機能はない。
代わりに、quelpa-use-packageというインテグレーションが用意されている。
良かった
- use-package.elとのインテグレーションがあるため移行コストが低い
- use-package節内で
:quelpa
キーワードが使えるようになる
- use-package節内で
-
:quelpa
キーワードを使って、GitHubのbranchが指定できる - package.elのパッケージ状態を認識してくれる
- 依存関係などがいい感じに解決される
- Quelpaでインストールするとpackage.elのインストールマークをつけてくれる
- quelpa/buildでビルドしてelpaにコピーしているようだった
悪かった
- 存在しないパッケージを
(quelpa PACKAGE ...)
で指定してもエラーが出ない- まじか???
-
:quelpa
だとさすがにuse-package.elがエラーを出してくれる
- 開発が終了している
use-package.el + straight.el
straight.elは次世代の純粋関数型のパッケージマネージャらしい。
なお、どの辺が純粋関数型なのかはよくわからなかった。
他のパッケージマネージャとの比較を、しっかりしているのに好感が持てた。
これも自身にはパッケージ設定管理の機能ははない。
代わりに、use-package.elとのインテグレーションを持っている。
良かった
- use-package.elとのインテグレーションがあるため移行コストが低い
- use-package節内で
:straight
キーワードが使えるようになる
- use-package節内で
-
:straight
キーワードでGitHubのbranchやforkの指定ができる- 機能としてもドキュメントとしても便利
-
:straight
キーワードを使うと、デフォルトでEmacsMirrorのパッケージも
探索してくれて便利だった
悪かった
- package.elとの相性が悪い
- package.elのインストール状態を認識せず、
straight.elは独自で依存関係も込みでインストールする - 結果、依存関係のパッケージが大量に重複してインストールされる
- package.elのインストール状態を認識せず、
leaf.el
leaf.elはYet Another use-packageで、パッケージ設定管理のパッケージの1つ。
Emacs Advent Calendarにも多数寄稿している@conao3さんが開発している。
昨年12月にバージョン1.0.0が出た比較的新しいパッケージ。
何度かQiita記事でも目にしており、気になっていた。
YA use-package.elということで、移行コストを低く抑えつつ、
よりよい機能が得られるのではと思って試した。
良かった
- package.elのパッケージ状態を認識してくれる
- Quelpaと同上、というかpackage.elをバックエンドとして使っている?
- GitHubのbranchが指定できる
- el-get.elとのインテグレーションがあり、
:el-get
を使い実現できる
- el-get.elとのインテグレーションがあり、
- leaf節で
:el-get
を使ってインストールすると依存パッケージを解決しない- そもそもpackage.elの管理外のものを導入しようとしているため、
依存関係などを自分で管理するのは妥当と思える - leaf節をネストして書けるため、依存関係も書きやすい
- 導入元がpackage.elとel-get.elとで違うものを、ちゃんと分離して管理できる
- そもそもpackage.elの管理外のものを導入しようとしているため、
- leaf節をネストして書けるため、関連する設定をまとめられる
- 例えば、companyの設定の中に、company-**の設定を書いておける
- use-package.elでもできないことはないが、推奨されていない
- 移行しただけでEmacsの起動時間が半分になった
- use-package.elでは
:defer t
で遅延読み込みの指定がいるが、
leaf.elではデフォルトで遅延読み込みなのも効いていそう - use-package.elは起動時間の統計をとるなどリッチな機能を持っており、
そもそも遅いのも効いていそう - 詳細な原因調査はしていない
- な に も し て な い の に Emacs が は や く な り ま し た
- use-package.elでは
悪かった
- ネストしたleaf節がつくるツリー構造が、パッケージの関係性に合わないものがあった
- あるモードの設定を、グローバルモードとメジャーモードのどちらに
まとめるか問題 - 例えば、company-jediはpython-modeでcompanyの補完を提供するが、
機能としてcompanyにまとめるべきか、modeとしてpythonにまとめるべきか - 好きにすればいいと思った、書ける自由度があるのは良い
- あるモードの設定を、グローバルモードとメジャーモードのどちらに
- use-package.elと書き方違いが多少あり、まあまあ移行コストがかかった
- 1,000行ほどの元のelファイルに対して、500行ほどのdiffがあった
leaf.el移行での変更点や感じたこと
- キーワード名が一部違うことがある
-
:defer t
に対応するのは:leaf-defer t
など
-
-
:custom
の引数のデータ構造と許される値が違う-
:custom
の引数がリストではなくドットペア -
:custom (x . (1+ a))
のような未評価部は許されていない-
defvar b (1+ a)
とかして:custom (x . b)
とする
-
-
- デフォルトでパッケージがrequireされない
- requireが必要なパッケージには
:require t
をつける
- requireが必要なパッケージには
- 遅延読み込みがデフォルトとなっている
-
:bind
でのmap名の書き方が違う-
(:map xxx-mode-map ...)
を(:xxx-mode-map ...)
にする
-