モダンな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した。