Previous: Advice combinators, Up: Advising Functions
A lot of code uses the old defadvice mechanism, which is largely made
obsolete by the new advice-add, whose implementation and semantics is
significantly simpler.
An old advice such as:
(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))))
could be translated in the new advice mechanism into a plain function:
(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))))
Obviously, this does not actually modify previous-line. For that the
old advice needed:
(ad-activate 'previous-line)
whereas the new advice mechanism needs:
(advice-add 'previous-line :before #'previous-line--next-line-at-end)
Note that ad-activate had a global effect: it activated all pieces of
advice enabled for that specified function. If you wanted to only activate or
deactivate a particular advice, you needed to enable or disable
that advice with ad-enable-advice and ad-disable-advice.
The new mechanism does away with this distinction.
An around advice such as:
(defadvice foo (around foo-around)
"Ignore case in `foo'."
(let ((case-fold-search t))
ad-do-it))
(ad-activate 'foo)
could translate into:
(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)
Regarding the advice's class, note that the new :before is not
quite equivalent to the old before, because in the old advice you could
modify the function's arguments (e.g., with ad-set-arg), and that would
affect the argument values seen by the original function, whereas in the new
:before, modifying an argument via setq in the advice has no
effect on the arguments seen by the original function.
When porting a before advice which relied on this behavior, you'll need
to turn it into a new :around or :filter-args advice instead.
Similarly an old after advice could modify the returned value by
changing ad-return-value, whereas a new :after advice cannot, so
when porting such an old after advice, you'll need to turn it into a new
:around or :filter-return advice instead.