Next: アドバイスとバイトコード, Previous: アドバイスの構築方法, Up: Emacs Lisp関数にたいするアドバイス [Contents][Index]
多くのコードは古いdefadvice
メカニズムを使用しており、これらの大半はadvice-add
によって陳腐化しました。advice-add
の実装とセマンティックは非常にシンプルです。
古いアドバイスは以下のようなものです:
(defadvice previous-line (before next-line-at-end (&optional arg try-vscroll)) "Insert an empty line when moving up from the top line." (if (and next-line-add-newlines (= arg 1) (save-excursion (beginning-of-line) (bobp))) (progn (beginning-of-line) (newline))))
新しいアドバイスメカニズムを使用すれば、これを通常の関数に変換できます:
(defun previous-line--next-line-at-end (&optional arg try-vscroll) "Insert an empty line when moving up from the top line." (if (and next-line-add-newlines (= arg 1) (save-excursion (beginning-of-line) (bobp))) (progn (beginning-of-line) (newline))))
これが実際のprevious-line
を変更しないことは明確です。古いアドバイスには以下が必要です:
(ad-activate 'previous-line)
一方、新しいアドバイスメカニズムでは以下が必要です:
(advice-add 'previous-line :before #'previous-line--next-line-at-end)
ad-activate
はグローバルな効果をもつことに注意してください。これは指定された関数にたいして、アドバイスのすべてを有効にします。特定のアドバイスだけをアクティブ、または非アクティブにしたいなら、ad-enable-advice
かad-disable-advice
でアドバイスを有効か無効にする必要があります。新しいメカニズムではこの区別はなくなりました。
以下のようなaroundのアドバイスがあるとします:
(defadvice foo (around foo-around) "Ignore case in `foo'." (let ((case-fold-search t)) ad-do-it)) (ad-activate 'foo)
これは以下のように変換できます:
(defun foo--foo-around (orig-fun &rest args) "Ignore case in `foo'." (let ((case-fold-search t)) (apply orig-fun args))) (advice-add 'foo :around #'foo--foo-around)
アドバイスのクラスについて、新たな:before
は古いbefore
は完全に等価ではないことに注意してください。なぜなら古いアドバイス内では、(たとえばad-set-arg
を使って)その関数の引数を変更でき、それは元の関数が参照する引数値に影響します。しかし新しい:before
は、setq
を通じてアドバイス内の引数を変更して、その変更は元の関数からの参照に影響しません。この振る舞いにもとづいてbefore
アドバイスを移行するときは、代わりにそれを新たなアドバイス:around
か:filter-args
に変更する必要があるでしょう。
同様に古いafter
アドバイスは、ad-return-value
を変更することによりリターン値を変更できますが、新しい:after
は変更できないので、そのようなafter
を移行するときは、かわりにそれらを新しいアドバイス:around
か:filter-return
に変更する必要があるでしょう。