2009年11月11日水曜日

[Emacs]そんなことよりeval-after-load使おうぜ

もっと使われてもいいのにと思うEmacsの設定周りのメモ。

[関数] (eval-after-load FILE FORM)

この関数は、指定されたライブラリFILEがロードされているときにのみ2番目の引数FORMを評価するというもの。

例えばmigemoをロードする時の自分の設定はこんな感じ。

;; migemoを読み込む。存在しない場合はnilを返す
(load "migemo" 'noerror)

(eval-after-load "migemo"
 (quote
  (progn
    ;; この辺がmigemoをロードした後に評価される
    (defadvice isearch-mode (before migemo-off activate)
      "初期状態は常にnil"
      (setq migemo-isearch-enable-p nil))
    (fset 'toggle-migemo #'migemo-toggle-isearch-enable)
    (define-key isearch-mode-map (kbd "C-t") 'migemo-isearch-toggle-migemo)
    )))

この関数の利点は

  • ライブラリが存在しない場合はeval-after内のフォームが評価されない。
    つまりエラーにならない。
  • emacsの標準関数である (emacs/lisp/subr.el内で定義)。
    つまり自前で関数を用意しなくて良い。
  • 一度eval-after-loadが評価されれば、後からライブラリが読み込まれてもフォーム内部を評価してくれる。
    これは各種メジャーモードのフックに関数を引っ掛けて、フォームの評価を遅らせるのと同様の手段となる。
    例: (add-hook 'emacs-lisp-mode-hook 'turn-on-eldoc-mode)

逆に不便な点、気にくわない点は

  • 評価できるフォームが1つしか指定できない。
    => (progn ...) を使えば複数フォームを指定できる
  • 関数なので引数が必ず評価される。そのためにフォームをquoteするのが嫌。おまけにシングルクオート '(...) を使うとフォーム内のインデントが崩れる。
    => 代わりに (quote FORM) を使えば長いフォームもそれなりにインデントされる。

この辺は一応マクロを使えば解決するが...なんで関数なんでしょうね、これ。

(defmacro eval-after-load-1 (file &rest args)
 `(eval-after-load ,file
    (quote (progn ,@args))))
(put 'eval-after-load-1 'lisp-indent-function 1)

参考URL

0 件のコメント:

コメントを投稿