package.elで自動インストール

Emacsには便利なelispパッケージがあるが、最近ではpackage.elというのが付属していて、ネットワーク上からパッケージをインストール仕組みができている。以前はウェブ上から手作業でダウンロードして.emacs.dに下に保存していたが、package.elを使えば一覧から好きなものを選択するだけでインストールできる。

ということで、package.elの設定と自動インストールの設定をしてみた。

基本設定

デフォルトではelpa.gnu.orgから取得するようになっているが、ここにあるパッケージはあまり多くない。MELPA(Milkypostman’s Emacs Lisp Package Archive)というところに多く集まっているので、これを追加しよう。

MELPAを使う設定は公式サイトにあるが、Emacs-24なら以下で良い。

(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
(add-to-list 'package-archives '("melpa-stable" . "https://stable.melpa.org/packages/") t)
(package-initialize)

ここではmelpaとmelpa-stalbeの2つの設定した。melpa-stableの方は安定版が登録されているので、安定性を重視するならこちらを使うのが良いだろう。ただ、melpa-stableにはないものもあるので両方設定する。

これで起動して、M-x package-list-packagesと打てばパッケージのリストを取得して表示してくれる。

f:id:wagavulin:20160704211100p:plain

同じ名前のパッケージが2つあるものがあるが、これはstableとそうでないものがあるからだ。あとは欲しいものを選んで"Install"を選べばインストールしてくれる。インストール先は.emacs.d/elpaの下になる。

また、package.elを使うときは必ずpackage-initializeを呼ぶようにしよう。単にインストールしただけでは、load-pathにそのインストール先が含まれていないため使うことができない。あるいは手動でload-pathに追加しなくてはならない。package-initializeを呼べばそのあたりを任せることができる。

Windowsでの設定

公式サイトに書いてあるが、Windows版のEmacsではHTTPSがうまく扱えないので、リポジトリのURLをhttps://ではなくhttp://にする必要がある。

プロキシ設定

プロキシを使う必要がある場合は以下のようにurl-proxy-servicesを設定する。

(require 'package)
(setq url-proxy-services 
      '(("http" . "proxy.example.com:8080")
        ("https" . "proxy.example.com:8080")))
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
(add-to-list 'package-archives '("melpa-stable" . "https://stable.melpa.org/packages/") t)
(package-initialize)

自動インストール

これで手動でのインストールができたが、できれば自動化したいところだ。新しい環境に行く度に必要なパッケージを一つずつ選択するのは面倒だ。

動作仕様

やりたいことはざっと以下のような感じ。

  • リポジトリからパッケージの一覧を取得したことがない場合、パッケージ一覧を取ってくる。すでに一覧がある場合は取ってこない(結構時間がかかるので毎回やると煩わしい)。
  • あらかじめ必要なパッケージをリストアップしておき、そのパッケージがインストールされていなければインストールする。

以上を行うのが以下のスクリプト。my-favorite-package-listにインストールしたいパッケージの名前を入れておく。ここではweb-mode、projectile、auto-completeを入れてみた。

;;; MELPA
(defvar my-favorite-package-list
  '(web-mode
    projectile
    auto-complete)
  "packages to be installed")

(require 'package)
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/"))
(add-to-list 'package-archives '("melpa-stable" . "http://stable.melpa.org/packages/") t)
(package-initialize)
(unless package-archive-contents (package-refresh-contents))
(dolist (pkg my-favorite-package-list)
  (unless (package-installed-p pkg)
    (package-install pkg)))

;;; web-mode
(require 'web-mode)
;; 以下web-modeの設定

これで起動するとパッケージ一覧の取得とインストールが行われる。下のバッファにエラーが出ていなければ成功だ(多少の警告はあるかもしれない)。また、最後に(require 'web-mode)としているので、これでweb-modeが使えるようになる。

f:id:wagavulin:20160704211059p:plain

stableと最新版の使い分け

上の設定だと、melpaとmelpa-stableの両方にパッケージがある場合、melpaの方が使われる。できれば安定したものが使いたいので、melpa-stableにあるものはmelpa-stableから、そうでなければmelpaから取ってくるようにしたい。

調べたところ、package-pinned-packagesという変数に、パッケージと取得するリポジトリを挙げておけば良いようだ。例えば、web-modeとauto-completeはmelpa-stableから取ってくるが、それ以外はmelpaから取ってくる、という場合、以下のようにする。

;;; MELPA
(defvar my-favorite-package-list
  '(web-mode
    auto-complete
    projectile)
  "packages to be installed")

(require 'package)
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/"))
(add-to-list 'package-archives '("melpa-stable" . "http://stable.melpa.org/packages/") t)
(package-initialize)
(setq package-pinned-packages
      '((web-mode . "melpa-stable")
        (auto-complete . "melpa-stable")))
(unless package-archive-contents (package-refresh-contents))
(dolist (pkg my-favorite-package-list)
  (unless (package-installed-p pkg)
    (package-install pkg)))

;;; web-mode
(require 'web-mode)
;; 以下web-modeの設定

パッケージ名を2箇所に書いているあたりがちょっとイケてないが、これでインストールを自動化できた。