モダンなEmacsを求めて (4) package.elでインストールしていないパッケージを自動でインストールする
今回のモダンなEmacsを求めては、インストールしたいパッケージをリストに追加すると起動時に自動でインストールされるような仕組みをつくる。
前回、前々回でpackage.el
、init-loader
の設定がすんでいるものとする。
- モダンなEmacsを求めて (3) init-loaderで設定ファイルを分割する - block_given?
- モダンなEmacsを求めて (2) モダンなパッケージ管理 package.el を使う - block_given?
全体像
~/.emacs.d/inits/00_packages.el
に以下のような感じで書く。my/packages
でインストールしたいパッケージを定義する(この例の場合はruby-end
)。定義したパッケージがインストールされていない場合、起動時に自動でインストールされる。
(require 'cl) (defvar my/packages '(ruby-end)) (let ((not-installed (remove-if 'package-installed-p my/packages))) (when not-installed (package-refresh-contents) (dolist (package my/packages) (package-install package))))
インストールしたいパッケージを定義する
(defvar my/packages
'(ruby-end))
自分が定義した変数に接頭辞としてmy/
をつけると、拡張機能の設定や、その他の設定と区別がしやすい。
defvar
はsetq
と違って、初回のみ値を設定する。
(defvar hi 1) hi ;; => 1 (defvar hi 2) hi ;; => 1 (setq hola 1) hola ;; => 1 (setq hola 2) hola ;; => 2
インストールされていないパッケージを調べる
my/packages
の中から、まだインストールされていないパッケージを調べる。
EmacsLisp doesn’t come with a ‘filter’ function to keep elements that satisfy a conditional and remove elements that do not satisfy it.
http://www.emacswiki.org/emacs/ElispCookbook#toc39
Elispには、リストの要素を調べ、条件によってフィルタリングするような関数はないらしい。
cl
のremove-if
を使ってフィルタリングする。
フィルタした結果、インストールされていないパッケージがなければ空リスト(偽)になるため、何もしない。
もしもインストールされていないパッケージがある場合、package-refresh-contents
で最新のパッケージの情報を取得した後、mapc
でそれぞれインストールする。
(require 'cl) (let ((not-installed (remove-if 'package-installed-p my/packages))) (when not-installed (package-refresh-contents) (mapc 'package-install my/packages)))
戻り値は必要ないのでdolist
してもいいんだけど、書くことが増えるのでmapc
した。