前回は、Emacs の環境別に書き分ける方法を紹介したのですが、 どようびさんのコメントにあるように環境別にガチガチに書いてしまうと流用できなくて不便です。
で、環境によっては未導入な Elisp とかがあるわけですが、通常は .emacs 読み込み時に存在しない Elisp を require しようとすると、エラーを吐いて以後の読み込みを中断します。
これはこれで設定の正しさを確認できますが、違う環境でとりあえず使いたい場合にはちょっと面倒です。
そこで、存在しないものは、その関連する設定ごと無視してくれて、存在する Elisp は関連する設定も正しく読み込んでくれるような形が望ましいです。
when による分岐と require の第三引数を使う。
Emacs のバージョンいくつからかは知りませんが、require 関数には、オプションで第三引数 noerror を受けつけてくれます。
これを利用すると存在する Elisp は、その名前を返し、存在しない場合は nil を返すようになります。
ですので、以下のように require を使うと存在しない場合は、その Elisp に依存する設定を全て無視してくれるようになります。
;; undohist ;; (install-elisp "http://cx4a.org/pub/undohist.el") (when (require 'undohist nil t) (undohist-initialize))
(require 'undohist nil t) は、undohist を返し、when は nil 以外であれば、それ以下の部分を全て評価してくれます。逆にその Elisp が存在しなければ、require は nil をエラーを吐かずに nil を返すだけなので、when 内のそれ以下の部分は無視されます。
load / autoload の場合。
load は 第二引数を t にすることで、エラーを吐かないようになります。ですが、load を使う人は自分で Elisp を書いている人だと思うので、まぁ問題ないでしょう。
それよりも便利なのは autoload です。
どようびさんが紹介してくれているdot.emacsにある autoload-if-found は僕も使っております。
(defun autoload-if-found (function file &optional docstring interactive type) "set autoload iff. FILE has found." (and (locate-library file) (autoload function file docstring interactive type))) ;; 使い方 ;; 引数は autoload と全く同じです。-if-found を付けるだけ (when (autoload-if-found 'bs-show "bs" "buffer selection" t) ;; autoload は成功した場合のみ non-nil を返すので、 ;; when の条件部に置くことで、依存関係にある設定項目を自然に表現できます。 (global-set-key [(control x) (control b)] 'bs-show) (setq bs-max-window-height 10))dot.emacs
例えば、いつも使うとは限らない mode-compile であれば、
;; mode-compile (when (autoload-if-found 'mode-compile "mode-compile" "Command to compile current buffer file based on the major mode" t) ;; (global-set-key "\C-cc" 'mode-compile) (global-set-key "\C-c\C-c" 'mode-compile) (autoload-if-found 'mode-compile-kill "mode-compile" "Command to kill a compilation launched by `mode-compile'" t) (global-set-key "\C-ck" 'mode-compile-kill) (global-set-key "\C-cn" 'next-error) ; エラー箇所に飛ぶ )
という感じになります。まぁ、やっていることは、require と同じですね。
ちなみに、autoload は Elisp 内の関数を始めて実行するときに読み込んでくれるというもので、起動速度を早めたい方向けの Elisp の読み込み方です。
なお、require と load は共に起動時に読み込むもので、load はファイル名(拡張子無し)を、require は provide されている名前を指定します。
というわけで、バージョンや OS などの違う Emacs 向けの設定(例えば、専用関数や変数、パスなど)は、前回紹介した方法を使い、Elisp が存在するかどうかの違いは、今回の方法で書き分けると良いでしょう。