diff options
Diffstat (limited to 'devdocs/elisp/porting-old-advice.html')
| -rw-r--r-- | devdocs/elisp/porting-old-advice.html | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/devdocs/elisp/porting-old-advice.html b/devdocs/elisp/porting-old-advice.html new file mode 100644 index 00000000..f36c957a --- /dev/null +++ b/devdocs/elisp/porting-old-advice.html @@ -0,0 +1,41 @@ + <h4 class="subsection">Adapting code using the old defadvice</h4> <p>A lot of code uses the old <code>defadvice</code> mechanism, which is largely made obsolete by the new <code>advice-add</code>, whose implementation and semantics is significantly simpler. </p> <p>An old piece of advice such as: </p> <div class="example"> <pre class="example">(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)))) +</pre> +</div> <p>could be translated in the new advice mechanism into a plain function: </p> <div class="example"> <pre class="example">(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)))) +</pre> +</div> <p>Obviously, this does not actually modify <code>previous-line</code>. For that the old advice needed: </p> +<div class="example"> <pre class="example">(ad-activate 'previous-line) +</pre> +</div> <p>whereas the new advice mechanism needs: </p> +<div class="example"> <pre class="example">(advice-add 'previous-line :before #'previous-line--next-line-at-end) +</pre> +</div> <p>Note that <code>ad-activate</code> 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 piece, you needed to <em>enable</em> or <em>disable</em> it with <code>ad-enable-advice</code> and <code>ad-disable-advice</code>. The new mechanism does away with this distinction. </p> <p>Around advice such as: </p> <div class="example"> <pre class="example">(defadvice foo (around foo-around) + "Ignore case in `foo'." + (let ((case-fold-search t)) + ad-do-it)) +(ad-activate 'foo) +</pre> +</div> <p>could translate into: </p> <div class="example"> <pre class="example">(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) +</pre> +</div> <p>Regarding the advice’s <em>class</em>, note that the new <code>:before</code> is not quite equivalent to the old <code>before</code>, because in the old advice you could modify the function’s arguments (e.g., with <code>ad-set-arg</code>), and that would affect the argument values seen by the original function, whereas in the new <code>:before</code>, modifying an argument via <code>setq</code> in the advice has no effect on the arguments seen by the original function. When porting <code>before</code> advice which relied on this behavior, you’ll need to turn it into new <code>:around</code> or <code>:filter-args</code> advice instead. </p> <p>Similarly old <code>after</code> advice could modify the returned value by changing <code>ad-return-value</code>, whereas new <code>:after</code> advice cannot, so when porting such old <code>after</code> advice, you’ll need to turn it into new <code>:around</code> or <code>:filter-return</code> advice instead. </p><div class="_attribution"> + <p class="_attribution-p"> + Copyright © 1990-1996, 1998-2022 Free Software Foundation, Inc. <br>Licensed under the GNU GPL license.<br> + <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Porting-Old-Advice.html" class="_attribution-link">https://www.gnu.org/software/emacs/manual/html_node/elisp/Porting-Old-Advice.html</a> + </p> +</div> |
