block_given?

ジャングル ブロック ナイ アルノハ jump ダケ。CC-BY-SA 3.0

モダンなEmacsを求めて (4) package.elでインストールしていないパッケージを自動でインストールする

今回のモダンなEmacsを求めては、インストールしたいパッケージをリストに追加すると起動時に自動でインストールされるような仕組みをつくる。

前回、前々回でpackage.elinit-loaderの設定がすんでいるものとする。

全体像

~/.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/をつけると、拡張機能の設定や、その他の設定と区別がしやすい。 defvarsetqと違って、初回のみ値を設定する。

(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には、リストの要素を調べ、条件によってフィルタリングするような関数はないらしい。 clremove-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した。

参考