トップ «前の日記(2009-12-10 (Thu)) 最新 次の日記(2010-01-20 (Wed))» 編集   RSS 1.0 FEED  

Journal InTime


2009-12-24 (Thu) [長年日記]

_ Emacsユーザのためのadvice

Emacs Advent Calendar jp: 2009の参加記事。昨日はid:hayamizさん。 明日は他に参加する人がいなければid:authorNariさん。

最近はVimを使うことが多いけど、shiroさんのお話を聞いてやっぱりLispは強力だなあとか思ったりしたので参加してみた。 知ってる人も多いと思うけど、Emacs Lispのadviceという機能を簡単に紹介しよう。

adviceとは、簡単に言うとCLOSのmethod combinationみたいなものだ。あるいは、Railsのbefore/after/aroundフィルタみたいなものと言った方がいいだろうか。要は、既存の関数(正確にはマクロや特殊フォームを含む)の実行の前(before)あるいは後(after)、前後両方(around)で実行したいコードを定義する機能である。

たとえば、以下のコードはGNU Emacs拡張ガイド―Emacs Lispプログラミングに載っている例(だったと思う)で、switch-to-bufferで存在しないバッファ名を指定した時に、新しいバッファを作らないようにするためのものだ。

(defadvice switch-to-buffer (before existing-buffer activate compile)
  "When interactive, switch to existing buffers only,
   unless given a prefix argument."
  (interactive
   (list (read-buffer "Switch to buffer: "
                      (other-buffer)
                      (null current-prefix-arg)))))

簡単に説明すると、defadviceはadviceを定義するためのマクロ(マクロ万歳!)で、defunに似ているがちょっと違う。 switch-to-bufferの部分には拡張対象の関数名を指定し、beforeの部分にはbefore/after/aroundのいずれかを、existing-bufferの部分にはadviceの名前を指定する。activateとcompileはフラグで、それぞれadviceを活性化することと、コンパイルすることを指示している。 詳細はマニュアルなどを参照。

以下の例は、find-fileを拡張して、C-u C-x C-fのようにprefix引数付きで実行した時に明示的にcoding-systemを指定できるようにするもので、標準の機能が見つからなかったので自分で定義して愛用している。

(defadvice find-file (around coding-system activate compile)
  "When a prefix argument given, specify coding-system-for-read."
  (let ((coding-system-for-read
         (if current-prefix-arg
             (read-coding-system "coding system: ")
           coding-system-for-read)))
    ad-do-it))

aroundの場合は、元の関数(この場合はfind-file、正確には自分より内側で実行されるaround adviceも含む)の前後でadviceを実行するわけだが、上記のad-do-itの部分で元の関数が実行される。 この例だとad-do-itの後に何も処理していないのでbeforeでもいいと思われるかもしれないが、letでcoding-system-for-readを束縛する範囲にad-do-itを含めるためにaroundにする必要がある(Emacs Lispはdynamic scopingを採用しているので、letで束縛されたcoding-system-for-readの値は、ad-do-itで呼び出される元のfind-fileからも参照されることに注意)。

というわけで、今日はEmacs Lispのadviceを紹介した。 こういったadviceが色んな人の.emacsに散らかっている(そしてどれもちょっとずつ違う)のが、Emacsの楽しいところであり、やっかいなところでもある。 他人のマシンで作業する時のために、第2母エディタとしてviなども習得しておくことをお勧めする…というのが僕からのEmacsユーザのためのadviceである。

Tags: Emacs