Next: , Up: Emacs Lisp関数にたいするアドバイス   [Contents][Index]


13.12.1 アドバイスを操作するためのプリミティブ

Macro: add-function where place function &optional props

このマクロはplace(ジェネリック変数を参照)に格納された関数に、アドバイスfunctionを追加する手軽な方法である。

whereは既存の関数のどこ — たとえば元の関数の前や後 — にfunctionが構成されるかを決定する。2つの関数を構成するために利用可能な方法のリストは、アドバイスの構築方法を参照のこと。

(通常は名前が-functionで終わる)変数を変更するときには、functionがグローバルに使用されるか、あるいはカレントバッファーだけに使用されるか選ぶことができる。placeが単にシンボルならfunctionplaceのグローバル値に追加される。place(local symbol)というフォームなら、symbolはその変数の名前をリターンする式なので、functionはカレントバッファーだけに追加される。最後にレキシカル変数を変更したければ、(var variable)を使用する必要があるだろう。

add-functionで追加されたすべての関数は、自動的にプロパティpropsの連想リストに加えることができる。現在のところ特別な意味をもつのは以下の2つのプロパティのみ:

name

これはアドバイスの名前を与える。この名前はremove-functionが取り除く関数を識別するのに使用できます。これは通常はfunctionが無名関数のときに使用されます。

depth

これは複数のアドバイスが与えられたときにアドバイスを順番づける方法を指定します。depthのデフォルト0です。depthが100のときにはアドバイスが可能な限りの深さを保持すべきことを、-100のときは最外のアドバイスに留めることを意味します。同じdepthで2つのアドバイスが指定された場合には、もっとも最近に追加されたアドバイスが最外になります。

:beforeアドバイスにたいしては、最外(outermost)になるということは、このアドバイスが他のすべてのアドバイスの前、つまり1番目に実行されることを意味し、最内(innermost)とは元の関数が実行される直前、すなわちこのアドバイスと元の関数の間に実行されるアドバイスは存在しないことを意味する。同様に:afterアドバイスにたいしては、最内とは元の関数の直後、つまりこの元の関数とアドバイスの間に実行される他のアドバイスは存在せず、最外とは他のすべてのアドバイスが実行された直後にこのアドバイスが実行されることを意味する。:overrideの最内アドバイスは、元の関数だけをオーバーライドし、他のアドバイスはそれに適用されるが、:overrideの最外アドバイスは元の関数だけではなく、その他すべての適用済みのアドバイスをも同様にオーバーライドする。

functionがインタラクティブでなければ合成された関数は、(もしあれば)元の関数のインタラクティブ仕様(interactive spec)を継承します。それ以外なら合成された関数はインタラクティブとなりfunctionのインタラクティブ仕様を使用します。1つ例外があります。functionのインタラクティブ仕様が関数(式や文字列ではないlambda式やfboundシンボル)なら、合成される関数のインタラクティブ仕様は、元の関数のインタラクティブ仕様を唯一の引数とする、その関数の呼び出しとなります。引数として受け取ったインタラクティブ仕様を解釈するためにはadvice-eval-interactive-specを使用します。

注意: functionのインタラクティブ指定は結合された関数に適用されるべきであり、functionではなく結合された関数の呼び出し規約にしたがうこと。これらは多くの場合には等しいので差異は生じないが、placeに格納されたオリジナルの関数とは異なる引数を受け取るfunctionでは:around:filter-args:filter-returnでは重要になる。

Macro: remove-function place function

このマクロはplaceに格納された関数からfunctionを取り除く。これはadd-functionを使用してfunctionplaceに追加されたときだけ機能する。

functionplaceに追加された関数にたいして、ラムダ式にたいしても機能するようにequalを使用して比較を試みる。これは追加でplaceに追加された関数のnameプロパティも比較する。これはequalを使用してラムダ式を比較するより信頼性がある。

Function: advice-function-member-p advice function-def

adviceがすでにfunction-def内にあれば非nilをリターンする。上記のremove-functionと同様、実際の関数adviceのかわりにアドバイスのnameも使用できる。

Function: advice-function-mapc f function-def

function-defに追加されたすべてのアドバイスにたいして、関数fを呼び出す。fは2つの引数 — アドバイス関数とそれのプロパティで呼びだされる。

Function: advice-eval-interactive-spec spec

そのようなインタラクティブ仕様で関数がインタラクティブに呼び出されたようにspecを評価して、構築された引数のリストに対応するリストをリターンする。たとえば(advice-eval-interactive-spec "r\nP")はリージョンの境界、カレントプレフィクス引数を含む、3つの要素からなるリストをリターンする。

たとえばC-x m (compose-mail)コマンドに‘From:’ヘッダーの入力を求めるさせるようにするには、以下のようにすればよい:

(defun my-compose-mail-advice (orig &rest args)
  "Read From: address interactively."
  (interactive
   (lambda (spec)
     (let* ((user-mail-address
             (completing-read "From: "
                              '("one.address@example.net"
                                "alternative.address@example.net")))
            (from (message-make-from user-full-name
                                     user-mail-address))
            (spec (advice-eval-interactive-spec spec)))
       ;; Put the From header into the OTHER-HEADERS argument.
       (push (cons 'From from) (nth 2 spec))
       spec)))
  (apply orig args))

(advice-add 'compose-mail :around #'my-compose-mail-advice)