GNU Emacs 32.0.50 (9008bf64c3) のマニュアルを PLaMo 翻訳で機械翻訳したものです。誤訳を含むことがあります。原文: https://www.gnu.org/software/emacs/manual/html_node/elisp/Porting-Old-Advice.html ・ emacs-doc.conao3.com

13.12.4 旧 defadvice を用いたコードの適応

多くのコードで旧来の defadvice 機構が使われていますが、これは新しい 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を用いてそれを有効または無効にする必要がありました。新しい仕組みでは、この区別が不要になりました。

以下のようなアドバイス:

(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 アドバイスに変換する必要があります。