el-get.elでEmacs Lispパッケージをインストール・アップグレードする

Emacs Advent Calendar jp: 2010 の9日目の記事です。 去年のauto-install.el に引き続き、今年もインストーラの紹介です。

昨日は id:yaotti さん(anything関数を好きな言語で実装できるanything-with-everything.el (Emacs Advent Calendar 2010 8日目) - yaotti's diary)でした。 anything-with-everything.elは以前から作ろうと思っていたら先越されてしまいました。 明日は id:handlename さんです。

つい最近になって、Emacs Lispのインストールを管理するel-get.elが登場しました。 Emacs Lispのインストールといえば、auto-install.elやその前身のinstall-elisp.elがあります。 しかし、これらはEmacs Lispファイルそのものがインターネットに公開されている場合でしか使えません。 M-x auto-install-batchで複数ファイルで構成されているEmacs Lispをインストールできますが、ひとつひとつのEmacs Lispファイルに対応するURLが存在する場合に限られます。 Emacs Lisp『パッケージ』のインストーラとしては力不足なのが現状です。

el-get.elは、単体ファイル、Emacs Lisp Package Archive、Git、Git-Svn、bzr、CVS、darcs、apt-get、fink、tar、EmacsWikipacman、hgに対応しています。 tarやgitで公開されているEmacs Lispのインストール・アップグレードをEmacsの中で行うことができるようになります。

インストール

ELPA

まず最初にELPAをインストールします。 ELPAとは、Emacs Lisp版のaptみたいなシステムで、Emacs Lispパッケージのインストール・アンインストールを管理します。 ただ、登録されているパッケージの数が少ないという欠点があります。


M-x install-elisp http://tromey.com/elpa/package-install.el

ちなみに、Emacs24ではELPAが標準になるようです。

el-get.el

その後でel-get.el本体をインストールします。

Emacsに以下の式を貼り付けて評価してください。 最後の括弧にカーソルを置き、C-x C-eを押します。

これは、URLからel-get.elのインストーラをダウンロードして実行します。


(url-retrieve
"https://github.com/dimitri/el-get/raw/master/el-get-install.el"
(lambda (s)
(end-of-buffer)
(eval-print-last-sexp)))

すると、 ~/.emacs.d/el-get というディレクトリが作られ、それ以下にel-get含め、インストールしたパッケージが格納されます。

el-get-ext.el(暫定版)

素のel-get.elはまだ使いものにならないので、僕が拡張しました。


M-x install-elisp http://www.rubyist.net/~rubikitch/junk/2010-12-09-095707.el-get-ext.el

このコードは暫定版であり、作者に取り込んでもらう予定なので、あえてEmacsWikiには置いていません。 反映され次第、上のコードは不要になります。

以下の設定を.emacsに加えてください。

;; (save-window-excursion (shell-command (format "emacs-test -l %s %s &" buffer-file-name buffer-file-name)))
(add-to-list 'load-path "~/.emacs.d/el-get/el-get/")
(require 'el-get)
(load "2010-12-09-095707.el-get-ext.el")
;; 初期化ファイルのワイルドカードを指定する
(setq el-get-init-files-pattern "~/emacs/init.d/[0-9]*.el")
(setq el-get-sources (el-get:packages))
(el-get)

標準機能

el-get.elのパッケージの一部は最低限の設定もやってくれます。 しかし、ロードすらしないパッケージもあります。 el-get.elはどこまで面倒を見るかは、まだ定まっていないようです。

現時点では、設定はおまけみたいなものであり、あらゆる方法によるインストールを統一化するという位置付けで考えるのが無難です。 少なくともload-pathの面倒は見てくれるので、後でrequireすれば使える状態になっています。

パッケージを見る

残念ながら、現時点では、パッケージ一覧を見るインターフェースは存在しません。 そう難しくないので、anything.elインターフェースを作るかもしれません(笑) とりあえず現時点では、 ~/.emacs.d/el-get/el-get/recipes/ を見てください。 100以上のパッケージが登録されています。

パッケージファイルの中身はパッケージ名やURLやload-path等、インストールに必要なメタデータです。 このメタデータのことを「レシピ」と呼びます。 レシピはEmacs Lispです。 レシピのファイル名から拡張子(.el)を取り除いたものを「レシピ名」と呼ぶことにします。

インストールしたいものがあったとき、レシピ名を el-get-sources に加えておく必要があります。 しかし、後述する方法でel-get-sourcesを意識しなくて済むようになります。 そして、Emacsを再起動すれば、起動時にインストールされます。

M-x el-get-installでインストールする

レシピ名を el-get-sources に加え、el-get-sourcesを更新(setq el-get-sourcesの行末でC-x C-eする)すれば、再起動なしでもインストールできます。 M-x el-get-install で加えたパッケージ名を指定すればよいです。

M-x el-get-updateで更新する

すでにインストールされているパッケージを更新するには、M-x el-get-updateを使います。 URLやインストール方法を覚えていなくてもこのコマンド一発で更新できるのが、el-get.elの魅力です。

M-x el-get-removeで削除する

パッケージを削除するには、M-x el-get-removeです。 このコマンドを使うことはほとんどないです。 というのは、el-get-sourcesに書かなければ、そのパッケージは使われないからです。

レシピの構造

レシピは ~/.emacs.d./el-get/el-get/recipes/ 以下に配置されています。 中身を見てみると、1組のS式が書かれてあります。

たとえば、anything.elのレシピは次のようになっています。

(:name anything
       :type git
       :url "git://repo.or.cz/anything-config.git"
       :load-path ("." "extensions")
       :features anything)

少し見慣れないリストだと思います。 コロンから始まるのはキーワードといって、シンボルのひとつです。 キーワード、値の繰返しのリストになっています。 このようなリストを属性リスト(plist)と呼びます。 連想リスト同様、キーと値の対応関係を表現します。

それでは、ひとつひとつ見てみます。

  • :name :: パッケージ名
  • :type :: インストールのタイプ
  • :url :: Emacs LispあるいはリポジトリのURL
  • :load-path :: load-pathに加えるディレクトリで、バイトコンパイル対象(任意)
  • :features :: el-getでrequireするライブラリ(任意)

featuresキーワードにより、el-getでanything.elがロードされるようになっています。 御存知のとおり、anything.elはただの入れ物なので、使うためにはanything-startup.elをロードする必要があります。 しかしanything-startup.elはいろいろなライブラリに依存しているため、早い段階でロードするとエラーになってしまうでしょう。 レシピでは、anything.elのみロードしておくか、何もロードしないでおくのが無難です。

次はEMMSの例です。

(:name emms
       :type git
       :url "git://git.sv.gnu.org/emms.git"
       :info "doc"
       :load-path ("./lisp")
       :features emms-setup
       :build ("make autoloads" "make")
       :build/darwin `(,(concat "make EMACS=" el-get-emacs " autoloads all")))

これもgitからですが、インストールにはmakeを使う必要があります。

  • :info :: infoが格納されているディレクト
  • :build :: ビルド時に実行するコマンド(複数化)
  • :build/darwin :: system-typeの値がdarwinのとき、ビルド時に実行するコマンド

build/darwinはsystem-typeで判断しています。 Linuxの場合はbuild/gnu/linuxとなります。

他にもキーワードはいろいろ定義さているので、興味ある人は <f1> v el-get-sources で見ることができます。

問題点

「使い方」を読んでみて、面倒だと思ったでしょう。

  1. 手で el-get-sources を操作する必要がある
  2. レシピがないEmacs Lispの場合、複雑なレシピを自作しなければならない

せっかく複数ファイルに対応しているとはいえ、これでは利便性がなさすぎです。 インストーラといえば、auto-install.elのように、やっぱりURLを入力してコマンド一発でできなければなりません。

解決策

これではあんまりなので、自分なりに解決策を編み出しました。 その解決策がel-get-ext.el(暫定版)です。

実は、el-get-sourcesについては、手書きする必要はありません。 なぜなら、.emacs を走査しておくことで求められるからです。 el-get.elでは、インストールまでは面倒を見ていても、「設定」については .emacs に書く必要があります。 設定する部分でel-get.elを使うという「印」をつけておけば解決します。

レシピについても、だいたい決まったパターンが存在します。 そのため、URLからレシピを自動生成してしまえば9割方うまくいきます。 Emacs Lispが入っているディレクトリが異なる場合などには、レシピに手を加える必要がありますが… レシピを修正した場合は、M-x el-get-updateを実行すれば反映されます。

よって、URLを指定するだけで高確率でel-get.elによる楽々インストールが実現します。

auto-install.el風インターフェース

auto-install.elやinstall-elisp.el愛用者のために、URLやEmacsWikiから直接インストールするインターフェースを作りました。 gistやauto-install-batch等もサポートする予定ですが、間に合いませんでした。

M-x el-get-from-url でURLを入力してインストールする

M-x el-get-from-urlはURLからインストールします。 type(インストールのタイプ。httpやらgitやらtarやら)とname(パッケージ名)を自動判別します。 自動判別はたまに間違うこともあるので、プロンプトが出てきます。

また、レシピがあるならばレシピを使い、なければレシピを自動生成します。 レシピの作成場所は、el-get本体とは別に持っておけば自動生成されたものと区別できます。

たとえば、8日目の anything-with-everything.el をインストールする場合は、

  1. M-x el-get-from-url https://github.com/yaotti/anything-with-everything.el
  2. Package name: →anything-with-everything.el
  3. Type: →git

の順に操作します。

自動生成されたレシピは別ウィンドウに表示されます。 もし不都合があれば、レシピを修正し、「M-x el-get-update パッケージ名」 を実行します。

M-x el-get-from-emacswikiEmacsWikiからインストールする

EmacsWikiにある場合は、「M-x el-get-from-emacswiki ファイル名」を使うのが簡単です。 auto-install.elがあるならば、ファイル名の補完が使えます。 この場合は単純なので、レシピは自動生成され、100%インストールは成功します。

el-get-sourcesを手書きしないようにする方法

auto-install.el風インターフェースにより、インストールの問題は解決しました。 今度は設定の問題があります。

el-get-sourcesを手書きすると、el-get-sourcesの行と、実際のパッケージの設定部分が離れてしまいます。 これでは、新たにパッケージをインストールしたら、設定を加えるだけでなく、el-get-sourcesの行も更新しないといけません。 そこで、el-get.elがインストールしたパッケージに「印」をつけ、それを元にel-get-sourcesを自動設定しておきます。

その印とは (el-get:use パッケージ名) というS式を行頭に加えることです。 たとえば、 anything-with-everything.elの設定では、こんな感じになります。

(el-get:use anything)
(require 'anything)
(el-get:use anything-with-everything.el)
(require 'anything-with-everything)
;; 以下略

el-get:useの実体は空マクロなので、実行時には何も起こりません。 Emacsの初期化ファイル(.emacsや分割した場合はそれらのファイル)から el-get:use の行をgrep*1、el-get-sourcesを設定します。


(setq el-get-init-files-pattern "~/emacs/init.d/[0-9]*.el")
(setq el-get-sources (el-get:packages))

(el-get:packages)の返り値のリストには、きちんとanythingとanything-with-everything.elが含まれています。

まとめ

el-get.elは出来たてで、未完成なところもありますが、今後の成長が望めるインストーラです。 2011年は主流になるといいですね。

*1:このへんの実装はまだ手抜き