Mercurial > emacs
annotate lisp/emacs-lisp/advice.el @ 37678:ebec0594dece
(compile-files): Redirect output of chmod to
/dev/null.
| author | Gerd Moellmann <gerd@gnu.org> |
|---|---|
| date | Fri, 11 May 2001 10:53:56 +0000 |
| parents | 9ca19dfc32fb |
| children | d5f3a4fa3bc5 |
| rev | line source |
|---|---|
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1 ;;; advice.el --- an overloading mechanism for Emacs Lisp functions |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2 |
|
37056
543952c0704a
(ad-make-advised-definition): Call
Gerd Moellmann <gerd@gnu.org>
parents:
33665
diff
changeset
|
3 ;; Copyright (C) 1993,1994,2000, 2001 Free Software Foundation, Inc. |
| 4110 | 4 |
| 5 ;; Author: Hans Chalupsky <hans@cs.buffalo.edu> | |
| 26622 | 6 ;; Maintainer: FSF |
| 4110 | 7 ;; Created: 12 Dec 1992 |
| 5140 | 8 ;; Keywords: extensions, lisp, tools |
| 4110 | 9 |
| 10 ;; This file is part of GNU Emacs. | |
| 11 | |
| 12 ;; GNU Emacs is free software; you can redistribute it and/or modify | |
| 13 ;; it under the terms of the GNU General Public License as published by | |
| 14 ;; the Free Software Foundation; either version 2, or (at your option) | |
| 15 ;; any later version. | |
| 16 | |
| 17 ;; GNU Emacs is distributed in the hope that it will be useful, | |
| 18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 20 ;; GNU General Public License for more details. | |
| 21 | |
| 22 ;; You should have received a copy of the GNU General Public License | |
| 14169 | 23 ;; along with GNU Emacs; see the file COPYING. If not, write to the |
| 24 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
| 25 ;; Boston, MA 02111-1307, USA. | |
| 4110 | 26 |
| 27 ;; LCD Archive Entry: | |
| 28 ;; advice|Hans Chalupsky|hans@cs.buffalo.edu| | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
29 ;; Overloading mechanism for Emacs Lisp functions| |
|
8458
a95ca44cec95
(ad-subr-arglist): Adapted to new DOC file format.
Richard M. Stallman <rms@gnu.org>
parents:
8445
diff
changeset
|
30 ;; 1994/08/05 03:42:04|2.14|~/packages/advice.el.Z| |
| 4110 | 31 |
| 32 | |
| 33 ;;; Commentary: | |
| 34 | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
35 ;; NOTE: This documentation is slightly out of date. In particular, all the |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
36 ;; references to Emacs-18 are obsolete now, because it is not any longer |
| 26217 | 37 ;; supported by this version of Advice. |
| 38 | |
| 39 ;; Advice is documented in the Emacs Lisp Manual. | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
40 |
| 4110 | 41 ;; @ Introduction: |
| 42 ;; =============== | |
| 43 ;; This package implements a full-fledged Lisp-style advice mechanism | |
| 26217 | 44 ;; for Emacs Lisp. Advice is a clean and efficient way to modify the |
| 4110 | 45 ;; behavior of Emacs Lisp functions without having to keep personal |
| 26217 | 46 ;; modified copies of such functions around. A great number of such |
| 47 ;; modifications can be achieved by treating the original function as a | |
| 48 ;; black box and specifying a different execution environment for it | |
| 4110 | 49 ;; with a piece of advice. Think of a piece of advice as a kind of fancy |
| 50 ;; hook that you can attach to any function/macro/subr. | |
| 51 | |
| 52 ;; @ Highlights: | |
| 53 ;; ============= | |
| 54 ;; - Clean definition of multiple, named before/around/after advices | |
| 55 ;; for functions, macros, subrs and special forms | |
| 56 ;; - Full control over the arguments an advised function will receive, | |
| 57 ;; the binding environment in which it will be executed, as well as the | |
| 58 ;; value it will return. | |
| 59 ;; - Allows re/definition of interactive behavior for functions and subrs | |
| 26217 | 60 ;; - Every piece of advice can have its documentation string which will be |
| 4110 | 61 ;; combined with the original documentation of the advised function at |
| 62 ;; call-time of `documentation' for proper command-key substitution. | |
| 63 ;; - The execution of every piece of advice can be protected against error | |
| 64 ;; and non-local exits in preceding code or advices. | |
| 65 ;; - Simple argument access either by name, or, more portable but as | |
| 66 ;; efficient, via access macros | |
| 67 ;; - Allows the specification of a different argument list for the advised | |
| 68 ;; version of a function. | |
| 69 ;; - Advised functions can be byte-compiled either at file-compile time | |
| 70 ;; (see preactivation) or activation time. | |
| 71 ;; - Separation of advice definition and activation | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
72 ;; - Forward advice is possible, that is |
| 4110 | 73 ;; as yet undefined or autoload functions can be advised without having to |
| 26217 | 74 ;; preload the file in which they are defined. |
| 4110 | 75 ;; - Forward redefinition is possible because around advice can be used to |
| 76 ;; completely redefine a function. | |
| 77 ;; - A caching mechanism for advised definition provides for cheap deactivation | |
| 78 ;; and reactivation of advised functions. | |
| 79 ;; - Preactivation allows efficient construction and compilation of advised | |
| 80 ;; definitions at file compile time without giving up the flexibility of | |
| 81 ;; the advice mechanism. | |
| 82 ;; - En/disablement mechanism allows the use of different "views" of advised | |
| 83 ;; functions depending on what pieces of advice are currently en/disabled | |
| 26217 | 84 ;; - Provides manipulation mechanisms for sets of advised functions via |
| 4110 | 85 ;; regular expressions that match advice names |
| 86 | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
87 ;; @ How to get Advice for Emacs-18: |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
88 ;; ================================= |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
89 ;; `advice18.el', a version of Advice that also works in Emacs-18 is available |
| 26217 | 90 ;; either via anonymous ftp from `ftp.cs.buffalo.edu (128.205.32.9)' with |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
91 ;; pathname `/pub/Emacs/advice18.el', or from one of the Emacs Lisp archive |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
92 ;; sites, or send email to <hans@cs.buffalo.edu> and I'll mail it to you. |
| 4110 | 93 |
| 94 ;; @ Overview, or how to read this file: | |
| 95 ;; ===================================== | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
96 ;; NOTE: This documentation is slightly out of date. In particular, all the |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
97 ;; references to Emacs-18 are obsolete now, because it is not any longer |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
98 ;; supported by this version of Advice. An up-to-date version will soon be |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
99 ;; available as an info file (thanks to the kind help of Jack Vinson and |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
100 ;; David M. Smith). Until then you can use `outline-mode' to help you read |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
101 ;; this documentation (set `outline-regexp' to `";; @+"'). |
| 4110 | 102 ;; |
| 103 ;; The four major sections of this file are: | |
| 104 ;; | |
| 105 ;; @ This initial information ...installation, customization etc. | |
| 106 ;; @ Advice documentation: ...general documentation | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
107 ;; @ Foo games: An advice tutorial ...teaches about Advice by example |
| 4110 | 108 ;; @ Advice implementation: ...actual code, yeah!! |
| 109 ;; | |
| 110 ;; The latter three are actual headings which you can search for | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
111 ;; directly in case `outline-mode' doesn't work for you. |
| 4110 | 112 |
| 113 ;; @ Restrictions: | |
| 114 ;; =============== | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
115 ;; - This version of Advice only works for Emacs 19.26 and later. It uses |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
116 ;; new versions of the built-in functions `fset/defalias' which are not |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
117 ;; yet available in Lucid Emacs, hence, it won't work there. |
| 4110 | 118 ;; - Advised functions/macros/subrs will only exhibit their advised behavior |
| 119 ;; when they are invoked via their function cell. This means that advice will | |
| 120 ;; not work for the following: | |
| 26217 | 121 ;; + advised subrs that are called directly from other subrs or C-code |
| 122 ;; + advised subrs that got replaced with their byte-code during | |
| 4110 | 123 ;; byte-compilation (e.g., car) |
| 124 ;; + advised macros which were expanded during byte-compilation before | |
| 125 ;; their advice was activated. | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
126 |
| 4110 | 127 ;; @ Credits: |
| 128 ;; ========== | |
| 129 ;; This package is an extension and generalization of packages such as | |
| 130 ;; insert-hooks.el written by Noah S. Friedman, and advise.el written by | |
| 131 ;; Raul J. Acevedo. Some ideas used in here come from these packages, | |
| 132 ;; others come from the various Lisp advice mechanisms I've come across | |
| 133 ;; so far, and a few are simply mine. | |
| 134 | |
| 135 ;; @ Comments, suggestions, bug reports: | |
| 136 ;; ===================================== | |
| 137 ;; If you find any bugs, have suggestions for new advice features, find the | |
| 138 ;; documentation wrong, confusing, incomplete, or otherwise unsatisfactory, | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
139 ;; have any questions about Advice, or have otherwise enlightening |
| 4110 | 140 ;; comments feel free to send me email at <hans@cs.buffalo.edu>. |
| 141 | |
| 142 ;; @ Safety Rules and Emergency Exits: | |
| 143 ;; =================================== | |
| 144 ;; Before we begin: CAUTION!! | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
145 ;; Advice provides you with a lot of rope to hang yourself on very |
| 4110 | 146 ;; easily accessible trees, so, here are a few important things you |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
147 ;; should know: Once Advice has been started with `ad-start-advice' |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
148 ;; (which happens automatically when you load this file), it |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
149 ;; generates an advised definition of the `documentation' function, and |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
150 ;; it will enable automatic advice activation when functions get defined. |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
151 ;; All of this can be undone at any time with `M-x ad-stop-advice'. |
| 4110 | 152 ;; |
| 153 ;; If you experience any strange behavior/errors etc. that you attribute to | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
154 ;; Advice or to some ill-advised function do one of the following: |
| 4110 | 155 |
| 156 ;; - M-x ad-deactivate FUNCTION (if you have a definite suspicion what | |
| 157 ;; function gives you problems) | |
| 158 ;; - M-x ad-deactivate-all (if you don't have a clue what's going wrong) | |
| 159 ;; - M-x ad-stop-advice (if you think the problem is related to the | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
160 ;; advised functions used by Advice itself) |
| 4110 | 161 ;; - M-x ad-recover-normality (for real emergencies) |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
162 ;; - If none of the above solves your Advice-related problem go to another |
| 4110 | 163 ;; terminal, kill your Emacs process and send me some hate mail. |
| 164 | |
| 165 ;; The first three measures have restarts, i.e., once you've figured out | |
| 166 ;; the problem you can reactivate advised functions with either `ad-activate', | |
| 167 ;; `ad-activate-all', or `ad-start-advice'. `ad-recover-normality' unadvises | |
| 168 ;; everything so you won't be able to reactivate any advised functions, you'll | |
| 169 ;; have to stick with their standard incarnations for the rest of the session. | |
| 170 | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
171 ;; IMPORTANT: With Advice loaded always do `M-x ad-deactivate-all' before |
| 4110 | 172 ;; you byte-compile a file, because advised special forms and macros can lead |
| 173 ;; to unwanted compilation results. When you are done compiling use | |
| 26217 | 174 ;; `M-x ad-activate-all' to go back to the advised state of all your |
| 4110 | 175 ;; advised functions. |
| 176 | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
177 ;; RELAX: Advice is pretty safe even if you are oblivious to the above. |
| 4110 | 178 ;; I use it extensively and haven't run into any serious trouble in a long |
| 179 ;; time. Just wanted you to be warned. | |
| 180 | |
| 181 ;; @ Customization: | |
| 182 ;; ================ | |
| 183 | |
| 184 ;; Look at the documentation of `ad-redefinition-action' for possible values | |
| 185 ;; of this variable. Its default value is `warn' which will print a warning | |
| 186 ;; message when an already defined advised function gets redefined with a | |
| 187 ;; new original definition and de/activated. | |
| 188 | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
189 ;; Look at the documentation of `ad-default-compilation-action' for possible |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
190 ;; values of this variable. Its default value is `maybe' which will compile |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
191 ;; advised definitions during activation in case the byte-compiler is already |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
192 ;; loaded. Otherwise, it will leave them uncompiled. |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
193 |
| 4110 | 194 ;; @ Motivation: |
| 195 ;; ============= | |
| 196 ;; Before I go on explaining how advice works, here are four simple examples | |
| 197 ;; how this package can be used. The first three are very useful, the last one | |
| 198 ;; is just a joke: | |
| 199 | |
| 200 ;;(defadvice switch-to-buffer (before existing-buffers-only activate) | |
| 26217 | 201 ;; "When called interactively switch to existing buffers only, unless |
| 4110 | 202 ;;when called with a prefix argument." |
| 26217 | 203 ;; (interactive |
| 204 ;; (list (read-buffer "Switch to buffer: " (other-buffer) | |
| 4110 | 205 ;; (null current-prefix-arg))))) |
| 206 ;; | |
| 207 ;;(defadvice switch-to-buffer (around confirm-non-existing-buffers activate) | |
| 208 ;; "Switch to non-existing buffers only upon confirmation." | |
| 209 ;; (interactive "BSwitch to buffer: ") | |
| 210 ;; (if (or (get-buffer (ad-get-arg 0)) | |
| 211 ;; (y-or-n-p (format "`%s' does not exist, create? " (ad-get-arg 0)))) | |
| 212 ;; ad-do-it)) | |
| 213 ;; | |
| 214 ;;(defadvice find-file (before existing-files-only activate) | |
| 215 ;; "Find existing files only" | |
| 216 ;; (interactive "fFind file: ")) | |
| 217 ;; | |
| 218 ;;(defadvice car (around interactive activate) | |
| 219 ;; "Make `car' an interactive function." | |
| 220 ;; (interactive "xCar of list: ") | |
| 221 ;; ad-do-it | |
| 222 ;; (if (interactive-p) | |
| 223 ;; (message "%s" ad-return-value))) | |
| 224 | |
| 225 | |
| 226 ;; @ Advice documentation: | |
| 227 ;; ======================= | |
| 228 ;; Below is general documentation of the various features of advice. For more | |
| 229 ;; concrete examples check the corresponding sections in the tutorial part. | |
| 230 | |
| 231 ;; @@ Terminology: | |
| 232 ;; =============== | |
| 24875 | 233 ;; - Emacs, Emacs-19: Emacs as released by the GNU Project |
| 4110 | 234 ;; - Lemacs: Lucid's version of Emacs with major version 19 |
| 235 ;; - v18: Any Emacs with major version 18 or built as an extension to that | |
| 236 ;; (such as Epoch) | |
| 237 ;; - v19: Any Emacs with major version 19 | |
| 26217 | 238 ;; - jwz: Jamie Zawinski - former keeper of Lemacs and creator of the optimizing |
| 4110 | 239 ;; byte-compiler used in v19s. |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
240 ;; - Advice: The name of this package. |
| 4110 | 241 ;; - advices: Short for "pieces of advice". |
| 242 | |
| 243 ;; @@ Defining a piece of advice with `defadvice': | |
| 244 ;; =============================================== | |
| 245 ;; The main means of defining a piece of advice is the macro `defadvice', | |
| 246 ;; there is no interactive way of specifying a piece of advice. A call to | |
| 247 ;; `defadvice' has the following syntax which is similar to the syntax of | |
| 248 ;; `defun/defmacro': | |
| 249 ;; | |
| 250 ;; (defadvice <function> (<class> <name> [<position>] [<arglist>] {<flags>}*) | |
| 251 ;; [ [<documentation-string>] [<interactive-form>] ] | |
| 252 ;; {<body-form>}* ) | |
| 253 | |
| 254 ;; <function> is the name of the function/macro/subr to be advised. | |
| 255 | |
| 256 ;; <class> is the class of the advice which has to be one of `before', | |
| 257 ;; `around', `after', `activation' or `deactivation' (the last two allow | |
| 258 ;; definition of special act/deactivation hooks). | |
| 259 | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
260 ;; <name> is the name of the advice which has to be a non-nil symbol. |
| 4110 | 261 ;; Names uniquely identify a piece of advice in a certain advice class, |
| 262 ;; hence, advices can be redefined by defining an advice with the same class | |
| 263 ;; and name. Advice names are global symbols, hence, the same name space | |
| 264 ;; conventions used for function names should be applied. | |
| 265 | |
| 266 ;; An optional <position> specifies where in the current list of advices of | |
| 267 ;; the specified <class> this new advice will be placed. <position> has to | |
| 268 ;; be either `first', `last' or a number that specifies a zero-based | |
| 269 ;; position (`first' is equivalent to 0). If no position is specified | |
| 270 ;; `first' will be used as a default. If this call to `defadvice' redefines | |
| 271 ;; an already existing advice (see above) then the position argument will | |
| 272 ;; be ignored and the position of the already existing advice will be used. | |
| 273 | |
| 274 ;; An optional <arglist> which has to be a list can be used to define the | |
| 275 ;; argument list of the advised function. This argument list should of | |
| 276 ;; course be compatible with the argument list of the original function, | |
| 277 ;; otherwise functions that call the advised function with the original | |
| 278 ;; argument list in mind will break. If more than one advice specify an | |
| 279 ;; argument list then the first one (the one with the smallest position) | |
| 280 ;; found in the list of before/around/after advices will be used. | |
| 281 | |
| 282 ;; <flags> is a list of symbols that specify further information about the | |
| 283 ;; advice. All flags can be specified with unambiguous initial substrings. | |
| 284 ;; `activate': Specifies that the advice information of the advised | |
| 285 ;; function should be activated right after this advice has been | |
| 26217 | 286 ;; defined. In forward advices `activate' will be ignored. |
| 4110 | 287 ;; `protect': Specifies that this advice should be protected against |
| 288 ;; non-local exits and errors in preceding code/advices. | |
| 289 ;; `compile': Specifies that the advised function should be byte-compiled. | |
| 290 ;; This flag will be ignored unless `activate' is also specified. | |
| 291 ;; `disable': Specifies that the defined advice should be disabled, hence, | |
| 292 ;; it will not be used in an activation until somebody enables it. | |
| 293 ;; `preactivate': Specifies that the advised function should get preactivated | |
| 294 ;; at macro-expansion/compile time of this `defadvice'. This | |
| 295 ;; generates a compiled advised definition according to the | |
| 296 ;; current advice state which will be used during activation | |
| 297 ;; if appropriate. Only use this if the `defadvice' gets | |
| 298 ;; actually compiled (with a v18 byte-compiler put the `defadvice' | |
| 299 ;; into the body of a `defun' to accomplish proper compilation). | |
| 300 | |
| 301 ;; An optional <documentation-string> can be supplied to document the advice. | |
| 302 ;; On call of the `documentation' function it will be combined with the | |
| 303 ;; documentation strings of the original function and other advices. | |
| 304 | |
| 305 ;; An optional <interactive-form> form can be supplied to change/add | |
| 306 ;; interactive behavior of the original function. If more than one advice | |
| 307 ;; has an `(interactive ...)' specification then the first one (the one | |
| 308 ;; with the smallest position) found in the list of before/around/after | |
| 309 ;; advices will be used. | |
| 310 | |
| 311 ;; A possibly empty list of <body-forms> specifies the body of the advice in | |
| 312 ;; an implicit progn. The body of an advice can access/change arguments, | |
| 26217 | 313 ;; the return value, the binding environment, and can have all sorts of |
| 4110 | 314 ;; other side effects. |
| 315 | |
| 316 ;; @@ Assembling advised definitions: | |
| 317 ;; ================================== | |
| 318 ;; Suppose a function/macro/subr/special-form has N pieces of before advice, | |
| 319 ;; M pieces of around advice and K pieces of after advice. Assuming none of | |
| 320 ;; the advices is protected, its advised definition will look like this | |
| 321 ;; (body-form indices correspond to the position of the respective advice in | |
| 322 ;; that advice class): | |
| 323 | |
| 324 ;; ([macro] lambda <arglist> | |
| 325 ;; [ [<advised-docstring>] [(interactive ...)] ] | |
| 326 ;; (let (ad-return-value) | |
| 327 ;; {<before-0-body-form>}* | |
| 328 ;; .... | |
| 329 ;; {<before-N-1-body-form>}* | |
| 330 ;; {<around-0-body-form>}* | |
| 331 ;; {<around-1-body-form>}* | |
| 332 ;; .... | |
| 333 ;; {<around-M-1-body-form>}* | |
| 334 ;; (setq ad-return-value | |
| 335 ;; <apply original definition to <arglist>>) | |
| 336 ;; {<other-around-M-1-body-form>}* | |
| 337 ;; .... | |
| 338 ;; {<other-around-1-body-form>}* | |
| 339 ;; {<other-around-0-body-form>}* | |
| 340 ;; {<after-0-body-form>}* | |
| 341 ;; .... | |
| 342 ;; {<after-K-1-body-form>}* | |
| 343 ;; ad-return-value)) | |
| 344 | |
| 345 ;; Macros and special forms will be redefined as macros, hence the optional | |
| 346 ;; [macro] in the beginning of the definition. | |
| 347 | |
| 348 ;; <arglist> is either the argument list of the original function or the | |
| 349 ;; first argument list defined in the list of before/around/after advices. | |
| 350 ;; The values of <arglist> variables can be accessed/changed in the body of | |
| 351 ;; an advice by simply referring to them by their original name, however, | |
| 352 ;; more portable argument access macros are also provided (see below). For | |
| 353 ;; subrs/special-forms for which neither explicit argument list definitions | |
| 354 ;; are available, nor their documentation strings contain such definitions | |
| 355 ;; (as they do v19s), `(&rest ad-subr-args)' will be used. | |
| 356 | |
| 357 ;; <advised-docstring> is an optional, special documentation string which will | |
| 358 ;; be expanded into a proper documentation string upon call of `documentation'. | |
| 359 | |
| 360 ;; (interactive ...) is an optional interactive form either taken from the | |
| 361 ;; original function or from a before/around/after advice. For advised | |
| 362 ;; interactive subrs that do not have an interactive form specified in any | |
| 363 ;; advice we have to use (interactive) and then call the subr interactively | |
| 364 ;; if the advised function was called interactively, because the | |
| 365 ;; interactive specification of subrs is not accessible. This is the only | |
| 366 ;; case where changing the values of arguments will not have an affect | |
| 367 ;; because they will be reset by the interactive specification of the subr. | |
| 368 ;; If this is a problem one can always specify an interactive form in a | |
| 369 ;; before/around/after advice to gain control over argument values that | |
| 370 ;; were supplied interactively. | |
| 371 ;; | |
| 372 ;; Then the body forms of the various advices in the various classes of advice | |
| 373 ;; are assembled in order. The forms of around advice L are normally part of | |
| 374 ;; one of the forms of around advice L-1. An around advice can specify where | |
| 375 ;; the forms of the wrapped or surrounded forms should go with the special | |
| 376 ;; keyword `ad-do-it', which will be substituted with a `progn' containing the | |
| 377 ;; forms of the surrounded code. | |
| 378 | |
| 26217 | 379 ;; The innermost part of the around advice onion is |
| 4110 | 380 ;; <apply original definition to <arglist>> |
| 381 ;; whose form depends on the type of the original function. The variable | |
| 382 ;; `ad-return-value' will be set to its result. This variable is visible to | |
| 383 ;; all pieces of advice which can access and modify it before it gets returned. | |
| 384 ;; | |
| 385 ;; The semantic structure of advised functions that contain protected pieces | |
| 386 ;; of advice is the same. The only difference is that `unwind-protect' forms | |
| 387 ;; make sure that the protected advice gets executed even if some previous | |
| 388 ;; piece of advice had an error or a non-local exit. If any around advice is | |
| 389 ;; protected then the whole around advice onion will be protected. | |
| 390 | |
| 391 ;; @@ Argument access in advised functions: | |
| 392 ;; ======================================== | |
| 393 ;; As already mentioned, the simplest way to access the arguments of an | |
| 394 ;; advised function in the body of an advice is to refer to them by name. To | |
| 395 ;; do that, the advice programmer needs to know either the names of the | |
| 396 ;; argument variables of the original function, or the names used in the | |
| 397 ;; argument list redefinition given in a piece of advice. While this simple | |
| 398 ;; method might be sufficient in many cases, it has the disadvantage that it | |
| 399 ;; is not very portable because it hardcodes the argument names into the | |
| 400 ;; advice. If the definition of the original function changes the advice | |
| 401 ;; might break even though the code might still be correct. Situations like | |
| 402 ;; that arise, for example, if one advises a subr like `eval-region' which | |
| 403 ;; gets redefined in a non-advice style into a function by the edebug | |
| 404 ;; package. If the advice assumes `eval-region' to be a subr it might break | |
| 405 ;; once edebug is loaded. Similar situations arise when one wants to use the | |
| 406 ;; same piece of advice across different versions of Emacs. Some subrs in a | |
| 407 ;; v18 Emacs are functions in v19 and vice versa, but for the most part the | |
| 408 ;; semantics remain the same, hence, the same piece of advice might be usable | |
| 409 ;; in both Emacs versions. | |
| 410 | |
| 411 ;; As a solution to that advice provides argument list access macros that get | |
| 412 ;; translated into the proper access forms at activation time, i.e., when the | |
| 413 ;; advised definition gets constructed. Access macros access actual arguments | |
| 414 ;; by position regardless of how these actual argument get distributed onto | |
| 415 ;; the argument variables of a function. The rational behind this is that in | |
| 416 ;; Emacs Lisp the semantics of an argument is strictly determined by its | |
| 417 ;; position (there are no keyword arguments). | |
| 418 | |
| 419 ;; Suppose the function `foo' is defined as | |
| 420 ;; | |
| 421 ;; (defun foo (x y &optional z &rest r) ....) | |
| 422 ;; | |
| 423 ;; and is then called with | |
| 424 ;; | |
| 425 ;; (foo 0 1 2 3 4 5 6) | |
| 426 | |
| 427 ;; which means that X=0, Y=1, Z=2 and R=(3 4 5 6). The assumption is that | |
| 428 ;; the semantics of an actual argument is determined by its position. It is | |
| 429 ;; this semantics that has to be known by the advice programmer. Then s/he | |
| 430 ;; can access these arguments in a piece of advice with some of the | |
| 431 ;; following macros (the arrows indicate what value they will return): | |
| 432 | |
| 433 ;; (ad-get-arg 0) -> 0 | |
| 434 ;; (ad-get-arg 1) -> 1 | |
| 435 ;; (ad-get-arg 2) -> 2 | |
| 436 ;; (ad-get-arg 3) -> 3 | |
| 437 ;; (ad-get-args 2) -> (2 3 4 5 6) | |
| 438 ;; (ad-get-args 4) -> (4 5 6) | |
| 439 | |
| 440 ;; `(ad-get-arg <position>)' will return the actual argument that was supplied | |
| 441 ;; at <position>, `(ad-get-args <position>)' will return the list of actual | |
| 442 ;; arguments supplied starting at <position>. Note that these macros can be | |
| 443 ;; used without any knowledge about the form of the actual argument list of | |
| 444 ;; the original function. | |
| 445 | |
| 446 ;; Similarly, `(ad-set-arg <position> <value-form>)' can be used to set the | |
| 447 ;; value of the actual argument at <position> to <value-form>. For example, | |
| 448 ;; | |
| 449 ;; (ad-set-arg 5 "five") | |
| 450 ;; | |
| 451 ;; will have the effect that R=(3 4 "five" 6) once the original function is | |
| 452 ;; called. `(ad-set-args <position> <value-list-form>)' can be used to set | |
| 453 ;; the list of actual arguments starting at <position> to <value-list-form>. | |
| 454 ;; For example, | |
| 455 ;; | |
| 456 ;; (ad-set-args 0 '(5 4 3 2 1 0)) | |
| 457 ;; | |
| 458 ;; will have the effect that X=5, Y=4, Z=3 and R=(2 1 0) once the original | |
| 459 ;; function is called. | |
| 460 | |
| 461 ;; All these access macros are text macros rather than real Lisp macros. When | |
| 462 ;; the advised definition gets constructed they get replaced with actual access | |
| 463 ;; forms depending on the argument list of the advised function, i.e., after | |
| 464 ;; that argument access is in most cases as efficient as using the argument | |
| 465 ;; variable names directly. | |
| 466 | |
| 467 ;; @@@ Accessing argument bindings of arbitrary functions: | |
| 468 ;; ======================================================= | |
| 469 ;; Some functions (such as `trace-function' defined in trace.el) need a | |
| 470 ;; method of accessing the names and bindings of the arguments of an | |
| 471 ;; arbitrary advised function. To do that within an advice one can use the | |
| 472 ;; special keyword `ad-arg-bindings' which is a text macro that will be | |
| 473 ;; substituted with a form that will evaluate to a list of binding | |
| 474 ;; specifications, one for every argument variable. These binding | |
| 475 ;; specifications can then be examined in the body of the advice. For | |
| 476 ;; example, somewhere in an advice we could do this: | |
| 477 ;; | |
| 478 ;; (let* ((bindings ad-arg-bindings) | |
| 479 ;; (firstarg (car bindings)) | |
| 480 ;; (secondarg (car (cdr bindings)))) | |
| 481 ;; ;; Print info about first argument | |
| 482 ;; (print (format "%s=%s (%s)" | |
| 483 ;; (ad-arg-binding-field firstarg 'name) | |
| 484 ;; (ad-arg-binding-field firstarg 'value) | |
| 485 ;; (ad-arg-binding-field firstarg 'type))) | |
| 486 ;; ....) | |
| 487 ;; | |
| 488 ;; The `type' of an argument is either `required', `optional' or `rest'. | |
| 489 ;; Wherever `ad-arg-bindings' appears a form will be inserted that evaluates | |
| 490 ;; to the list of bindings, hence, in order to avoid multiple unnecessary | |
| 491 ;; evaluations one should always bind it to some variable. | |
| 492 | |
| 493 ;; @@@ Argument list mapping: | |
| 494 ;; ========================== | |
| 495 ;; Because `defadvice' allows the specification of the argument list of the | |
| 496 ;; advised function we need a mapping mechanism that maps this argument list | |
| 497 ;; onto that of the original function. For example, somebody might specify | |
| 498 ;; `(sym newdef)' as the argument list of `fset', while advice might use | |
| 499 ;; `(&rest ad-subr-args)' as the argument list of the original function | |
| 500 ;; (depending on what Emacs version is used). Hence SYM and NEWDEF have to | |
| 501 ;; be properly mapped onto the &rest variable when the original definition is | |
| 26217 | 502 ;; called. Advice automatically takes care of that mapping, hence, the advice |
| 4110 | 503 ;; programmer can specify an argument list without having to know about the |
| 504 ;; exact structure of the original argument list as long as the new argument | |
| 505 ;; list takes a compatible number/magnitude of actual arguments. | |
| 506 | |
| 507 ;; @@@ Definition of subr argument lists: | |
| 508 ;; ====================================== | |
| 509 ;; When advice constructs the advised definition of a function it has to | |
| 510 ;; know the argument list of the original function. For functions and macros | |
| 511 ;; the argument list can be determined from the actual definition, however, | |
| 512 ;; for subrs there is no such direct access available. In Lemacs and for some | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
513 ;; subrs in Emacs-19 the argument list of a subr can be determined from |
| 4110 | 514 ;; its documentation string, in a v18 Emacs even that is not possible. If |
| 515 ;; advice cannot at all determine the argument list of a subr it uses | |
| 516 ;; `(&rest ad-subr-args)' which will always work but is inefficient because | |
| 517 ;; it conses up arguments. The macro `ad-define-subr-args' can be used by | |
| 518 ;; the advice programmer to explicitly tell advice about the argument list | |
| 519 ;; of a certain subr, for example, | |
| 520 ;; | |
| 521 ;; (ad-define-subr-args 'fset '(sym newdef)) | |
| 522 ;; | |
| 523 ;; is used by advice itself to tell a v18 Emacs about the arguments of `fset'. | |
| 524 ;; The following can be used to undo such a definition: | |
| 525 ;; | |
| 526 ;; (ad-undefine-subr-args 'fset) | |
| 527 ;; | |
| 528 ;; The argument list definition is stored on the property list of the subr | |
| 529 ;; name symbol. When an argument list could be determined from the | |
| 530 ;; documentation string it will be cached under that property. The general | |
| 531 ;; mechanism for looking up the argument list of a subr is the following: | |
| 532 ;; 1) look for a definition stored on the property list | |
| 533 ;; 2) if that failed try to infer it from the documentation string and | |
| 534 ;; if successful cache it on the property list | |
| 535 ;; 3) otherwise use `(&rest ad-subr-args)' | |
| 536 | |
| 537 ;; @@ Activation and deactivation: | |
| 538 ;; =============================== | |
| 539 ;; The definition of an advised function does not change until all its advice | |
| 540 ;; gets actually activated. Activation can either happen with the `activate' | |
| 541 ;; flag specified in the `defadvice', with an explicit call or interactive | |
| 542 ;; invocation of `ad-activate', or if forward advice is enabled (i.e., the | |
| 543 ;; value of `ad-activate-on-definition' is t) at the time an already advised | |
| 544 ;; function gets defined. | |
| 545 | |
| 546 ;; When a function gets first activated its original definition gets saved, | |
| 547 ;; all defined and enabled pieces of advice will get combined with the | |
| 548 ;; original definition, the resulting definition might get compiled depending | |
| 549 ;; on some conditions described below, and then the function will get | |
| 550 ;; redefined with the advised definition. This also means that undefined | |
| 551 ;; functions cannot get activated even though they might be already advised. | |
| 552 | |
| 553 ;; The advised definition will get compiled either if `ad-activate' was called | |
| 554 ;; interactively with a prefix argument, or called explicitly with its second | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
555 ;; argument as t, or, if `ad-default-compilation-action' justifies it according |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
556 ;; to the current system state. If the advised definition was |
| 4110 | 557 ;; constructed during "preactivation" (see below) then that definition will |
| 558 ;; be already compiled because it was constructed during byte-compilation of | |
| 559 ;; the file that contained the `defadvice' with the `preactivate' flag. | |
| 560 | |
| 561 ;; `ad-deactivate' can be used to back-define an advised function to its | |
| 562 ;; original definition. It can be called interactively or directly. Because | |
| 563 ;; `ad-activate' caches the advised definition the function can be | |
| 564 ;; reactivated via `ad-activate' with only minor overhead (it is checked | |
| 565 ;; whether the current advice state is consistent with the cached | |
| 566 ;; definition, see the section on caching below). | |
| 567 | |
| 568 ;; `ad-activate-regexp' and `ad-deactivate-regexp' can be used to de/activate | |
| 569 ;; all currently advised function that have a piece of advice with a name that | |
| 570 ;; contains a match for a regular expression. These functions can be used to | |
| 571 ;; de/activate sets of functions depending on certain advice naming | |
| 572 ;; conventions. | |
| 573 | |
| 574 ;; Finally, `ad-activate-all' and `ad-deactivate-all' can be used to | |
| 575 ;; de/activate all currently advised functions. These are useful to | |
| 576 ;; (temporarily) return to an un/advised state. | |
| 577 | |
| 578 ;; @@@ Reasons for the separation of advice definition and activation: | |
| 579 ;; =================================================================== | |
| 580 ;; As already mentioned, advising happens in two stages: | |
| 581 | |
| 582 ;; 1) definition of various pieces of advice | |
| 583 ;; 2) activation of all advice currently defined and enabled | |
| 584 | |
| 585 ;; The advantage of this is that various pieces of advice can be defined | |
| 586 ;; before they get combined into an advised definition which avoids | |
| 587 ;; unnecessary constructions of intermediate advised definitions. The more | |
| 588 ;; important advantage is that it allows the implementation of forward advice. | |
| 589 ;; Advice information for a certain function accumulates as the value of the | |
| 590 ;; `advice-info' property of the function symbol. This accumulation is | |
| 591 ;; completely independent of the fact that that function might not yet be | |
| 592 ;; defined. The special forms `defun' and `defmacro' have been advised to | |
| 593 ;; check whether the function/macro they defined had advice information | |
| 594 ;; associated with it. If so and forward advice is enabled, the original | |
| 595 ;; definition will be saved, and then the advice will be activated. When a | |
| 596 ;; file is loaded in a v18 Emacs the functions/macros it defines are also | |
| 597 ;; defined with calls to `defun/defmacro'. Hence, we can forward advise | |
| 598 ;; functions/macros which will be defined later during a load/autoload of some | |
| 599 ;; file (for compiled files generated by jwz's byte-compiler in a v19 Emacs | |
| 600 ;; this is slightly more complicated but the basic idea is the same). | |
| 601 | |
| 602 ;; @@ Enabling/disabling pieces or sets of advice: | |
| 603 ;; =============================================== | |
| 604 ;; A major motivation for the development of this advice package was to bring | |
| 605 ;; a little bit more structure into the function overloading chaos in Emacs | |
| 606 ;; Lisp. Many packages achieve some of their functionality by adding a little | |
| 607 ;; bit (or a lot) to the standard functionality of some Emacs Lisp function. | |
| 608 ;; ange-ftp is a very popular package that achieves its magic by overloading | |
| 609 ;; most Emacs Lisp functions that deal with files. A popular function that's | |
| 610 ;; overloaded by many packages is `expand-file-name'. The situation that one | |
| 611 ;; function is multiply overloaded can arise easily. | |
| 612 | |
| 613 ;; Once in a while it would be desirable to be able to disable some/all | |
| 614 ;; overloads of a particular package while keeping all the rest. Ideally - | |
| 615 ;; at least in my opinion - these overloads would all be done with advice, | |
| 616 ;; I know I am dreaming right now... In that ideal case the enable/disable | |
| 617 ;; mechanism of advice could be used to achieve just that. | |
| 618 | |
| 619 ;; Every piece of advice is associated with an enablement flag. When the | |
| 620 ;; advised definition of a particular function gets constructed (e.g., during | |
| 621 ;; activation) only the currently enabled pieces of advice will be considered. | |
| 622 ;; This mechanism allows one to have different "views" of an advised function | |
| 623 ;; dependent on what pieces of advice are currently enabled. | |
| 624 | |
| 625 ;; Another motivation for this mechanism is that it allows one to define a | |
| 626 ;; piece of advice for some function yet keep it dormant until a certain | |
| 627 ;; condition is met. Until then activation of the function will not make use | |
| 628 ;; of that piece of advice. Once the condition is met the advice can be | |
| 629 ;; enabled and a reactivation of the function will add its functionality as | |
| 630 ;; part of the new advised definition. For example, the advices of `defun' | |
| 631 ;; etc. used by advice itself will stay disabled until `ad-start-advice' is | |
| 632 ;; called and some variables have the proper values. Hence, if somebody | |
| 633 ;; else advised these functions too and activates them the advices defined | |
| 634 ;; by advice will get used only if they are intended to be used. | |
| 635 | |
| 636 ;; The main interface to this mechanism are the interactive functions | |
| 637 ;; `ad-enable-advice' and `ad-disable-advice'. For example, the following | |
| 638 ;; would disable a particular advice of the function `foo': | |
| 639 ;; | |
| 640 ;; (ad-disable-advice 'foo 'before 'my-advice) | |
| 641 ;; | |
| 642 ;; This call by itself only changes the flag, to get the proper effect in | |
| 643 ;; the advised definition too one has to activate `foo' with | |
| 644 ;; | |
| 645 ;; (ad-activate 'foo) | |
| 646 ;; | |
| 647 ;; or interactively. To disable whole sets of advices one can use a regular | |
| 648 ;; expression mechanism. For example, let us assume that ange-ftp actually | |
| 649 ;; used advice to overload all its functions, and that it used the | |
| 650 ;; "ange-ftp-" prefix for all its advice names, then we could temporarily | |
| 651 ;; disable all its advices with | |
| 652 ;; | |
| 653 ;; (ad-disable-regexp "^ange-ftp-") | |
| 654 ;; | |
| 655 ;; and the following call would put that actually into effect: | |
| 656 ;; | |
| 657 ;; (ad-activate-regexp "^ange-ftp-") | |
| 658 ;; | |
| 659 ;; A saver way would have been to use | |
| 660 ;; | |
| 661 ;; (ad-update-regexp "^ange-ftp-") | |
| 662 ;; | |
| 663 ;; instead which would have only reactivated currently actively advised | |
| 664 ;; functions, but not functions that were currently deactivated. All these | |
| 665 ;; functions can also be called interactively. | |
| 666 | |
| 667 ;; A certain piece of advice is considered a match if its name contains a | |
| 668 ;; match for the regular expression. To enable ange-ftp again we would use | |
| 669 ;; `ad-enable-regexp' and then activate or update again. | |
| 670 | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
671 ;; @@ Forward advice, automatic advice activation: |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
672 ;; =============================================== |
| 4110 | 673 ;; Because most Emacs Lisp packages are loaded on demand via an autoload |
| 674 ;; mechanism it is essential to be able to "forward advise" functions. | |
| 675 ;; Otherwise, proper advice definition and activation would make it necessary | |
| 676 ;; to preload every file that defines a certain function before it can be | |
| 677 ;; advised, which would partly defeat the purpose of the advice mechanism. | |
| 678 | |
| 679 ;; In the following, "forward advice" always implies its automatic activation | |
| 680 ;; once a function gets defined, and not just the accumulation of advice | |
| 681 ;; information for a possibly undefined function. | |
| 682 | |
| 683 ;; Advice implements forward advice mainly via the following: 1) Separation | |
| 684 ;; of advice definition and activation that makes it possible to accumulate | |
| 685 ;; advice information without having the original function already defined, | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
686 ;; 2) special versions of the built-in functions `fset/defalias' which check |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
687 ;; for advice information whenever they define a function. If advice |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
688 ;; information was found then the advice will immediately get activated when |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
689 ;; the function gets defined. |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
690 |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
691 ;; Automatic advice activation means, that whenever a function gets defined |
| 4110 | 692 ;; with either `defun', `defmacro', `fset' or by loading a byte-compiled |
| 693 ;; file, and the function has some advice-info stored with it then that | |
| 694 ;; advice will get activated right away. | |
| 695 | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
696 ;; @@@ Enabling automatic advice activation: |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
697 ;; ========================================= |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
698 ;; Automatic advice activation is enabled by default. It can be disabled by |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
699 ;; doint `M-x ad-stop-advice' and enabled again with `M-x ad-start-advice'. |
| 4110 | 700 |
| 701 ;; @@ Caching of advised definitions: | |
| 702 ;; ================================== | |
| 703 ;; After an advised definition got constructed it gets cached as part of the | |
| 704 ;; advised function's advice-info so it can be reused, for example, after an | |
| 705 ;; intermediate deactivation. Because the advice-info of a function might | |
| 706 ;; change between the time of caching and reuse a cached definition gets | |
| 707 ;; a cache-id associated with it so it can be verified whether the cached | |
| 708 ;; definition is still valid (the main application of this is preactivation | |
| 709 ;; - see below). | |
| 710 | |
| 711 ;; When an advised function gets activated and a verifiable cached definition | |
| 712 ;; is available, then that definition will be used instead of creating a new | |
| 713 ;; advised definition from scratch. If you want to make sure that a new | |
| 714 ;; definition gets constructed then you should use `ad-clear-cache' before you | |
| 715 ;; activate the advised function. | |
| 716 | |
| 717 ;; @@ Preactivation: | |
| 718 ;; ================= | |
| 719 ;; Constructing an advised definition is moderately expensive. In a situation | |
| 720 ;; where one package defines a lot of advised functions it might be | |
| 721 ;; prohibitively expensive to do all the advised definition construction at | |
| 722 ;; runtime. Preactivation is a mechanism that allows compile-time construction | |
| 723 ;; of compiled advised definitions that can be activated cheaply during | |
| 724 ;; runtime. Preactivation uses the caching mechanism to do that. Here's how it | |
| 725 ;; works: | |
| 726 | |
| 727 ;; When the byte-compiler compiles a `defadvice' that has the `preactivate' | |
| 728 ;; flag specified, it uses the current original definition of the advised | |
| 729 ;; function plus the advice specified in this `defadvice' (even if it is | |
| 730 ;; specified as disabled) and all other currently enabled pieces of advice to | |
| 731 ;; construct an advised definition and an identifying cache-id and makes them | |
| 732 ;; part of the `defadvice' expansion which will then be compiled by the | |
| 733 ;; byte-compiler (to ensure that in a v18 emacs you have to put the | |
| 734 ;; `defadvice' inside a `defun' to get it compiled and then you have to call | |
| 735 ;; that compiled `defun' in order to actually execute the `defadvice'). When | |
| 736 ;; the file with the compiled, preactivating `defadvice' gets loaded the | |
| 737 ;; precompiled advised definition will be cached on the advised function's | |
| 738 ;; advice-info. When it gets activated (can be immediately on execution of the | |
| 739 ;; `defadvice' or any time later) the cache-id gets checked against the | |
| 740 ;; current state of advice and if it is verified the precompiled definition | |
| 741 ;; will be used directly (the verification is pretty cheap). If it couldn't get | |
| 742 ;; verified a new advised definition for that function will be built from | |
| 743 ;; scratch, hence, the efficiency added by the preactivation mechanism does | |
| 744 ;; not at all impair the flexibility of the advice mechanism. | |
| 745 | |
| 746 ;; MORAL: In order get all the efficiency out of preactivation the advice | |
| 747 ;; state of an advised function at the time the file with the | |
| 748 ;; preactivating `defadvice' gets byte-compiled should be exactly | |
| 749 ;; the same as it will be when the advice of that function gets | |
| 750 ;; actually activated. If it is not there is a high chance that the | |
| 751 ;; cache-id will not match and hence a new advised definition will | |
| 752 ;; have to be constructed at runtime. | |
| 753 | |
| 754 ;; Preactivation and forward advice do not contradict each other. It is | |
| 755 ;; perfectly ok to load a file with a preactivating `defadvice' before the | |
| 756 ;; original definition of the advised function is available. The constructed | |
| 757 ;; advised definition will be used once the original function gets defined and | |
| 758 ;; its advice gets activated. The only constraint is that at the time the | |
| 759 ;; file with the preactivating `defadvice' got compiled the original function | |
| 760 ;; definition was available. | |
| 761 | |
| 762 ;; TIPS: Here are some indications that a preactivation did not work the way | |
| 763 ;; you intended it to work: | |
| 764 ;; - Activation of the advised function takes longer than usual/expected | |
| 765 ;; - The byte-compiler gets loaded while an advised function gets | |
| 766 ;; activated | |
| 767 ;; - `byte-compile' is part of the `features' variable even though you | |
| 768 ;; did not use the byte-compiler | |
| 769 ;; Right now advice does not provide an elegant way to find out whether | |
| 770 ;; and why a preactivation failed. What you can do is to trace the | |
| 771 ;; function `ad-cache-id-verification-code' (with the function | |
| 772 ;; `trace-function-background' defined in my trace.el package) before | |
| 773 ;; any of your advised functions get activated. After they got | |
| 774 ;; activated check whether all calls to `ad-cache-id-verification-code' | |
| 775 ;; returned `verified' as a result. Other values indicate why the | |
| 776 ;; verification failed which should give you enough information to | |
| 777 ;; fix your preactivation/compile/load/activation sequence. | |
| 778 | |
| 26217 | 779 ;; IMPORTANT: There is one case (that I am aware of) that can make |
| 4110 | 780 ;; preactivation fail, i.e., a preconstructed advised definition that does |
| 781 ;; NOT match the current state of advice gets used nevertheless. That case | |
| 782 ;; arises if one package defines a certain piece of advice which gets used | |
| 26217 | 783 ;; during preactivation, and another package incompatibly redefines that |
| 4110 | 784 ;; very advice (i.e., same function/class/name), and it is the second advice |
| 785 ;; that is available when the preconstructed definition gets activated, and | |
| 26217 | 786 ;; that was the only definition of that advice so far (`ad-add-advice' |
| 787 ;; catches advice redefinitions and clears the cache in such a case). | |
| 4110 | 788 ;; Catching that would make the cache verification too expensive. |
| 789 | |
| 790 ;; MORAL-II: Redefining somebody else's advice is BAAAAD (to speak with | |
| 791 ;; George Walker Bush), and why would you redefine your own advice anyway? | |
| 792 ;; Advice is a mechanism to facilitate function redefinition, not advice | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
793 ;; redefinition (wait until I write Meta-Advice :-). If you really have |
| 4110 | 794 ;; to undo somebody else's advice try to write a "neutralizing" advice. |
| 795 | |
| 796 ;; @@ Advising macros and special forms and other dangerous things: | |
| 797 ;; ================================================================ | |
| 798 ;; Look at the corresponding tutorial sections for more information on | |
| 799 ;; these topics. Here it suffices to point out that the special treatment | |
| 800 ;; of macros and special forms by the byte-compiler can lead to problems | |
| 801 ;; when they get advised. Macros can create problems because they get | |
| 802 ;; expanded at compile time, hence, they might not have all the necessary | |
| 803 ;; runtime support and such advice cannot be de/activated or changed as | |
| 804 ;; it is possible for functions. Special forms create problems because they | |
| 805 ;; have to be advised "into" macros, i.e., an advised special form is a | |
| 806 ;; implemented as a macro, hence, in most cases the byte-compiler will | |
| 807 ;; not recognize it as a special form anymore which can lead to very strange | |
| 808 ;; results. | |
| 809 ;; | |
| 810 ;; MORAL: - Only advise macros or special forms when you are absolutely sure | |
| 811 ;; what you are doing. | |
| 812 ;; - As a safety measure, always do `ad-deactivate-all' before you | |
| 813 ;; byte-compile a file to make sure that even if some inconsiderate | |
| 814 ;; person advised some special forms you'll get proper compilation | |
| 815 ;; results. After compilation do `ad-activate-all' to get back to | |
| 816 ;; the previous state. | |
| 817 | |
| 818 ;; @@ Adding a piece of advice with `ad-add-advice': | |
| 819 ;; ================================================= | |
| 820 ;; The non-interactive function `ad-add-advice' can be used to add a piece of | |
| 821 ;; advice to some function without using `defadvice'. This is useful if advice | |
| 822 ;; has to be added somewhere by a function (also look at `ad-make-advice'). | |
| 823 | |
| 824 ;; @@ Activation/deactivation advices, file load hooks: | |
| 825 ;; ==================================================== | |
| 826 ;; There are two special classes of advice called `activation' and | |
| 827 ;; `deactivation'. The body forms of these advices are not included into the | |
| 828 ;; advised definition of a function, rather they are assembled into a hook | |
| 829 ;; form which will be evaluated whenever the advice-info of the advised | |
| 830 ;; function gets activated or deactivated. One application of this mechanism | |
| 831 ;; is to define file load hooks for files that do not provide such hooks | |
| 832 ;; (v19s already come with a general file-load-hook mechanism, v18s don't). | |
| 833 ;; For example, suppose you want to print a message whenever `file-x' gets | |
| 834 ;; loaded, and suppose the last function defined in `file-x' is | |
| 835 ;; `file-x-last-fn'. Then we can define the following advice: | |
| 836 ;; | |
| 837 ;; (defadvice file-x-last-fn (activation file-x-load-hook) | |
| 838 ;; "Executed whenever file-x is loaded" | |
| 839 ;; (if load-in-progress (message "Loaded file-x"))) | |
| 840 ;; | |
| 841 ;; This will constitute a forward advice for function `file-x-last-fn' which | |
| 842 ;; will get activated when `file-x' is loaded (only if forward advice is | |
| 843 ;; enabled of course). Because there are no "real" pieces of advice | |
| 844 ;; available for it, its definition will not be changed, but the activation | |
| 845 ;; advice will be run during its activation which is equivalent to having a | |
| 846 ;; file load hook for `file-x'. | |
| 847 | |
| 848 ;; @@ Summary of main advice concepts: | |
| 849 ;; =================================== | |
| 850 ;; - Definition: | |
| 851 ;; A piece of advice gets defined with `defadvice' and added to the | |
| 852 ;; `advice-info' property of a function. | |
| 853 ;; - Enablement: | |
| 854 ;; Every piece of advice has an enablement flag associated with it. Only | |
| 855 ;; enabled advices are considered during construction of an advised | |
| 856 ;; definition. | |
| 857 ;; - Activation: | |
| 858 ;; Redefine an advised function with its advised definition. Constructs | |
| 859 ;; an advised definition from scratch if no verifiable cached advised | |
| 860 ;; definition is available and caches it. | |
| 861 ;; - Deactivation: | |
| 862 ;; Back-define an advised function to its original definition. | |
| 863 ;; - Update: | |
| 26217 | 864 ;; Reactivate an advised function but only if its advice is currently |
| 4110 | 865 ;; active. This can be used to bring all currently advised function up |
| 866 ;; to date with the current state of advice without also activating | |
| 867 ;; currently deactivated functions. | |
| 868 ;; - Caching: | |
| 869 ;; Is the saving of an advised definition and an identifying cache-id so | |
| 870 ;; it can be reused, for example, for activation after deactivation. | |
| 871 ;; - Preactivation: | |
| 872 ;; Is the construction of an advised definition according to the current | |
| 873 ;; state of advice during byte-compilation of a file with a preactivating | |
| 874 ;; `defadvice'. That advised definition can then rather cheaply be used | |
| 875 ;; during activation without having to construct an advised definition | |
| 876 ;; from scratch at runtime. | |
| 877 | |
| 878 ;; @@ Summary of interactive advice manipulation functions: | |
| 879 ;; ======================================================== | |
| 880 ;; The following interactive functions can be used to manipulate the state | |
| 881 ;; of advised functions (all of them support completion on function names, | |
| 882 ;; advice classes and advice names): | |
| 883 | |
| 884 ;; - ad-activate to activate the advice of a FUNCTION | |
| 885 ;; - ad-deactivate to deactivate the advice of a FUNCTION | |
| 886 ;; - ad-update to activate the advice of a FUNCTION unless it was not | |
| 887 ;; yet activated or is currently deactivated. | |
| 26217 | 888 ;; - ad-unadvise deactivates a FUNCTION and removes all of its advice |
| 4110 | 889 ;; information, hence, it cannot be activated again |
| 890 ;; - ad-recover tries to redefine a FUNCTION to its original definition and | |
| 891 ;; discards all advice information (a low-level `ad-unadvise'). | |
| 892 ;; Use only in emergencies. | |
| 893 | |
| 894 ;; - ad-remove-advice removes a particular piece of advice of a FUNCTION. | |
| 895 ;; You still have to do call `ad-activate' or `ad-update' to | |
| 896 ;; activate the new state of advice. | |
| 897 ;; - ad-enable-advice enables a particular piece of advice of a FUNCTION. | |
| 898 ;; - ad-disable-advice disables a particular piece of advice of a FUNCTION. | |
| 899 ;; - ad-enable-regexp maps over all currently advised functions and enables | |
| 900 ;; every advice whose name contains a match for a regular | |
| 901 ;; expression. | |
| 902 ;; - ad-disable-regexp disables matching advices. | |
| 903 | |
| 904 ;; - ad-activate-regexp activates all advised function with a matching advice | |
| 905 ;; - ad-deactivate-regexp deactivates all advised function with matching advice | |
| 906 ;; - ad-update-regexp updates all advised function with a matching advice | |
| 907 ;; - ad-activate-all activates all advised functions | |
| 908 ;; - ad-deactivate-all deactivates all advised functions | |
| 909 ;; - ad-update-all updates all advised functions | |
| 910 ;; - ad-unadvise-all unadvises all advised functions | |
| 911 ;; - ad-recover-all recovers all advised functions | |
| 912 | |
| 913 ;; - ad-compile byte-compiles a function/macro if it is compilable. | |
| 914 | |
| 915 ;; @@ Summary of forms with special meanings when used within an advice: | |
| 916 ;; ===================================================================== | |
| 917 ;; ad-return-value name of the return value variable (get/settable) | |
| 918 ;; ad-subr-args name of &rest argument variable used for advised | |
| 919 ;; subrs whose actual argument list cannot be | |
| 920 ;; determined (get/settable) | |
| 921 ;; (ad-get-arg <pos>), (ad-get-args <pos>), | |
| 922 ;; (ad-set-arg <pos> <value>), (ad-set-args <pos> <value-list>) | |
| 923 ;; argument access text macros to get/set the values of | |
| 924 ;; actual arguments at a certain position | |
| 925 ;; ad-arg-bindings text macro that returns the actual names, values | |
| 926 ;; and types of the arguments as a list of bindings. The | |
| 927 ;; order of the bindings corresponds to the order of the | |
| 928 ;; arguments. The individual fields of every binding (name, | |
| 929 ;; value and type) can be accessed with the function | |
| 930 ;; `ad-arg-binding-field' (see example above). | |
| 931 ;; ad-do-it text macro that identifies the place where the original | |
| 932 ;; or wrapped definition should go in an around advice | |
| 933 | |
| 934 | |
| 935 ;; @ Foo games: An advice tutorial | |
| 936 ;; =============================== | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
937 ;; The following tutorial was created in Emacs 18.59. Left-justified |
| 4110 | 938 ;; s-expressions are input forms followed by one or more result forms. |
| 939 ;; First we have to start the advice magic: | |
| 940 ;; | |
| 941 ;; (ad-start-advice) | |
| 942 ;; nil | |
| 943 ;; | |
| 944 ;; We start by defining an innocent looking function `foo' that simply | |
| 945 ;; adds 1 to its argument X: | |
| 946 ;; | |
| 947 ;; (defun foo (x) | |
| 948 ;; "Add 1 to X." | |
| 949 ;; (1+ x)) | |
| 950 ;; foo | |
| 951 ;; | |
| 952 ;; (foo 3) | |
| 953 ;; 4 | |
| 954 ;; | |
| 955 ;; @@ Defining a simple piece of advice: | |
| 956 ;; ===================================== | |
| 957 ;; Now let's define the first piece of advice for `foo'. To do that we | |
| 958 ;; use the macro `defadvice' which takes a function name, a list of advice | |
| 959 ;; specifiers and a list of body forms as arguments. The first element of | |
| 960 ;; the advice specifiers is the class of the advice, the second is its name, | |
| 961 ;; the third its position and the rest are some flags. The class of our | |
| 962 ;; first advice is `before', its name is `fg-add2', its position among the | |
| 963 ;; currently defined before advices (none so far) is `first', and the advice | |
| 964 ;; will be `activate'ed immediately. Advice names are global symbols, hence, | |
| 965 ;; the name space conventions used for function names should be applied. All | |
| 966 ;; advice names in this tutorial will be prefixed with `fg' for `Foo Games' | |
| 967 ;; (because everybody has the right to be inconsistent all the function names | |
| 968 ;; used in this tutorial do NOT follow this convention). | |
| 969 ;; | |
| 970 ;; In the body of an advice we can refer to the argument variables of the | |
| 971 ;; original function by name. Here we add 1 to X so the effect of calling | |
| 972 ;; `foo' will be to actually add 2. All of the advice definitions below only | |
| 973 ;; have one body form for simplicity, but there is no restriction to that | |
| 974 ;; extent. Every piece of advice can have a documentation string which will | |
| 975 ;; be combined with the documentation of the original function. | |
| 976 ;; | |
| 977 ;; (defadvice foo (before fg-add2 first activate) | |
| 978 ;; "Add 2 to X." | |
| 979 ;; (setq x (1+ x))) | |
| 980 ;; foo | |
| 981 ;; | |
| 982 ;; (foo 3) | |
| 983 ;; 5 | |
| 984 ;; | |
| 985 ;; @@ Specifying the position of an advice: | |
| 986 ;; ======================================== | |
| 987 ;; Now we define the second before advice which will cancel the effect of | |
| 988 ;; the previous advice. This time we specify the position as 0 which is | |
| 989 ;; equivalent to `first'. A number can be used to specify the zero-based | |
| 990 ;; position of an advice among the list of advices in the same class. This | |
| 991 ;; time we already have one before advice hence the position specification | |
| 992 ;; actually has an effect. So, after the following definition the position | |
| 993 ;; of the previous advice will be 1 even though we specified it with `first' | |
| 994 ;; above, the reason for this is that the position argument is relative to | |
| 995 ;; the currently defined pieces of advice which by now has changed. | |
| 996 ;; | |
| 997 ;; (defadvice foo (before fg-cancel-add2 0 activate) | |
| 998 ;; "Again only add 1 to X." | |
| 999 ;; (setq x (1- x))) | |
| 1000 ;; foo | |
| 1001 ;; | |
| 1002 ;; (foo 3) | |
| 1003 ;; 4 | |
| 1004 ;; | |
| 1005 ;; @@ Redefining a piece of advice: | |
| 1006 ;; ================================ | |
| 1007 ;; Now we define an advice with the same class and same name but with a | |
| 1008 ;; different position. Defining an advice in a class in which an advice with | |
| 1009 ;; that name already exists is interpreted as a redefinition of that | |
| 1010 ;; particular advice, in which case the position argument will be ignored | |
| 1011 ;; and the previous position of the redefined piece of advice is used. | |
| 1012 ;; Advice flags can be specified with non-ambiguous initial substrings, hence, | |
| 1013 ;; from now on we'll use `act' instead of the verbose `activate'. | |
| 1014 ;; | |
| 1015 ;; (defadvice foo (before fg-cancel-add2 last act) | |
| 1016 ;; "Again only add 1 to X." | |
| 1017 ;; (setq x (1- x))) | |
| 1018 ;; foo | |
| 1019 ;; | |
| 1020 ;; @@ Assembly of advised documentation: | |
| 1021 ;; ===================================== | |
| 1022 ;; The documentation strings of the various pieces of advice are assembled | |
| 1023 ;; in order which shows that advice `fg-cancel-add2' is still the first | |
| 1024 ;; `before' advice even though we specified position `last' above: | |
| 1025 ;; | |
| 1026 ;; (documentation 'foo) | |
| 1027 ;; "Add 1 to X. | |
| 1028 ;; | |
| 1029 ;; This function is advised with the following advice(s): | |
| 1030 ;; | |
| 1031 ;; fg-cancel-add2 (before): | |
| 1032 ;; Again only add 1 to X. | |
| 1033 ;; | |
| 1034 ;; fg-add2 (before): | |
| 1035 ;; Add 2 to X." | |
| 1036 ;; | |
| 1037 ;; @@ Advising interactive behavior: | |
| 1038 ;; ================================= | |
| 1039 ;; We can make a function interactive (or change its interactive behavior) | |
| 1040 ;; by specifying an interactive form in one of the before or around | |
| 1041 ;; advices (there could also be body forms in this advice). The particular | |
| 1042 ;; definition always assigns 5 as an argument to X which gives us 6 as a | |
| 1043 ;; result when we call foo interactively: | |
| 1044 ;; | |
| 1045 ;; (defadvice foo (before fg-inter last act) | |
| 1046 ;; "Use 5 as argument when called interactively." | |
| 1047 ;; (interactive (list 5))) | |
| 1048 ;; foo | |
| 1049 ;; | |
| 1050 ;; (call-interactively 'foo) | |
| 1051 ;; 6 | |
| 1052 ;; | |
| 1053 ;; If more than one advice have an interactive declaration, then the one of | |
| 1054 ;; the advice with the smallest position will be used (before advices go | |
| 1055 ;; before around and after advices), hence, the declaration below does | |
| 1056 ;; not have any effect: | |
| 1057 ;; | |
| 1058 ;; (defadvice foo (before fg-inter2 last act) | |
| 1059 ;; (interactive (list 6))) | |
| 1060 ;; foo | |
| 1061 ;; | |
| 1062 ;; (call-interactively 'foo) | |
| 1063 ;; 6 | |
| 1064 ;; | |
| 26217 | 1065 ;; Let's have a look at what the definition of `foo' looks like now |
| 4110 | 1066 ;; (indentation added by hand for legibility): |
| 1067 ;; | |
| 1068 ;; (symbol-function 'foo) | |
| 1069 ;; (lambda (x) | |
| 1070 ;; "$ad-doc: foo$" | |
| 1071 ;; (interactive (list 5)) | |
| 26217 | 1072 ;; (let (ad-return-value) |
| 1073 ;; (setq x (1- x)) | |
| 1074 ;; (setq x (1+ x)) | |
| 1075 ;; (setq ad-return-value (ad-Orig-foo x)) | |
| 4110 | 1076 ;; ad-return-value)) |
| 1077 ;; | |
| 1078 ;; @@ Around advices: | |
| 1079 ;; ================== | |
| 1080 ;; Now we'll try some `around' advices. An around advice is a wrapper around | |
| 1081 ;; the original definition. It can shadow or establish bindings for the | |
| 1082 ;; original definition, and it can look at and manipulate the value returned | |
| 1083 ;; by the original function. The position of the special keyword `ad-do-it' | |
| 1084 ;; specifies where the code of the original function will be executed. The | |
| 1085 ;; keyword can appear multiple times which will result in multiple calls of | |
| 1086 ;; the original function in the resulting advised code. Note, that if we don't | |
| 26217 | 1087 ;; specify a position argument (i.e., `first', `last' or a number), then |
| 4110 | 1088 ;; `first' (or 0) is the default): |
| 1089 ;; | |
| 1090 ;; (defadvice foo (around fg-times-2 act) | |
| 1091 ;; "First double X." | |
| 1092 ;; (let ((x (* x 2))) | |
| 1093 ;; ad-do-it)) | |
| 1094 ;; foo | |
| 1095 ;; | |
| 1096 ;; (foo 3) | |
| 1097 ;; 7 | |
| 1098 ;; | |
| 1099 ;; Around advices are assembled like onion skins where the around advice | |
| 1100 ;; with position 0 is the outermost skin and the advice at the last position | |
| 1101 ;; is the innermost skin which is directly wrapped around the call of the | |
| 1102 ;; original definition of the function. Hence, after the next `defadvice' we | |
| 1103 ;; will first multiply X by 2 then add 1 and then call the original | |
| 1104 ;; definition (i.e., add 1 again): | |
| 1105 ;; | |
| 1106 ;; (defadvice foo (around fg-add-1 last act) | |
| 1107 ;; "Add 1 to X." | |
| 1108 ;; (let ((x (1+ x))) | |
| 1109 ;; ad-do-it)) | |
| 1110 ;; foo | |
| 1111 ;; | |
| 1112 ;; (foo 3) | |
| 1113 ;; 8 | |
| 1114 ;; | |
| 1115 ;; Again, let's see what the definition of `foo' looks like so far: | |
| 1116 ;; | |
| 1117 ;; (symbol-function 'foo) | |
| 26217 | 1118 ;; (lambda (x) |
| 4110 | 1119 ;; "$ad-doc: foo$" |
| 26217 | 1120 ;; (interactive (list 5)) |
| 1121 ;; (let (ad-return-value) | |
| 1122 ;; (setq x (1- x)) | |
| 1123 ;; (setq x (1+ x)) | |
| 1124 ;; (let ((x (* x 2))) | |
| 1125 ;; (let ((x (1+ x))) | |
| 1126 ;; (setq ad-return-value (ad-Orig-foo x)))) | |
| 4110 | 1127 ;; ad-return-value)) |
| 1128 ;; | |
| 1129 ;; @@ Controlling advice activation: | |
| 1130 ;; ================================= | |
| 1131 ;; In every `defadvice' so far we have used the flag `activate' to activate | |
| 1132 ;; the advice immediately after its definition, and that's what we want in | |
| 1133 ;; most cases. However, if we define multiple pieces of advice for a single | |
| 1134 ;; function then activating every advice immediately is inefficient. A | |
| 1135 ;; better way to do this is to only activate the last defined advice. | |
| 1136 ;; For example: | |
| 1137 ;; | |
| 1138 ;; (defadvice foo (after fg-times-x) | |
| 1139 ;; "Multiply the result with X." | |
| 1140 ;; (setq ad-return-value (* ad-return-value x))) | |
| 1141 ;; foo | |
| 1142 ;; | |
| 1143 ;; This still yields the same result as before: | |
| 1144 ;; (foo 3) | |
| 1145 ;; 8 | |
| 1146 ;; | |
| 1147 ;; Now we define another advice and activate which will also activate the | |
| 1148 ;; previous advice `fg-times-x'. Note the use of the special variable | |
| 1149 ;; `ad-return-value' in the body of the advice which is set to the result of | |
| 1150 ;; the original function. If we change its value then the value returned by | |
| 1151 ;; the advised function will be changed accordingly: | |
| 1152 ;; | |
| 1153 ;; (defadvice foo (after fg-times-x-again act) | |
| 1154 ;; "Again multiply the result with X." | |
| 1155 ;; (setq ad-return-value (* ad-return-value x))) | |
| 1156 ;; foo | |
| 1157 ;; | |
| 1158 ;; Now the advices have an effect: | |
| 1159 ;; | |
| 1160 ;; (foo 3) | |
| 1161 ;; 72 | |
| 1162 ;; | |
| 1163 ;; @@ Protecting advice execution: | |
| 1164 ;; =============================== | |
| 26217 | 1165 ;; Once in a while we define an advice to perform some cleanup action, |
| 4110 | 1166 ;; for example: |
| 1167 ;; | |
| 1168 ;; (defadvice foo (after fg-cleanup last act) | |
| 1169 ;; "Do some cleanup." | |
| 1170 ;; (print "Let's clean up now!")) | |
| 1171 ;; foo | |
| 1172 ;; | |
| 1173 ;; However, in case of an error the cleanup won't be performed: | |
| 1174 ;; | |
| 1175 ;; (condition-case error | |
| 1176 ;; (foo t) | |
| 1177 ;; (error 'error-in-foo)) | |
| 1178 ;; error-in-foo | |
| 1179 ;; | |
| 1180 ;; To make sure a certain piece of advice gets executed even if some error or | |
| 1181 ;; non-local exit occurred in any preceding code, we can protect it by using | |
| 1182 ;; the `protect' keyword. (if any of the around advices is protected then the | |
| 1183 ;; whole around advice onion will be protected): | |
| 1184 ;; | |
| 1185 ;; (defadvice foo (after fg-cleanup prot act) | |
| 1186 ;; "Do some protected cleanup." | |
| 1187 ;; (print "Let's clean up now!")) | |
| 1188 ;; foo | |
| 1189 ;; | |
| 1190 ;; Now the cleanup form will be executed even in case of an error: | |
| 1191 ;; | |
| 1192 ;; (condition-case error | |
| 1193 ;; (foo t) | |
| 1194 ;; (error 'error-in-foo)) | |
| 1195 ;; "Let's clean up now!" | |
| 1196 ;; error-in-foo | |
| 1197 ;; | |
| 1198 ;; Again, let's see what `foo' looks like: | |
| 1199 ;; | |
| 1200 ;; (symbol-function 'foo) | |
| 26217 | 1201 ;; (lambda (x) |
| 4110 | 1202 ;; "$ad-doc: foo$" |
| 26217 | 1203 ;; (interactive (list 5)) |
| 1204 ;; (let (ad-return-value) | |
| 1205 ;; (unwind-protect | |
| 1206 ;; (progn (setq x (1- x)) | |
| 1207 ;; (setq x (1+ x)) | |
| 1208 ;; (let ((x (* x 2))) | |
| 1209 ;; (let ((x (1+ x))) | |
| 1210 ;; (setq ad-return-value (ad-Orig-foo x)))) | |
| 1211 ;; (setq ad-return-value (* ad-return-value x)) | |
| 1212 ;; (setq ad-return-value (* ad-return-value x))) | |
| 1213 ;; (print "Let's clean up now!")) | |
| 4110 | 1214 ;; ad-return-value)) |
| 1215 ;; | |
| 1216 ;; @@ Compilation of advised definitions: | |
| 1217 ;; ====================================== | |
| 1218 ;; Finally, we can specify the `compile' keyword in a `defadvice' to say | |
| 1219 ;; that we want the resulting advised function to be byte-compiled | |
| 1220 ;; (`compile' will be ignored unless we also specified `activate'): | |
| 1221 ;; | |
| 1222 ;; (defadvice foo (after fg-cleanup prot act comp) | |
| 1223 ;; "Do some protected cleanup." | |
| 1224 ;; (print "Let's clean up now!")) | |
| 1225 ;; foo | |
| 1226 ;; | |
| 1227 ;; Now `foo' is byte-compiled: | |
| 1228 ;; | |
| 1229 ;; (symbol-function 'foo) | |
| 26217 | 1230 ;; (lambda (x) |
| 4110 | 1231 ;; "$ad-doc: foo$" |
| 26217 | 1232 ;; (interactive (byte-code "....." [5] 1)) |
| 4110 | 1233 ;; (byte-code "....." [ad-return-value x nil ((byte-code "....." [print "Let's clean up now!"] 2)) * 2 ad-Orig-foo] 6)) |
| 1234 ;; | |
| 1235 ;; (foo 3) | |
| 1236 ;; "Let's clean up now!" | |
| 1237 ;; 72 | |
| 1238 ;; | |
| 1239 ;; @@ Enabling and disabling pieces of advice: | |
| 1240 ;; =========================================== | |
| 1241 ;; Once in a while it is desirable to temporarily disable a piece of advice | |
| 1242 ;; so that it won't be considered during activation, for example, if two | |
| 1243 ;; different packages advise the same function and one wants to temporarily | |
| 1244 ;; neutralize the effect of the advice of one of the packages. | |
| 1245 ;; | |
| 1246 ;; The following disables the after advice `fg-times-x' in the function `foo'. | |
| 1247 ;; All that does is to change a flag for this particular advice. All the | |
| 1248 ;; other information defining it will be left unchanged (e.g., its relative | |
| 1249 ;; position in this advice class, etc.). | |
| 1250 ;; | |
| 1251 ;; (ad-disable-advice 'foo 'after 'fg-times-x) | |
| 1252 ;; nil | |
| 1253 ;; | |
| 1254 ;; For this to have an effect we have to activate `foo': | |
| 1255 ;; | |
| 1256 ;; (ad-activate 'foo) | |
| 1257 ;; foo | |
| 1258 ;; | |
| 1259 ;; (foo 3) | |
| 1260 ;; "Let's clean up now!" | |
| 1261 ;; 24 | |
| 1262 ;; | |
| 1263 ;; If we want to disable all multiplication advices in `foo' we can use a | |
| 1264 ;; regular expression that matches the names of such advices. Actually, any | |
| 1265 ;; advice name that contains a match for the regular expression will be | |
| 1266 ;; called a match. A special advice class `any' can be used to consider | |
| 1267 ;; all advice classes: | |
| 1268 ;; | |
| 1269 ;; (ad-disable-advice 'foo 'any "^fg-.*times") | |
| 1270 ;; nil | |
| 1271 ;; | |
| 1272 ;; (ad-activate 'foo) | |
| 1273 ;; foo | |
| 1274 ;; | |
| 1275 ;; (foo 3) | |
| 1276 ;; "Let's clean up now!" | |
| 1277 ;; 5 | |
| 1278 ;; | |
| 1279 ;; To enable the disabled advice we could use either `ad-enable-advice' | |
| 1280 ;; similar to `ad-disable-advice', or as an alternative `ad-enable-regexp' | |
| 1281 ;; which will enable matching advices in ALL currently advised functions. | |
| 1282 ;; Hence, this can be used to dis/enable advices made by a particular | |
| 1283 ;; package to a set of functions as long as that package obeys standard | |
| 1284 ;; advice name conventions. We prefixed all advice names with `fg-', hence | |
| 1285 ;; the following will do the trick (`ad-enable-regexp' returns the number | |
| 1286 ;; of matched advices): | |
| 1287 ;; | |
| 1288 ;; (ad-enable-regexp "^fg-") | |
| 1289 ;; 9 | |
| 1290 ;; | |
| 1291 ;; The following will activate all currently active advised functions that | |
| 1292 ;; contain some advice matched by the regular expression. This is a save | |
| 1293 ;; way to update the activation of advised functions whose advice changed | |
| 1294 ;; in some way or other without accidentally also activating currently | |
| 1295 ;; deactivated functions: | |
| 1296 ;; | |
| 1297 ;; (ad-update-regexp "^fg-") | |
| 1298 ;; nil | |
| 1299 ;; | |
| 1300 ;; (foo 3) | |
| 1301 ;; "Let's clean up now!" | |
| 1302 ;; 72 | |
| 1303 ;; | |
| 1304 ;; Another use for the dis/enablement mechanism is to define a piece of advice | |
| 1305 ;; and keep it "dormant" until a particular condition is satisfied, i.e., until | |
| 1306 ;; then the advice will not be used during activation. The `disable' flag lets | |
| 1307 ;; one do that with `defadvice': | |
| 1308 ;; | |
| 1309 ;; (defadvice foo (before fg-1-more dis) | |
| 1310 ;; "Add yet 1 more." | |
| 1311 ;; (setq x (1+ x))) | |
| 1312 ;; foo | |
| 1313 ;; | |
| 1314 ;; (ad-activate 'foo) | |
| 1315 ;; foo | |
| 1316 ;; | |
| 1317 ;; (foo 3) | |
| 1318 ;; "Let's clean up now!" | |
| 1319 ;; 72 | |
| 1320 ;; | |
| 1321 ;; (ad-enable-advice 'foo 'before 'fg-1-more) | |
| 1322 ;; nil | |
| 1323 ;; | |
| 1324 ;; (ad-activate 'foo) | |
| 1325 ;; foo | |
| 1326 ;; | |
| 1327 ;; (foo 3) | |
| 1328 ;; "Let's clean up now!" | |
| 1329 ;; 160 | |
| 1330 ;; | |
| 1331 ;; @@ Caching: | |
| 1332 ;; =========== | |
| 1333 ;; Advised definitions get cached to allow efficient activation/deactivation | |
| 1334 ;; without having to reconstruct them if nothing in the advice-info of a | |
| 1335 ;; function has changed. The following idiom can be used to temporarily | |
| 1336 ;; deactivate functions that have a piece of advice defined by a certain | |
| 1337 ;; package (we save the old definition to check out caching): | |
| 1338 ;; | |
| 1339 ;; (setq old-definition (symbol-function 'foo)) | |
| 1340 ;; (lambda (x) ....) | |
| 1341 ;; | |
| 1342 ;; (ad-deactivate-regexp "^fg-") | |
| 1343 ;; nil | |
| 1344 ;; | |
| 1345 ;; (foo 3) | |
| 1346 ;; 4 | |
| 1347 ;; | |
| 1348 ;; (ad-activate-regexp "^fg-") | |
| 1349 ;; nil | |
| 1350 ;; | |
| 1351 ;; (eq old-definition (symbol-function 'foo)) | |
| 1352 ;; t | |
| 1353 ;; | |
| 1354 ;; (foo 3) | |
| 1355 ;; "Let's clean up now!" | |
| 1356 ;; 160 | |
| 1357 ;; | |
| 1358 ;; @@ Forward advice: | |
| 1359 ;; ================== | |
| 1360 ;; To enable automatic activation of forward advice we first have to set | |
| 1361 ;; `ad-activate-on-definition' to t and restart advice: | |
| 1362 ;; | |
| 1363 ;; (setq ad-activate-on-definition t) | |
| 1364 ;; t | |
| 1365 ;; | |
| 1366 ;; (ad-start-advice) | |
| 1367 ;; (ad-activate-defined-function) | |
| 1368 ;; | |
| 1369 ;; Let's define a piece of advice for an undefined function: | |
| 1370 ;; | |
| 1371 ;; (defadvice bar (before fg-sub-1-more act) | |
| 1372 ;; "Subtract one more from X." | |
| 1373 ;; (setq x (1- x))) | |
| 1374 ;; bar | |
| 1375 ;; | |
| 1376 ;; `bar' is not yet defined: | |
| 1377 ;; (fboundp 'bar) | |
| 1378 ;; nil | |
| 1379 ;; | |
| 1380 ;; Now we define it and the forward advice will get activated (only because | |
| 1381 ;; `ad-activate-on-definition' was t when we started advice above with | |
| 1382 ;; `ad-start-advice'): | |
| 1383 ;; | |
| 1384 ;; (defun bar (x) | |
| 1385 ;; "Subtract 1 from X." | |
| 1386 ;; (1- x)) | |
| 1387 ;; bar | |
| 1388 ;; | |
| 1389 ;; (bar 4) | |
| 1390 ;; 2 | |
| 1391 ;; | |
| 1392 ;; Redefinition will activate any available advice if the value of | |
| 1393 ;; `ad-redefinition-action' is either `warn', `accept' or `discard': | |
| 1394 ;; | |
| 1395 ;; (defun bar (x) | |
| 1396 ;; "Subtract 2 from X." | |
| 1397 ;; (- x 2)) | |
| 1398 ;; bar | |
| 1399 ;; | |
| 1400 ;; (bar 4) | |
| 1401 ;; 1 | |
| 1402 ;; | |
| 1403 ;; @@ Preactivation: | |
| 1404 ;; ================= | |
| 1405 ;; Constructing advised definitions is moderately expensive, hence, it is | |
| 1406 ;; desirable to have a way to construct them at byte-compile time. | |
| 1407 ;; Preactivation is a mechanism that allows one to do that. | |
| 1408 ;; | |
| 1409 ;; (defun fie (x) | |
| 1410 ;; "Multiply X by 2." | |
| 1411 ;; (* x 2)) | |
| 1412 ;; fie | |
| 1413 ;; | |
| 1414 ;; (defadvice fie (before fg-times-4 preact) | |
| 1415 ;; "Multiply X by 4." | |
| 1416 ;; (setq x (* x 2))) | |
| 1417 ;; fie | |
| 1418 ;; | |
| 1419 ;; This advice did not affect `fie'... | |
| 1420 ;; | |
| 1421 ;; (fie 2) | |
| 1422 ;; 4 | |
| 1423 ;; | |
| 1424 ;; ...but it constructed a cached definition that will be used once `fie' gets | |
| 1425 ;; activated as long as its current advice state is the same as it was during | |
| 1426 ;; preactivation: | |
| 1427 ;; | |
| 1428 ;; (setq cached-definition (ad-get-cache-definition 'fie)) | |
| 1429 ;; (lambda (x) ....) | |
| 1430 ;; | |
| 1431 ;; (ad-activate 'fie) | |
| 1432 ;; fie | |
| 1433 ;; | |
| 1434 ;; (eq cached-definition (symbol-function 'fie)) | |
| 1435 ;; t | |
| 1436 ;; | |
| 1437 ;; (fie 2) | |
| 1438 ;; 8 | |
| 1439 ;; | |
| 11035 | 1440 ;; If you put a preactivating `defadvice' into a Lisp file that gets byte- |
| 4110 | 1441 ;; compiled then the constructed advised definition will get compiled by |
| 1442 ;; the byte-compiler. For that to occur in a v18 emacs you have to put the | |
| 1443 ;; `defadvice' inside a `defun' because the v18 compiler does not compile | |
| 1444 ;; top-level forms other than `defun' or `defmacro', for example, | |
| 1445 ;; | |
| 1446 ;; (defun fg-defadvice-fum () | |
| 1447 ;; (defadvice fum (before fg-times-4 preact act) | |
| 1448 ;; "Multiply X by 4." | |
| 1449 ;; (setq x (* x 2)))) | |
| 1450 ;; fg-defadvice-fum | |
| 1451 ;; | |
| 1452 ;; So far, no `defadvice' for `fum' got executed, but when we compile | |
| 1453 ;; `fg-defadvice-fum' the `defadvice' will be expanded by the byte compiler. | |
| 1454 ;; In order for preactivation to be effective we have to have a proper | |
| 1455 ;; definition of `fum' around at preactivation time, hence, we define it now: | |
| 1456 ;; | |
| 1457 ;; (defun fum (x) | |
| 1458 ;; "Multiply X by 2." | |
| 1459 ;; (* x 2)) | |
| 1460 ;; fum | |
| 1461 ;; | |
| 1462 ;; Now we compile the defining function which will construct an advised | |
| 1463 ;; definition during expansion of the `defadvice', compile it and store it | |
| 1464 ;; as part of the compiled `fg-defadvice-fum': | |
| 1465 ;; | |
| 1466 ;; (ad-compile-function 'fg-defadvice-fum) | |
| 1467 ;; (lambda nil (byte-code ...)) | |
| 1468 ;; | |
| 1469 ;; `fum' is still completely unaffected: | |
| 1470 ;; | |
| 1471 ;; (fum 2) | |
| 1472 ;; 4 | |
| 1473 ;; | |
| 1474 ;; (ad-get-advice-info 'fum) | |
| 1475 ;; nil | |
| 1476 ;; | |
| 1477 ;; (fg-defadvice-fum) | |
| 1478 ;; fum | |
| 1479 ;; | |
| 1480 ;; Now the advised version of `fum' is compiled because the compiled definition | |
| 1481 ;; constructed during preactivation was used, even though we did not specify | |
| 1482 ;; the `compile' flag: | |
| 1483 ;; | |
| 1484 ;; (symbol-function 'fum) | |
| 26217 | 1485 ;; (lambda (x) |
| 4110 | 1486 ;; "$ad-doc: fum$" |
| 1487 ;; (byte-code "....." [ad-return-value x nil * 2 ad-Orig-fum] 4)) | |
| 1488 ;; | |
| 1489 ;; (fum 2) | |
| 1490 ;; 8 | |
| 1491 ;; | |
| 1492 ;; A preactivated definition will only be used if it matches the current | |
| 1493 ;; function definition and advice information. If it does not match it | |
| 1494 ;; will simply be discarded and a new advised definition will be constructed | |
| 1495 ;; from scratch. For example, let's first remove all advice-info for `fum': | |
| 1496 ;; | |
| 1497 ;; (ad-unadvise 'fum) | |
| 1498 ;; (("fie") ("bar") ("foo") ...) | |
| 1499 ;; | |
| 1500 ;; And now define a new piece of advice: | |
| 1501 ;; | |
| 1502 ;; (defadvice fum (before fg-interactive act) | |
| 1503 ;; "Make fum interactive." | |
| 1504 ;; (interactive "nEnter x: ")) | |
| 1505 ;; fum | |
| 1506 ;; | |
| 1507 ;; When we now try to use a preactivation it will not be used because the | |
| 1508 ;; current advice state is different from the one at preactivation time. This | |
| 1509 ;; is no tragedy, everything will work as expected just not as efficient, | |
| 1510 ;; because a new advised definition has to be constructed from scratch: | |
| 1511 ;; | |
| 1512 ;; (fg-defadvice-fum) | |
| 1513 ;; fum | |
| 1514 ;; | |
| 1515 ;; A new uncompiled advised definition got constructed: | |
| 1516 ;; | |
| 1517 ;; (ad-compiled-p (symbol-function 'fum)) | |
| 1518 ;; nil | |
| 1519 ;; | |
| 1520 ;; (fum 2) | |
| 1521 ;; 8 | |
| 1522 ;; | |
| 1523 ;; MORAL: To get all the efficiency out of preactivation the function | |
| 1524 ;; definition and advice state at preactivation time must be the same as the | |
| 1525 ;; state at activation time. Preactivation does work with forward advice, all | |
| 1526 ;; that's necessary is that the definition of the forward advised function is | |
| 1527 ;; available when the `defadvice' with the preactivation gets compiled. | |
| 1528 ;; | |
| 1529 ;; @@ Portable argument access: | |
| 1530 ;; ============================ | |
| 1531 ;; So far, we always used the actual argument variable names to access an | |
| 1532 ;; argument in a piece of advice. For many advice applications this is | |
| 1533 ;; perfectly ok and keeps advices simple. However, it decreases portability | |
| 1534 ;; of advices because it assumes specific argument variable names. For example, | |
| 1535 ;; if one advises a subr such as `eval-region' which then gets redefined by | |
| 1536 ;; some package (e.g., edebug) into a function with different argument names, | |
| 1537 ;; then a piece of advice written for `eval-region' that was written with | |
| 1538 ;; the subr arguments in mind will break. Similar situations arise when one | |
| 1539 ;; switches between major Emacs versions, e.g., certain subrs in v18 are | |
| 1540 ;; functions in v19 and vice versa. Also, in v19s subr argument lists | |
| 1541 ;; are available and will be used, while they are not available in v18. | |
| 1542 ;; | |
| 1543 ;; Argument access text macros allow one to access arguments of an advised | |
| 1544 ;; function in a portable way without having to worry about all these | |
| 1545 ;; possibilities. These macros will be translated into the proper access forms | |
| 1546 ;; at activation time, hence, argument access will be as efficient as if | |
| 1547 ;; the arguments had been used directly in the definition of the advice. | |
| 1548 ;; | |
| 1549 ;; (defun fuu (x y z) | |
| 1550 ;; "Add 3 numbers." | |
| 1551 ;; (+ x y z)) | |
| 1552 ;; fuu | |
| 1553 ;; | |
| 1554 ;; (fuu 1 1 1) | |
| 1555 ;; 3 | |
| 1556 ;; | |
| 1557 ;; Argument access macros specify actual arguments at a certain position. | |
| 1558 ;; Position 0 access the first actual argument, position 1 the second etc. | |
| 1559 ;; For example, the following advice adds 1 to each of the 3 arguments: | |
| 1560 ;; | |
| 1561 ;; (defadvice fuu (before fg-add-1-to-all act) | |
| 1562 ;; "Adds 1 to all arguments." | |
| 1563 ;; (ad-set-arg 0 (1+ (ad-get-arg 0))) | |
| 1564 ;; (ad-set-arg 1 (1+ (ad-get-arg 1))) | |
| 1565 ;; (ad-set-arg 2 (1+ (ad-get-arg 2)))) | |
| 1566 ;; fuu | |
| 1567 ;; | |
| 1568 ;; (fuu 1 1 1) | |
| 1569 ;; 6 | |
| 1570 ;; | |
| 1571 ;; Now suppose somebody redefines `fuu' with a rest argument. Our advice | |
| 1572 ;; will still work because we used access macros (note, that automatic | |
| 1573 ;; advice activation is still in effect, hence, the redefinition of `fuu' | |
| 1574 ;; will automatically activate all its advice): | |
| 1575 ;; | |
| 1576 ;; (defun fuu (&rest numbers) | |
| 1577 ;; "Add NUMBERS." | |
| 1578 ;; (apply '+ numbers)) | |
| 1579 ;; fuu | |
| 1580 ;; | |
| 1581 ;; (fuu 1 1 1) | |
| 1582 ;; 6 | |
| 1583 ;; | |
| 1584 ;; (fuu 1 1 1 1 1 1) | |
| 1585 ;; 9 | |
| 1586 ;; | |
| 1587 ;; What's important to notice is that argument access macros access actual | |
| 1588 ;; arguments regardless of how they got distributed onto argument variables. | |
| 1589 ;; In Emacs Lisp the semantics of an actual argument is determined purely | |
| 1590 ;; by position, hence, as long as nobody changes the semantics of what a | |
| 1591 ;; certain actual argument at a certain position means the access macros | |
| 1592 ;; will do the right thing. | |
| 1593 ;; | |
| 1594 ;; Because of &rest arguments we need a second kind of access macro that | |
| 1595 ;; can access all actual arguments starting from a certain position: | |
| 1596 ;; | |
| 1597 ;; (defadvice fuu (before fg-print-args act) | |
| 1598 ;; "Print all arguments." | |
| 1599 ;; (print (ad-get-args 0))) | |
| 1600 ;; fuu | |
| 1601 ;; | |
| 1602 ;; (fuu 1 2 3 4 5) | |
| 1603 ;; (1 2 3 4 5) | |
| 1604 ;; 18 | |
| 1605 ;; | |
| 1606 ;; (defadvice fuu (before fg-set-args act) | |
| 1607 ;; "Swaps 2nd and 3rd arg and discards all the rest." | |
| 1608 ;; (ad-set-args 1 (list (ad-get-arg 2) (ad-get-arg 1)))) | |
| 1609 ;; fuu | |
| 1610 ;; | |
| 1611 ;; (fuu 1 2 3 4 4 4 4 4 4) | |
| 1612 ;; (1 3 2) | |
| 1613 ;; 9 | |
| 1614 ;; | |
| 1615 ;; (defun fuu (x y z) | |
| 1616 ;; "Add 3 numbers." | |
| 1617 ;; (+ x y z)) | |
| 1618 ;; | |
| 1619 ;; (fuu 1 2 3) | |
| 1620 ;; (1 3 2) | |
| 1621 ;; 9 | |
| 1622 ;; | |
| 1623 ;; @@ Defining the argument list of an advised function: | |
| 1624 ;; ===================================================== | |
| 1625 ;; Once in a while it might be desirable to advise a function and additionally | |
| 1626 ;; give it an extra argument that controls the advised code, for example, one | |
| 1627 ;; might want to make an interactive function sensitive to a prefix argument. | |
| 1628 ;; For such cases `defadvice' allows the specification of an argument list | |
| 26217 | 1629 ;; for the advised function. Similar to the redefinition of interactive |
| 4110 | 1630 ;; behavior, the first argument list specification found in the list of before/ |
| 1631 ;; around/after advices will be used. Of course, the specified argument list | |
| 1632 ;; should be downward compatible with the original argument list, otherwise | |
| 1633 ;; functions that call the advised function with the original argument list | |
| 1634 ;; in mind will break. | |
| 1635 ;; | |
| 1636 ;; (defun fii (x) | |
| 1637 ;; "Add 1 to X." | |
| 1638 ;; (1+ x)) | |
| 1639 ;; fii | |
| 1640 ;; | |
| 1641 ;; Now we advise `fii' to use an optional second argument that controls the | |
| 1642 ;; amount of incrementation. A list following the (optional) position | |
| 1643 ;; argument of the advice will be interpreted as an argument list | |
| 1644 ;; specification. This means you cannot specify an empty argument list, and | |
| 1645 ;; why would you want to anyway? | |
| 1646 ;; | |
| 1647 ;; (defadvice fii (before fg-inc-x (x &optional incr) act) | |
| 1648 ;; "Increment X by INCR (default is 1)." | |
| 1649 ;; (setq x (+ x (1- (or incr 1))))) | |
| 1650 ;; fii | |
| 1651 ;; | |
| 1652 ;; (fii 3) | |
| 1653 ;; 4 | |
| 1654 ;; | |
| 1655 ;; (fii 3 2) | |
| 1656 ;; 5 | |
| 1657 ;; | |
| 1658 ;; @@ Specifying argument lists of subrs: | |
| 1659 ;; ====================================== | |
| 1660 ;; The argument lists of subrs cannot be determined directly from Lisp. | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1661 ;; This means that Advice has to use `(&rest ad-subr-args)' as the |
| 4110 | 1662 ;; argument list of the advised subr which is not very efficient. In Lemacs |
| 1663 ;; subr argument lists can be determined from their documentation string, in | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1664 ;; Emacs-19 this is the case for some but not all subrs. To accommodate |
| 4110 | 1665 ;; for the cases where the argument lists cannot be determined (e.g., in a |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1666 ;; v18 Emacs) Advice comes with a specification mechanism that allows the |
| 4110 | 1667 ;; advice programmer to tell advice what the argument list of a certain subr |
| 1668 ;; really is. | |
| 1669 ;; | |
| 1670 ;; In a v18 Emacs the following will return the &rest idiom: | |
| 1671 ;; | |
| 1672 ;; (ad-arglist (symbol-function 'car)) | |
| 1673 ;; (&rest ad-subr-args) | |
| 1674 ;; | |
| 1675 ;; To tell advice what the argument list of `car' really is we | |
| 1676 ;; can do the following: | |
| 1677 ;; | |
| 1678 ;; (ad-define-subr-args 'car '(list)) | |
| 1679 ;; ((list)) | |
| 1680 ;; | |
| 1681 ;; Now `ad-arglist' will return the proper argument list (this method is | |
| 1682 ;; actually used by advice itself for the advised definition of `fset'): | |
| 1683 ;; | |
| 1684 ;; (ad-arglist (symbol-function 'car)) | |
| 1685 ;; (list) | |
| 1686 ;; | |
| 1687 ;; The defined argument list will be stored on the property list of the | |
| 1688 ;; subr name symbol. When advice looks for a subr argument list it first | |
| 1689 ;; checks for a definition on the property list, if that fails it tries | |
| 1690 ;; to infer it from the documentation string and caches it on the property | |
| 1691 ;; list if it was successful, otherwise `(&rest ad-subr-args)' will be used. | |
| 1692 ;; | |
| 1693 ;; @@ Advising interactive subrs: | |
| 1694 ;; ============================== | |
| 1695 ;; For the most part there is no difference between advising functions and | |
| 1696 ;; advising subrs. There is one situation though where one might have to write | |
| 1697 ;; slightly different advice code for subrs than for functions. This case | |
| 1698 ;; arises when one wants to access subr arguments in a before/around advice | |
| 1699 ;; when the arguments were determined by an interactive call to the subr. | |
| 1700 ;; Advice cannot determine what `interactive' form determines the interactive | |
| 1701 ;; behavior of the subr, hence, when it calls the original definition in an | |
| 1702 ;; interactive subr invocation it has to use `call-interactively' to generate | |
| 1703 ;; the proper interactive behavior. Thus up to that call the arguments of the | |
| 1704 ;; interactive subr will be nil. For example, the following advice for | |
| 1705 ;; `kill-buffer' will not work in an interactive invocation... | |
| 1706 ;; | |
| 1707 ;; (defadvice kill-buffer (before fg-kill-buffer-hook first act preact comp) | |
| 1708 ;; (my-before-kill-buffer-hook (ad-get-arg 0))) | |
| 1709 ;; kill-buffer | |
| 1710 ;; | |
| 1711 ;; ...because the buffer argument will be nil in that case. The way out of | |
| 1712 ;; this dilemma is to provide an `interactive' specification that mirrors | |
| 1713 ;; the interactive behavior of the unadvised subr, for example, the following | |
| 1714 ;; will do the right thing even when `kill-buffer' is called interactively: | |
| 1715 ;; | |
| 1716 ;; (defadvice kill-buffer (before fg-kill-buffer-hook first act preact comp) | |
| 1717 ;; (interactive "bKill buffer: ") | |
| 1718 ;; (my-before-kill-buffer-hook (ad-get-arg 0))) | |
| 1719 ;; kill-buffer | |
| 1720 ;; | |
| 1721 ;; @@ Advising macros: | |
| 1722 ;; =================== | |
| 1723 ;; Advising macros is slightly different because there are two significant | |
| 1724 ;; time points in the invocation of a macro: Expansion and evaluation time. | |
| 1725 ;; For an advised macro instead of evaluating the original definition we | |
| 1726 ;; use `macroexpand', that is, changing argument values and binding | |
| 1727 ;; environments by pieces of advice has an affect during macro expansion | |
| 1728 ;; but not necessarily during evaluation. In particular, any side effects | |
| 1729 ;; of pieces of advice will occur during macro expansion. To also affect | |
| 1730 ;; the behavior during evaluation time one has to change the value of | |
| 1731 ;; `ad-return-value' in a piece of after advice. For example: | |
| 1732 ;; | |
| 1733 ;; (defmacro foom (x) | |
| 1734 ;; (` (list (, x)))) | |
| 1735 ;; foom | |
| 1736 ;; | |
| 1737 ;; (foom '(a)) | |
| 1738 ;; ((a)) | |
| 1739 ;; | |
| 1740 ;; (defadvice foom (before fg-print-x act) | |
| 1741 ;; "Print the value of X." | |
| 1742 ;; (print x)) | |
| 1743 ;; foom | |
| 1744 ;; | |
| 1745 ;; The following works as expected because evaluation immediately follows | |
| 1746 ;; macro expansion: | |
| 1747 ;; | |
| 1748 ;; (foom '(a)) | |
| 1749 ;; (quote (a)) | |
| 1750 ;; ((a)) | |
| 1751 ;; | |
| 1752 ;; However, the printing happens during expansion (or byte-compile) time: | |
| 1753 ;; | |
| 1754 ;; (macroexpand '(foom '(a))) | |
| 1755 ;; (quote (a)) | |
| 1756 ;; (list (quote (a))) | |
| 1757 ;; | |
| 26217 | 1758 ;; If we want it to happen during evaluation time we have to do the |
| 4110 | 1759 ;; following (first remove the old advice): |
| 1760 ;; | |
| 1761 ;; (ad-remove-advice 'foom 'before 'fg-print-x) | |
| 1762 ;; nil | |
| 1763 ;; | |
| 1764 ;; (defadvice foom (after fg-print-x act) | |
| 1765 ;; "Print the value of X." | |
| 1766 ;; (setq ad-return-value | |
| 1767 ;; (` (progn (print (, x)) | |
| 1768 ;; (, ad-return-value))))) | |
| 1769 ;; foom | |
| 1770 ;; | |
| 1771 ;; (macroexpand '(foom '(a))) | |
| 1772 ;; (progn (print (quote (a))) (list (quote (a)))) | |
| 1773 ;; | |
| 1774 ;; (foom '(a)) | |
| 1775 ;; (a) | |
| 1776 ;; ((a)) | |
| 1777 ;; | |
| 1778 ;; While this method might seem somewhat cumbersome, it is very general | |
| 1779 ;; because it allows one to influence macro expansion as well as evaluation. | |
| 1780 ;; In general, advising macros should be a rather rare activity anyway, in | |
| 1781 ;; particular, because compile-time macro expansion takes away a lot of the | |
| 1782 ;; flexibility and effectiveness of the advice mechanism. Macros that were | |
| 1783 ;; compile-time expanded before the advice was activated will of course never | |
| 1784 ;; exhibit the advised behavior. | |
| 1785 ;; | |
| 1786 ;; @@ Advising special forms: | |
| 1787 ;; ========================== | |
| 1788 ;; Now for something that should be even more rare than advising macros: | |
| 1789 ;; Advising special forms. Because special forms are irregular in their | |
| 1790 ;; argument evaluation behavior (e.g., `setq' evaluates the second but not | |
| 1791 ;; the first argument) they have to be advised into macros. A dangerous | |
| 1792 ;; consequence of this is that the byte-compiler will not recognize them | |
| 1793 ;; as special forms anymore (well, in most cases) and use their expansion | |
| 1794 ;; rather than the proper byte-code. Also, because the original definition | |
| 1795 ;; of a special form cannot be `funcall'ed, `eval' has to be used instead | |
| 1796 ;; which is less efficient. | |
| 1797 ;; | |
| 1798 ;; MORAL: Do not advise special forms unless you are completely sure about | |
| 1799 ;; what you are doing (some of the forward advice behavior is | |
| 1800 ;; implemented via advice of the special forms `defun' and `defmacro'). | |
| 1801 ;; As a safety measure one should always do `ad-deactivate-all' before | |
| 1802 ;; one byte-compiles a file to avoid any interference of advised | |
| 1803 ;; special forms. | |
| 1804 ;; | |
| 1805 ;; Apart from the safety concerns advising special forms is not any different | |
| 1806 ;; from advising plain functions or subrs. | |
| 1807 | |
| 1808 | |
| 1809 ;;; Code: | |
| 1810 | |
| 1811 ;; @ Advice implementation: | |
| 1812 ;; ======================== | |
| 1813 | |
| 1814 ;; @@ Compilation idiosyncrasies: | |
| 1815 ;; ============================== | |
| 1816 | |
| 1817 ;; `defadvice' expansion needs quite a few advice functions and variables, | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1818 ;; hence, I need to preload the file before it can be compiled. To avoid |
| 4110 | 1819 ;; interference of bogus compiled files I always preload the source file: |
| 1820 (provide 'advice-preload) | |
| 1821 ;; During a normal load this is a noop: | |
| 1822 (require 'advice-preload "advice.el") | |
| 1823 | |
| 1824 | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
1825 ;; @@ Variable definitions: |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
1826 ;; ======================== |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
1827 |
| 21365 | 1828 (defgroup advice nil |
| 1829 "An overloading mechanism for Emacs Lisp functions." | |
| 1830 :prefix "ad-" | |
| 26217 | 1831 :link '(custom-manual "(elisp)Advising Functions") |
| 21365 | 1832 :group 'lisp) |
| 1833 | |
|
8458
a95ca44cec95
(ad-subr-arglist): Adapted to new DOC file format.
Richard M. Stallman <rms@gnu.org>
parents:
8445
diff
changeset
|
1834 (defconst ad-version "2.14") |
| 4110 | 1835 |
| 1836 ;;;###autoload | |
| 21365 | 1837 (defcustom ad-redefinition-action 'warn |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
1838 "*Defines what to do with redefinitions during Advice de/activation. |
| 4110 | 1839 Redefinition occurs if a previously activated function that already has an |
| 1840 original definition associated with it gets redefined and then de/activated. | |
| 1841 In such a case we can either accept the current definition as the new | |
| 1842 original definition, discard the current definition and replace it with the | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1843 old original, or keep it and raise an error. The values `accept', `discard', |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1844 `error' or `warn' govern what will be done. `warn' is just like `accept' but |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1845 it additionally prints a warning message. All other values will be |
| 21365 | 1846 interpreted as `error'." |
| 22577 | 1847 :type '(choice (const accept) (const discard) (const warn) |
| 1848 (other :tag "error" error)) | |
| 21365 | 1849 :group 'advice) |
| 4110 | 1850 |
| 1851 ;;;###autoload | |
| 21365 | 1852 (defcustom ad-default-compilation-action 'maybe |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
1853 "*Defines whether to compile advised definitions during activation. |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
1854 A value of `always' will result in unconditional compilation, `never' will |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
1855 always avoid compilation, `maybe' will compile if the byte-compiler is already |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
1856 loaded, and `like-original' will compile if the original definition of the |
| 26217 | 1857 advised function is compiled or a built-in function. Every other value will |
| 1858 be interpreted as `maybe'. This variable will only be considered if the | |
| 21365 | 1859 COMPILE argument of `ad-activate' was supplied as nil." |
| 22577 | 1860 :type '(choice (const always) (const never) (const like-original) |
| 1861 (other :tag "maybe" maybe)) | |
| 21365 | 1862 :group 'advice) |
| 1863 | |
| 4110 | 1864 |
| 1865 | |
| 1866 ;; @@ Some utilities: | |
| 1867 ;; ================== | |
| 1868 | |
| 1869 ;; We don't want the local arguments to interfere with anything | |
| 1870 ;; referenced in the supplied functions => the cryptic casing: | |
| 1871 (defun ad-substitute-tree (sUbTrEe-TeSt fUnCtIoN tReE) | |
| 26217 | 1872 "Substitute qualifying subTREEs with result of FUNCTION(subTREE). |
| 1873 Only proper subtrees are considered, for example, if TREE is (1 (2 (3)) 4) | |
| 1874 then the subtrees will be 1 (2 (3)) 2 (3) 3 4, dotted structures are | |
| 1875 allowed too. Once a qualifying subtree has been found its subtrees will | |
| 1876 not be considered anymore. (ad-substitute-tree 'atom 'identity tree) | |
| 1877 generates a copy of TREE." | |
| 4110 | 1878 (cond ((consp tReE) |
| 1879 (cons (if (funcall sUbTrEe-TeSt (car tReE)) | |
| 1880 (funcall fUnCtIoN (car tReE)) | |
| 1881 (if (consp (car tReE)) | |
| 1882 (ad-substitute-tree sUbTrEe-TeSt fUnCtIoN (car tReE)) | |
| 1883 (car tReE))) | |
| 1884 (ad-substitute-tree sUbTrEe-TeSt fUnCtIoN (cdr tReE)))) | |
| 1885 ((funcall sUbTrEe-TeSt tReE) | |
| 1886 (funcall fUnCtIoN tReE)) | |
| 1887 (t tReE))) | |
| 1888 | |
| 1889 ;; this is just faster than `ad-substitute-tree': | |
| 1890 (defun ad-copy-tree (tree) | |
| 26217 | 1891 "Return a copy of the list structure of TREE." |
| 4110 | 1892 (cond ((consp tree) |
| 1893 (cons (ad-copy-tree (car tree)) | |
| 1894 (ad-copy-tree (cdr tree)))) | |
| 1895 (t tree))) | |
| 1896 | |
| 1897 (defmacro ad-dolist (varform &rest body) | |
| 1898 "A Common-Lisp-style dolist iterator with the following syntax: | |
| 1899 | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1900 (ad-dolist (VAR INIT-FORM [RESULT-FORM]) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1901 BODY-FORM...) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1902 |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1903 which will iterate over the list yielded by INIT-FORM binding VAR to the |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1904 current head at every iteration. If RESULT-FORM is supplied its value will |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1905 be returned at the end of the iteration, nil otherwise. The iteration can be |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1906 exited prematurely with `(ad-do-return [VALUE])'." |
| 4110 | 1907 (let ((expansion |
| 1908 (` (let ((ad-dO-vAr (, (car (cdr varform)))) | |
| 1909 (, (car varform))) | |
| 1910 (while ad-dO-vAr | |
| 1911 (setq (, (car varform)) (car ad-dO-vAr)) | |
| 1912 (,@ body) | |
| 1913 ;;work around a backquote bug: | |
| 1914 ;;(` ((,@ '(foo)) (bar))) => (append '(foo) '(((bar)))) wrong | |
| 1915 ;;(` ((,@ '(foo)) (, '(bar)))) => (append '(foo) (list '(bar))) | |
| 1916 (, '(setq ad-dO-vAr (cdr ad-dO-vAr)))) | |
| 1917 (, (car (cdr (cdr varform)))))))) | |
| 1918 ;;ok, this wastes some cons cells but only during compilation: | |
| 1919 (if (catch 'contains-return | |
| 1920 (ad-substitute-tree | |
| 1921 (function (lambda (subtree) | |
| 1922 (cond ((eq (car-safe subtree) 'ad-dolist)) | |
| 1923 ((eq (car-safe subtree) 'ad-do-return) | |
| 1924 (throw 'contains-return t))))) | |
| 1925 'identity body) | |
| 1926 nil) | |
| 1927 (` (catch 'ad-dO-eXiT (, expansion))) | |
| 1928 expansion))) | |
| 1929 | |
| 1930 (defmacro ad-do-return (value) | |
| 1931 (` (throw 'ad-dO-eXiT (, value)))) | |
| 1932 | |
| 1933 (if (not (get 'ad-dolist 'lisp-indent-hook)) | |
| 1934 (put 'ad-dolist 'lisp-indent-hook 1)) | |
| 1935 | |
| 1936 | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1937 ;; @@ Save real definitions of subrs used by Advice: |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1938 ;; ================================================= |
| 26217 | 1939 ;; Advice depends on the real, unmodified functionality of various subrs, |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1940 ;; we save them here so advised versions will not interfere (eventually, |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1941 ;; we will save all subrs used in code generated by Advice): |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1942 |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1943 (defmacro ad-save-real-definition (function) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1944 (let ((saved-function (intern (format "ad-real-%s" function)))) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1945 ;; Make sure the compiler is loaded during macro expansion: |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1946 (require 'byte-compile "bytecomp") |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1947 (` (if (not (fboundp '(, saved-function))) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1948 (progn (fset '(, saved-function) (symbol-function '(, function))) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1949 ;; Copy byte-compiler properties: |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1950 (,@ (if (get function 'byte-compile) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1951 (` ((put '(, saved-function) 'byte-compile |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1952 '(, (get function 'byte-compile))))))) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1953 (,@ (if (get function 'byte-opcode) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1954 (` ((put '(, saved-function) 'byte-opcode |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1955 '(, (get function 'byte-opcode)))))))))))) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1956 |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1957 (defun ad-save-real-definitions () |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1958 ;; Macro expansion will hardcode the values of the various byte-compiler |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1959 ;; properties into the compiled version of this function such that the |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1960 ;; proper values will be available at runtime without loading the compiler: |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1961 (ad-save-real-definition fset) |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
1962 (ad-save-real-definition documentation)) |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1963 |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1964 (ad-save-real-definitions) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1965 |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1966 |
| 4110 | 1967 ;; @@ Advice info access fns: |
| 1968 ;; ========================== | |
| 1969 | |
| 1970 ;; Advice information for a particular function is stored on the | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
1971 ;; advice-info property of the function symbol. It is stored as an |
| 4110 | 1972 ;; alist of the following format: |
| 1973 ;; | |
| 1974 ;; ((active . t/nil) | |
| 1975 ;; (before adv1 adv2 ...) | |
| 1976 ;; (around adv1 adv2 ...) | |
| 1977 ;; (after adv1 adv2 ...) | |
| 1978 ;; (activation adv1 adv2 ...) | |
| 1979 ;; (deactivation adv1 adv2 ...) | |
| 1980 ;; (origname . <symbol fbound to origdef>) | |
| 1981 ;; (cache . (<advised-definition> . <id>))) | |
| 1982 | |
| 1983 ;; List of currently advised though not necessarily activated functions | |
| 1984 ;; (this list is maintained as a completion table): | |
| 1985 (defvar ad-advised-functions nil) | |
| 1986 | |
| 1987 (defmacro ad-pushnew-advised-function (function) | |
| 26217 | 1988 "Add FUNCTION to `ad-advised-functions' unless its already there." |
| 4110 | 1989 (` (if (not (assoc (symbol-name (, function)) ad-advised-functions)) |
| 1990 (setq ad-advised-functions | |
| 1991 (cons (list (symbol-name (, function))) | |
| 1992 ad-advised-functions))))) | |
| 1993 | |
| 1994 (defmacro ad-pop-advised-function (function) | |
| 26217 | 1995 "Remove FUNCTION from `ad-advised-functions'." |
| 4110 | 1996 (` (setq ad-advised-functions |
| 1997 (delq (assoc (symbol-name (, function)) ad-advised-functions) | |
| 1998 ad-advised-functions)))) | |
| 1999 | |
| 2000 (defmacro ad-do-advised-functions (varform &rest body) | |
| 26217 | 2001 "`ad-dolist'-style iterator that maps over `ad-advised-functions'. |
| 2002 \(ad-do-advised-functions (VAR [RESULT-FORM]) | |
| 2003 BODY-FORM...) | |
| 2004 On each iteration VAR will be bound to the name of an advised function | |
| 2005 \(a symbol)." | |
| 4110 | 2006 (` (ad-dolist ((, (car varform)) |
| 2007 ad-advised-functions | |
| 2008 (, (car (cdr varform)))) | |
| 2009 (setq (, (car varform)) (intern (car (, (car varform))))) | |
| 2010 (,@ body)))) | |
| 2011 | |
| 2012 (if (not (get 'ad-do-advised-functions 'lisp-indent-hook)) | |
| 2013 (put 'ad-do-advised-functions 'lisp-indent-hook 1)) | |
| 2014 | |
| 2015 (defmacro ad-get-advice-info (function) | |
| 2016 (` (get (, function) 'ad-advice-info))) | |
| 2017 | |
| 2018 (defmacro ad-set-advice-info (function advice-info) | |
| 2019 (` (put (, function) 'ad-advice-info (, advice-info)))) | |
| 2020 | |
| 2021 (defmacro ad-copy-advice-info (function) | |
| 2022 (` (ad-copy-tree (get (, function) 'ad-advice-info)))) | |
| 2023 | |
| 2024 (defmacro ad-is-advised (function) | |
| 26217 | 2025 "Return non-nil if FUNCTION has any advice info associated with it. |
| 2026 This does not mean that the advice is also active." | |
| 4110 | 2027 (list 'ad-get-advice-info function)) |
| 2028 | |
| 2029 (defun ad-initialize-advice-info (function) | |
| 26217 | 2030 "Initialize the advice info for FUNCTION. |
| 2031 Assumes that FUNCTION has not yet been advised." | |
| 4110 | 2032 (ad-pushnew-advised-function function) |
| 2033 (ad-set-advice-info function (list (cons 'active nil)))) | |
| 2034 | |
| 2035 (defmacro ad-get-advice-info-field (function field) | |
| 26217 | 2036 "Retrieve the value of the advice info FIELD of FUNCTION." |
| 4110 | 2037 (` (cdr (assq (, field) (ad-get-advice-info (, function)))))) |
| 2038 | |
| 2039 (defun ad-set-advice-info-field (function field value) | |
| 26217 | 2040 "Destructively modify VALUE of the advice info FIELD of FUNCTION." |
| 4110 | 2041 (and (ad-is-advised function) |
| 2042 (cond ((assq field (ad-get-advice-info function)) | |
| 2043 ;; A field with that name is already present: | |
| 2044 (rplacd (assq field (ad-get-advice-info function)) value)) | |
| 2045 (t;; otherwise, create a new field with that name: | |
| 2046 (nconc (ad-get-advice-info function) | |
| 2047 (list (cons field value))))))) | |
| 2048 | |
| 2049 ;; Don't make this a macro so we can use it as a predicate: | |
| 2050 (defun ad-is-active (function) | |
| 26217 | 2051 "Return non-nil if FUNCTION is advised and activated." |
| 4110 | 2052 (ad-get-advice-info-field function 'active)) |
| 2053 | |
| 2054 | |
| 2055 ;; @@ Access fns for single pieces of advice and related predicates: | |
| 2056 ;; ================================================================= | |
| 2057 | |
| 2058 (defun ad-make-advice (name protect enable definition) | |
| 2059 "Constructs single piece of advice to be stored in some advice-info. | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2060 NAME should be a non-nil symbol, PROTECT and ENABLE should each be |
| 4110 | 2061 either t or nil, and DEFINITION should be a list of the form |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2062 `(advice lambda ARGLIST [DOCSTRING] [INTERACTIVE-FORM] BODY...)'." |
| 4110 | 2063 (list name protect enable definition)) |
| 2064 | |
| 2065 ;; ad-find-advice uses the alist structure directly -> | |
| 2066 ;; change if this data structure changes!! | |
| 2067 (defmacro ad-advice-name (advice) | |
| 2068 (list 'car advice)) | |
| 2069 (defmacro ad-advice-protected (advice) | |
| 2070 (list 'nth 1 advice)) | |
| 2071 (defmacro ad-advice-enabled (advice) | |
| 2072 (list 'nth 2 advice)) | |
| 2073 (defmacro ad-advice-definition (advice) | |
| 2074 (list 'nth 3 advice)) | |
| 2075 | |
| 2076 (defun ad-advice-set-enabled (advice flag) | |
| 2077 (rplaca (cdr (cdr advice)) flag)) | |
| 2078 | |
| 2079 (defun ad-class-p (thing) | |
| 2080 (memq thing ad-advice-classes)) | |
| 2081 (defun ad-name-p (thing) | |
| 2082 (and thing (symbolp thing))) | |
| 2083 (defun ad-position-p (thing) | |
| 2084 (or (natnump thing) | |
| 2085 (memq thing '(first last)))) | |
| 2086 | |
| 2087 | |
| 2088 ;; @@ Advice access functions: | |
| 2089 ;; =========================== | |
| 2090 | |
| 2091 ;; List of defined advice classes: | |
| 2092 (defvar ad-advice-classes '(before around after activation deactivation)) | |
| 2093 | |
| 2094 (defun ad-has-enabled-advice (function class) | |
| 26217 | 2095 "True if at least one of FUNCTION's advices in CLASS is enabled." |
| 4110 | 2096 (ad-dolist (advice (ad-get-advice-info-field function class)) |
| 2097 (if (ad-advice-enabled advice) (ad-do-return t)))) | |
| 2098 | |
| 2099 (defun ad-has-redefining-advice (function) | |
| 26217 | 2100 "True if FUNCTION's advice info defines at least 1 redefining advice. |
| 2101 Redefining advices affect the construction of an advised definition." | |
| 4110 | 2102 (and (ad-is-advised function) |
| 2103 (or (ad-has-enabled-advice function 'before) | |
| 2104 (ad-has-enabled-advice function 'around) | |
| 2105 (ad-has-enabled-advice function 'after)))) | |
| 2106 | |
| 2107 (defun ad-has-any-advice (function) | |
| 26217 | 2108 "True if the advice info of FUNCTION defines at least one advice." |
| 4110 | 2109 (and (ad-is-advised function) |
| 2110 (ad-dolist (class ad-advice-classes nil) | |
| 2111 (if (ad-get-advice-info-field function class) | |
| 2112 (ad-do-return t))))) | |
| 2113 | |
| 2114 (defun ad-get-enabled-advices (function class) | |
| 26217 | 2115 "Return the list of enabled advices of FUNCTION in CLASS." |
| 4110 | 2116 (let (enabled-advices) |
| 2117 (ad-dolist (advice (ad-get-advice-info-field function class)) | |
| 2118 (if (ad-advice-enabled advice) | |
| 2119 (setq enabled-advices (cons advice enabled-advices)))) | |
| 2120 (reverse enabled-advices))) | |
| 2121 | |
| 2122 | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2123 ;; @@ Dealing with automatic advice activation via `fset/defalias': |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2124 ;; ================================================================ |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2125 |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2126 ;; Since Emacs 19.26 the built-in versions of `fset' and `defalias' |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2127 ;; take care of automatic advice activation, hence, we don't have to |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2128 ;; hack it anymore by advising `fset/defun/defmacro/byte-code/etc'. |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2129 |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2130 ;; The functionality of the new `fset' is as follows: |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2131 ;; |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2132 ;; fset(sym,newdef) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2133 ;; assign NEWDEF to SYM |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2134 ;; if (get SYM 'ad-advice-info) |
|
26206
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
2135 ;; ad-activate-internal(SYM, nil) |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2136 ;; return (symbol-function SYM) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2137 ;; |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2138 ;; Whether advised definitions created by automatic activations will be |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2139 ;; compiled depends on the value of `ad-default-compilation-action'. |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2140 |
|
26206
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
2141 ;; Since calling `ad-activate-internal' in the built-in definition of `fset' can |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2142 ;; create major disasters we have to be a bit careful. One precaution is |
|
26206
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
2143 ;; to provide a dummy definition for `ad-activate-internal' which can be used to |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2144 ;; turn off automatic advice activation (e.g., when `ad-stop-advice' or |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2145 ;; `ad-recover-normality' are called). Another is to avoid recursive calls |
|
26206
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
2146 ;; to `ad-activate' by using `ad-with-auto-activation-disabled' where |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2147 ;; appropriate, especially in a safe version of `fset'. |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2148 |
|
26206
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
2149 ;; For now define `ad-activate-internal' to the dummy definition: |
|
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
2150 (defun ad-activate-internal (function &optional compile) |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2151 "Automatic advice activation is disabled. `ad-start-advice' enables it." |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2152 nil) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2153 |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2154 ;; This is just a copy of the above: |
|
26206
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
2155 (defun ad-activate-internal-off (function &optional compile) |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2156 "Automatic advice activation is disabled. `ad-start-advice' enables it." |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2157 nil) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2158 |
|
26206
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
2159 ;; This will be t for top-level calls to `ad-activate-internal-on': |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2160 (defvar ad-activate-on-top-level t) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2161 |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2162 (defmacro ad-with-auto-activation-disabled (&rest body) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2163 (` (let ((ad-activate-on-top-level nil)) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2164 (,@ body)))) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2165 |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2166 (defun ad-safe-fset (symbol definition) |
| 26217 | 2167 "A safe `fset' which will never call `ad-activate-internal' recursively." |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2168 (ad-with-auto-activation-disabled |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2169 (ad-real-fset symbol definition))) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2170 |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2171 |
| 4110 | 2172 ;; @@ Access functions for original definitions: |
| 2173 ;; ============================================ | |
| 2174 ;; The advice-info of an advised function contains its `origname' which is | |
| 2175 ;; a symbol that is fbound to the original definition available at the first | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2176 ;; proper activation of the function after a legal re/definition. If the |
| 4110 | 2177 ;; original was defined via fcell indirection then `origname' will be defined |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2178 ;; just so. Hence, to get hold of the actual original definition of a function |
| 4110 | 2179 ;; we need to use `ad-real-orig-definition'. |
| 2180 | |
| 2181 (defun ad-make-origname (function) | |
| 26217 | 2182 "Make name to be used to call the original FUNCTION." |
| 4110 | 2183 (intern (format "ad-Orig-%s" function))) |
| 2184 | |
| 2185 (defmacro ad-get-orig-definition (function) | |
| 2186 (` (let ((origname (ad-get-advice-info-field (, function) 'origname))) | |
| 2187 (if (fboundp origname) | |
| 2188 (symbol-function origname))))) | |
| 2189 | |
| 2190 (defmacro ad-set-orig-definition (function definition) | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2191 (` (ad-safe-fset |
| 4110 | 2192 (ad-get-advice-info-field function 'origname) (, definition)))) |
| 2193 | |
| 2194 (defmacro ad-clear-orig-definition (function) | |
| 2195 (` (fmakunbound (ad-get-advice-info-field (, function) 'origname)))) | |
| 2196 | |
| 2197 | |
| 2198 ;; @@ Interactive input functions: | |
| 2199 ;; =============================== | |
| 2200 | |
| 2201 (defun ad-read-advised-function (&optional prompt predicate default) | |
| 26217 | 2202 "Read name of advised function with completion from the minibuffer. |
| 2203 An optional PROMPT will be used to prompt for the function. PREDICATE | |
| 2204 plays the same role as for `try-completion' (which see). DEFAULT will | |
| 2205 be returned on empty input (defaults to the first advised function for | |
| 2206 which PREDICATE returns non-nil)." | |
| 4110 | 2207 (if (null ad-advised-functions) |
| 2208 (error "ad-read-advised-function: There are no advised functions")) | |
| 2209 (setq default | |
| 2210 (or default | |
| 2211 (ad-do-advised-functions (function) | |
| 2212 (if (or (null predicate) | |
| 2213 (funcall predicate function)) | |
| 2214 (ad-do-return function))) | |
| 2215 (error "ad-read-advised-function: %s" | |
| 2216 "There are no qualifying advised functions"))) | |
| 2217 (let* ((ad-pReDiCaTe predicate) | |
| 2218 (function | |
| 2219 (completing-read | |
| 2220 (format "%s(default %s) " (or prompt "Function: ") default) | |
| 2221 ad-advised-functions | |
| 2222 (if predicate | |
| 2223 (function | |
| 2224 (lambda (function) | |
| 2225 ;; Oops, no closures - the joys of dynamic scoping: | |
| 2226 ;; `predicate' clashed with the `predicate' argument | |
| 2227 ;; of Lemacs' `completing-read'..... | |
| 2228 (funcall ad-pReDiCaTe (intern (car function)))))) | |
| 2229 t))) | |
| 2230 (if (equal function "") | |
| 2231 (if (ad-is-advised default) | |
| 2232 default | |
| 2233 (error "ad-read-advised-function: `%s' is not advised" default)) | |
| 2234 (intern function)))) | |
| 2235 | |
| 2236 (defvar ad-advice-class-completion-table | |
|
29579
05016ef95d0f
(ad-advice-class-completion-table)
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
26627
diff
changeset
|
2237 (mapcar (lambda (class) (list (symbol-name class))) |
| 4110 | 2238 ad-advice-classes)) |
| 2239 | |
| 2240 (defun ad-read-advice-class (function &optional prompt default) | |
| 26217 | 2241 "Read a legal advice class with completion from the minibuffer. |
| 2242 An optional PROMPT will be used to prompt for the class. DEFAULT will | |
| 2243 be returned on empty input (defaults to the first non-empty advice | |
| 2244 class of FUNCTION)." | |
| 4110 | 2245 (setq default |
| 2246 (or default | |
| 2247 (ad-dolist (class ad-advice-classes) | |
| 2248 (if (ad-get-advice-info-field function class) | |
| 2249 (ad-do-return class))) | |
| 2250 (error "ad-read-advice-class: `%s' has no advices" function))) | |
| 2251 (let ((class (completing-read | |
| 2252 (format "%s(default %s) " (or prompt "Class: ") default) | |
| 2253 ad-advice-class-completion-table nil t))) | |
| 2254 (if (equal class "") | |
| 2255 default | |
| 2256 (intern class)))) | |
| 2257 | |
| 2258 (defun ad-read-advice-name (function class &optional prompt) | |
| 26217 | 2259 "Read name of existing advice of CLASS for FUNCTION with completion. |
| 2260 An optional PROMPT is used to prompt for the name." | |
| 4110 | 2261 (let* ((name-completion-table |
| 2262 (mapcar (function (lambda (advice) | |
| 2263 (list (symbol-name (ad-advice-name advice))))) | |
| 2264 (ad-get-advice-info-field function class))) | |
| 2265 (default | |
| 2266 (if (null name-completion-table) | |
| 2267 (error "ad-read-advice-name: `%s' has no %s advice" | |
| 2268 function class) | |
| 2269 (car (car name-completion-table)))) | |
| 2270 (prompt (format "%s(default %s) " (or prompt "Name: ") default)) | |
| 2271 (name (completing-read prompt name-completion-table nil t))) | |
| 2272 (if (equal name "") | |
| 2273 (intern default) | |
| 2274 (intern name)))) | |
| 2275 | |
| 2276 (defun ad-read-advice-specification (&optional prompt) | |
| 26217 | 2277 "Read a complete function/class/name specification from minibuffer. |
| 2278 The list of read symbols will be returned. The optional PROMPT will | |
| 2279 be used to prompt for the function." | |
| 4110 | 2280 (let* ((function (ad-read-advised-function prompt)) |
| 2281 (class (ad-read-advice-class function)) | |
| 2282 (name (ad-read-advice-name function class))) | |
| 2283 (list function class name))) | |
| 2284 | |
| 2285 ;; Use previous regexp as a default: | |
| 2286 (defvar ad-last-regexp "") | |
| 2287 | |
| 2288 (defun ad-read-regexp (&optional prompt) | |
| 26217 | 2289 "Read a regular expression from the minibuffer." |
| 4110 | 2290 (let ((regexp (read-from-minibuffer |
| 2291 (concat (or prompt "Regular expression: ") | |
| 2292 (if (equal ad-last-regexp "") "" | |
| 2293 (format "(default \"%s\") " ad-last-regexp)))))) | |
| 2294 (setq ad-last-regexp | |
| 2295 (if (equal regexp "") ad-last-regexp regexp)))) | |
| 2296 | |
| 2297 | |
| 2298 ;; @@ Finding, enabling, adding and removing pieces of advice: | |
| 2299 ;; =========================================================== | |
| 2300 | |
| 2301 (defmacro ad-find-advice (function class name) | |
| 26217 | 2302 "Find the first advice of FUNCTION in CLASS with NAME." |
| 4110 | 2303 (` (assq (, name) (ad-get-advice-info-field (, function) (, class))))) |
| 2304 | |
| 2305 (defun ad-advice-position (function class name) | |
| 26217 | 2306 "Return position of first advice of FUNCTION in CLASS with NAME." |
| 4110 | 2307 (let* ((found-advice (ad-find-advice function class name)) |
| 2308 (advices (ad-get-advice-info-field function class))) | |
| 2309 (if found-advice | |
| 2310 (- (length advices) (length (memq found-advice advices)))))) | |
| 2311 | |
| 2312 (defun ad-find-some-advice (function class name) | |
| 26217 | 2313 "Find the first of FUNCTION's advices in CLASS matching NAME. |
| 4110 | 2314 NAME can be a symbol or a regular expression matching part of an advice name. |
| 2315 If CLASS is `any' all legal advice classes will be checked." | |
| 2316 (if (ad-is-advised function) | |
| 2317 (let (found-advice) | |
| 2318 (ad-dolist (advice-class ad-advice-classes) | |
| 2319 (if (or (eq class 'any) (eq advice-class class)) | |
| 2320 (setq found-advice | |
| 2321 (ad-dolist (advice (ad-get-advice-info-field | |
| 2322 function advice-class)) | |
| 2323 (if (or (and (stringp name) | |
| 2324 (string-match | |
| 2325 name (symbol-name | |
| 2326 (ad-advice-name advice)))) | |
| 2327 (eq name (ad-advice-name advice))) | |
| 2328 (ad-do-return advice))))) | |
| 2329 (if found-advice (ad-do-return found-advice)))))) | |
| 2330 | |
| 2331 (defun ad-enable-advice-internal (function class name flag) | |
| 26217 | 2332 "Set enable FLAG of FUNCTION's advices in CLASS matching NAME. |
| 2333 If NAME is a string rather than a symbol then it's interpreted as a regular | |
| 2334 expression and all advices whose name contain a match for it will be | |
| 2335 affected. If CLASS is `any' advices in all legal advice classes will be | |
| 2336 considered. The number of changed advices will be returned (or nil if | |
| 2337 FUNCTION was not advised)." | |
| 4110 | 2338 (if (ad-is-advised function) |
| 2339 (let ((matched-advices 0)) | |
| 2340 (ad-dolist (advice-class ad-advice-classes) | |
| 2341 (if (or (eq class 'any) (eq advice-class class)) | |
| 2342 (ad-dolist (advice (ad-get-advice-info-field | |
| 2343 function advice-class)) | |
| 2344 (cond ((or (and (stringp name) | |
| 2345 (string-match | |
| 2346 name (symbol-name (ad-advice-name advice)))) | |
| 2347 (eq name (ad-advice-name advice))) | |
| 2348 (setq matched-advices (1+ matched-advices)) | |
| 2349 (ad-advice-set-enabled advice flag)))))) | |
| 2350 matched-advices))) | |
| 2351 | |
| 2352 (defun ad-enable-advice (function class name) | |
| 2353 "Enables the advice of FUNCTION with CLASS and NAME." | |
| 2354 (interactive (ad-read-advice-specification "Enable advice of: ")) | |
| 2355 (if (ad-is-advised function) | |
| 2356 (if (eq (ad-enable-advice-internal function class name t) 0) | |
| 2357 (error "ad-enable-advice: `%s' has no %s advice matching `%s'" | |
| 2358 function class name)) | |
| 2359 (error "ad-enable-advice: `%s' is not advised" function))) | |
| 2360 | |
| 2361 (defun ad-disable-advice (function class name) | |
| 26217 | 2362 "Disable the advice of FUNCTION with CLASS and NAME." |
| 4110 | 2363 (interactive (ad-read-advice-specification "Disable advice of: ")) |
| 2364 (if (ad-is-advised function) | |
| 2365 (if (eq (ad-enable-advice-internal function class name nil) 0) | |
| 2366 (error "ad-disable-advice: `%s' has no %s advice matching `%s'" | |
| 2367 function class name)) | |
| 2368 (error "ad-disable-advice: `%s' is not advised" function))) | |
| 2369 | |
| 2370 (defun ad-enable-regexp-internal (regexp class flag) | |
| 26217 | 2371 "Set enable FLAGs of all CLASS advices whose name contains a REGEXP match. |
| 2372 If CLASS is `any' all legal advice classes are considered. The number of | |
| 2373 affected advices will be returned." | |
| 4110 | 2374 (let ((matched-advices 0)) |
| 2375 (ad-do-advised-functions (advised-function) | |
| 2376 (setq matched-advices | |
| 2377 (+ matched-advices | |
| 2378 (or (ad-enable-advice-internal | |
| 2379 advised-function class regexp flag) | |
| 2380 0)))) | |
| 2381 matched-advices)) | |
| 2382 | |
| 2383 (defun ad-enable-regexp (regexp) | |
| 2384 "Enables all advices with names that contain a match for REGEXP. | |
| 2385 All currently advised functions will be considered." | |
| 2386 (interactive | |
| 2387 (list (ad-read-regexp "Enable advices via regexp: "))) | |
| 2388 (let ((matched-advices (ad-enable-regexp-internal regexp 'any t))) | |
| 2389 (if (interactive-p) | |
| 2390 (message "%d matching advices enabled" matched-advices)) | |
| 2391 matched-advices)) | |
| 2392 | |
| 2393 (defun ad-disable-regexp (regexp) | |
| 26217 | 2394 "Disable all advices with names that contain a match for REGEXP. |
| 4110 | 2395 All currently advised functions will be considered." |
| 2396 (interactive | |
| 2397 (list (ad-read-regexp "Disable advices via regexp: "))) | |
| 2398 (let ((matched-advices (ad-enable-regexp-internal regexp 'any nil))) | |
| 2399 (if (interactive-p) | |
| 2400 (message "%d matching advices disabled" matched-advices)) | |
| 2401 matched-advices)) | |
| 2402 | |
| 2403 (defun ad-remove-advice (function class name) | |
| 26217 | 2404 "Remove FUNCTION's advice with NAME from its advices in CLASS. |
| 4110 | 2405 If such an advice was found it will be removed from the list of advices |
| 2406 in that CLASS." | |
| 2407 (interactive (ad-read-advice-specification "Remove advice of: ")) | |
| 2408 (if (ad-is-advised function) | |
| 2409 (let* ((advice-to-remove (ad-find-advice function class name))) | |
| 2410 (if advice-to-remove | |
| 2411 (ad-set-advice-info-field | |
| 2412 function class | |
| 2413 (delq advice-to-remove (ad-get-advice-info-field function class))) | |
| 2414 (error "ad-remove-advice: `%s' has no %s advice `%s'" | |
| 2415 function class name))) | |
| 2416 (error "ad-remove-advice: `%s' is not advised" function))) | |
| 2417 | |
| 2418 ;;;###autoload | |
| 2419 (defun ad-add-advice (function advice class position) | |
| 26217 | 2420 "Add a piece of ADVICE to FUNCTION's list of advices in CLASS. |
| 4110 | 2421 If FUNCTION already has one or more pieces of advice of the specified |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2422 CLASS then POSITION determines where the new piece will go. The value |
| 4110 | 2423 of POSITION can either be `first', `last' or a number where 0 corresponds |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2424 to `first'. Numbers outside the range will be mapped to the closest |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2425 extreme position. If there was already a piece of ADVICE with the same |
| 4110 | 2426 name, then the position argument will be ignored and the old advice |
| 2427 will be overwritten with the new one. | |
| 26217 | 2428 If the FUNCTION was not advised already, then its advice info will be |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2429 initialized. Redefining a piece of advice whose name is part of the cache-id |
| 4110 | 2430 will clear the cache." |
| 2431 (cond ((not (ad-is-advised function)) | |
| 2432 (ad-initialize-advice-info function) | |
| 2433 (ad-set-advice-info-field | |
| 2434 function 'origname (ad-make-origname function)))) | |
| 2435 (let* ((previous-position | |
| 2436 (ad-advice-position function class (ad-advice-name advice))) | |
| 2437 (advices (ad-get-advice-info-field function class)) | |
| 2438 ;; Determine a numerical position for the new advice: | |
| 2439 (position (cond (previous-position) | |
| 2440 ((eq position 'first) 0) | |
| 2441 ((eq position 'last) (length advices)) | |
| 2442 ((numberp position) | |
| 2443 (max 0 (min position (length advices)))) | |
| 2444 (t 0)))) | |
| 2445 ;; Check whether we have to clear the cache: | |
| 2446 (if (memq (ad-advice-name advice) (ad-get-cache-class-id function class)) | |
| 2447 (ad-clear-cache function)) | |
| 2448 (if previous-position | |
| 2449 (setcar (nthcdr position advices) advice) | |
| 2450 (if (= position 0) | |
| 2451 (ad-set-advice-info-field function class (cons advice advices)) | |
| 2452 (setcdr (nthcdr (1- position) advices) | |
| 2453 (cons advice (nthcdr position advices))))))) | |
| 2454 | |
| 2455 | |
| 2456 ;; @@ Accessing and manipulating function definitions: | |
| 2457 ;; =================================================== | |
| 2458 | |
| 2459 (defmacro ad-macrofy (definition) | |
| 26217 | 2460 "Take a lambda function DEFINITION and make a macro out of it." |
| 4110 | 2461 (` (cons 'macro (, definition)))) |
| 2462 | |
| 2463 (defmacro ad-lambdafy (definition) | |
| 26217 | 2464 "Take a macro function DEFINITION and make a lambda out of it." |
| 4110 | 2465 (` (cdr (, definition)))) |
| 2466 | |
| 2467 ;; There is no way to determine whether some subr is a special form or not, | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2468 ;; hence we need this list (which is probably out of date): |
| 4110 | 2469 (defvar ad-special-forms |
|
25260
0c8c07d1d12f
(ad-special-forms): Use track-mouse iff bound.
Karl Heuer <kwzh@gnu.org>
parents:
25208
diff
changeset
|
2470 (let ((tem '(and catch cond condition-case defconst defmacro |
|
0c8c07d1d12f
(ad-special-forms): Use track-mouse iff bound.
Karl Heuer <kwzh@gnu.org>
parents:
25208
diff
changeset
|
2471 defun defvar function if interactive let let* |
|
0c8c07d1d12f
(ad-special-forms): Use track-mouse iff bound.
Karl Heuer <kwzh@gnu.org>
parents:
25208
diff
changeset
|
2472 or prog1 prog2 progn quote save-current-buffer |
|
0c8c07d1d12f
(ad-special-forms): Use track-mouse iff bound.
Karl Heuer <kwzh@gnu.org>
parents:
25208
diff
changeset
|
2473 save-excursion save-restriction save-window-excursion |
|
33665
b51b000b2c50
(ad-special-forms): Correct the conditional inclusion of `track-mouse'.
Miles Bader <miles@gnu.org>
parents:
29579
diff
changeset
|
2474 setq setq-default unwind-protect while |
|
25260
0c8c07d1d12f
(ad-special-forms): Use track-mouse iff bound.
Karl Heuer <kwzh@gnu.org>
parents:
25208
diff
changeset
|
2475 with-output-to-temp-buffer))) |
|
0c8c07d1d12f
(ad-special-forms): Use track-mouse iff bound.
Karl Heuer <kwzh@gnu.org>
parents:
25208
diff
changeset
|
2476 ;; track-mouse could be void in some configurations. |
|
0c8c07d1d12f
(ad-special-forms): Use track-mouse iff bound.
Karl Heuer <kwzh@gnu.org>
parents:
25208
diff
changeset
|
2477 (if (fboundp 'track-mouse) |
|
0c8c07d1d12f
(ad-special-forms): Use track-mouse iff bound.
Karl Heuer <kwzh@gnu.org>
parents:
25208
diff
changeset
|
2478 (setq tem (cons 'track-mouse tem))) |
|
0c8c07d1d12f
(ad-special-forms): Use track-mouse iff bound.
Karl Heuer <kwzh@gnu.org>
parents:
25208
diff
changeset
|
2479 (mapcar 'symbol-function tem))) |
| 4110 | 2480 |
| 2481 (defmacro ad-special-form-p (definition) | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2482 ;;"non-nil if DEFINITION is a special form." |
| 4110 | 2483 (list 'memq definition 'ad-special-forms)) |
| 2484 | |
| 2485 (defmacro ad-interactive-p (definition) | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2486 ;;"non-nil if DEFINITION can be called interactively." |
| 4110 | 2487 (list 'commandp definition)) |
| 2488 | |
| 2489 (defmacro ad-subr-p (definition) | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2490 ;;"non-nil if DEFINITION is a subr." |
| 4110 | 2491 (list 'subrp definition)) |
| 2492 | |
| 2493 (defmacro ad-macro-p (definition) | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2494 ;;"non-nil if DEFINITION is a macro." |
| 4110 | 2495 (` (eq (car-safe (, definition)) 'macro))) |
| 2496 | |
| 2497 (defmacro ad-lambda-p (definition) | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2498 ;;"non-nil if DEFINITION is a lambda expression." |
| 4110 | 2499 (` (eq (car-safe (, definition)) 'lambda))) |
| 2500 | |
| 2501 ;; see ad-make-advice for the format of advice definitions: | |
| 2502 (defmacro ad-advice-p (definition) | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2503 ;;"non-nil if DEFINITION is a piece of advice." |
| 4110 | 2504 (` (eq (car-safe (, definition)) 'advice))) |
| 2505 | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2506 ;; Emacs/Lemacs cross-compatibility |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2507 ;; (compiled-function-p is an obsolete function in Emacs): |
| 4110 | 2508 (if (and (not (fboundp 'byte-code-function-p)) |
| 2509 (fboundp 'compiled-function-p)) | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2510 (ad-safe-fset 'byte-code-function-p 'compiled-function-p)) |
| 4110 | 2511 |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2512 (defmacro ad-compiled-p (definition) |
| 26217 | 2513 "Return non-nil if DEFINITION is a compiled byte-code object." |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2514 (` (or (byte-code-function-p (, definition)) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2515 (and (ad-macro-p (, definition)) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2516 (byte-code-function-p (ad-lambdafy (, definition))))))) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2517 |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2518 (defmacro ad-compiled-code (compiled-definition) |
| 26217 | 2519 "Return the byte-code object of a COMPILED-DEFINITION." |
| 4110 | 2520 (` (if (ad-macro-p (, compiled-definition)) |
| 2521 (ad-lambdafy (, compiled-definition)) | |
| 2522 (, compiled-definition)))) | |
| 2523 | |
| 2524 (defun ad-lambda-expression (definition) | |
| 26217 | 2525 "Return the lambda expression of a function/macro/advice DEFINITION." |
| 4110 | 2526 (cond ((ad-lambda-p definition) |
| 2527 definition) | |
| 2528 ((ad-macro-p definition) | |
| 2529 (ad-lambdafy definition)) | |
| 2530 ((ad-advice-p definition) | |
| 2531 (cdr definition)) | |
| 2532 (t nil))) | |
| 2533 | |
| 2534 (defun ad-arglist (definition &optional name) | |
| 26217 | 2535 "Return the argument list of DEFINITION. |
| 2536 If DEFINITION could be from a subr then its NAME should be | |
| 2537 supplied to make subr arglist lookup more efficient." | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2538 (cond ((ad-compiled-p definition) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2539 (aref (ad-compiled-code definition) 0)) |
| 4110 | 2540 ((consp definition) |
| 2541 (car (cdr (ad-lambda-expression definition)))) | |
| 2542 ((ad-subr-p definition) | |
| 2543 (if name | |
| 2544 (ad-subr-arglist name) | |
| 2545 ;; otherwise get it from its printed representation: | |
| 2546 (setq name (format "%s" definition)) | |
| 2547 (string-match "^#<subr \\([^>]+\\)>$" name) | |
| 2548 (ad-subr-arglist | |
| 2549 (intern (substring name (match-beginning 1) (match-end 1)))))))) | |
| 2550 | |
| 2551 ;; Store subr-args as `((arg1 arg2 ...))' so I can distinguish | |
| 2552 ;; a defined empty arglist `(nil)' from an undefined arglist: | |
| 2553 (defmacro ad-define-subr-args (subr arglist) | |
| 2554 (` (put (, subr) 'ad-subr-arglist (list (, arglist))))) | |
| 2555 (defmacro ad-undefine-subr-args (subr) | |
| 2556 (` (put (, subr) 'ad-subr-arglist nil))) | |
| 2557 (defmacro ad-subr-args-defined-p (subr) | |
| 2558 (` (get (, subr) 'ad-subr-arglist))) | |
| 2559 (defmacro ad-get-subr-args (subr) | |
| 2560 (` (car (get (, subr) 'ad-subr-arglist)))) | |
| 2561 | |
| 2562 (defun ad-subr-arglist (subr-name) | |
| 26217 | 2563 "Retrieve arglist of the subr with SUBR-NAME. |
| 2564 Either use the one stored under the `ad-subr-arglist' property, | |
| 2565 or try to retrieve it from the docstring and cache it under | |
| 2566 that property, or otherwise use `(&rest ad-subr-args)'." | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2567 (cond ((ad-subr-args-defined-p subr-name) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2568 (ad-get-subr-args subr-name)) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2569 ;; says jwz: Should use this for Lemacs 19.8 and above: |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2570 ;;((fboundp 'subr-min-args) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2571 ;; ...) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2572 ;; says hans: I guess what Jamie means is that I should use the values |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2573 ;; of `subr-min-args' and `subr-max-args' to construct the subr arglist |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2574 ;; without having to look it up via parsing the docstring, e.g., |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2575 ;; values 1 and 2 would suggest `(arg1 &optional arg2)' as an |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2576 ;; argument list. However, that won't work because there is no |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2577 ;; way to distinguish a subr with args `(a &optional b &rest c)' from |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2578 ;; one with args `(a &rest c)' using that mechanism. Also, the argument |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2579 ;; names from the docstring are more meaningful. Hence, I'll stick with |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2580 ;; the old way of doing things. |
|
8458
a95ca44cec95
(ad-subr-arglist): Adapted to new DOC file format.
Richard M. Stallman <rms@gnu.org>
parents:
8445
diff
changeset
|
2581 (t (let ((doc (or (ad-real-documentation subr-name t) ""))) |
|
a95ca44cec95
(ad-subr-arglist): Adapted to new DOC file format.
Richard M. Stallman <rms@gnu.org>
parents:
8445
diff
changeset
|
2582 (cond ((string-match "^\\(([^\)]+)\\)\n?\\'" doc) |
|
a95ca44cec95
(ad-subr-arglist): Adapted to new DOC file format.
Richard M. Stallman <rms@gnu.org>
parents:
8445
diff
changeset
|
2583 (ad-define-subr-args |
|
a95ca44cec95
(ad-subr-arglist): Adapted to new DOC file format.
Richard M. Stallman <rms@gnu.org>
parents:
8445
diff
changeset
|
2584 subr-name |
|
a95ca44cec95
(ad-subr-arglist): Adapted to new DOC file format.
Richard M. Stallman <rms@gnu.org>
parents:
8445
diff
changeset
|
2585 (cdr (car (read-from-string |
|
a95ca44cec95
(ad-subr-arglist): Adapted to new DOC file format.
Richard M. Stallman <rms@gnu.org>
parents:
8445
diff
changeset
|
2586 (downcase |
|
a95ca44cec95
(ad-subr-arglist): Adapted to new DOC file format.
Richard M. Stallman <rms@gnu.org>
parents:
8445
diff
changeset
|
2587 (substring doc |
|
a95ca44cec95
(ad-subr-arglist): Adapted to new DOC file format.
Richard M. Stallman <rms@gnu.org>
parents:
8445
diff
changeset
|
2588 (match-beginning 1) |
|
a95ca44cec95
(ad-subr-arglist): Adapted to new DOC file format.
Richard M. Stallman <rms@gnu.org>
parents:
8445
diff
changeset
|
2589 (match-end 1))))))) |
|
a95ca44cec95
(ad-subr-arglist): Adapted to new DOC file format.
Richard M. Stallman <rms@gnu.org>
parents:
8445
diff
changeset
|
2590 (ad-get-subr-args subr-name)) |
|
a95ca44cec95
(ad-subr-arglist): Adapted to new DOC file format.
Richard M. Stallman <rms@gnu.org>
parents:
8445
diff
changeset
|
2591 ;; this is the old format used before Emacs 19.24: |
|
a95ca44cec95
(ad-subr-arglist): Adapted to new DOC file format.
Richard M. Stallman <rms@gnu.org>
parents:
8445
diff
changeset
|
2592 ((string-match |
|
a95ca44cec95
(ad-subr-arglist): Adapted to new DOC file format.
Richard M. Stallman <rms@gnu.org>
parents:
8445
diff
changeset
|
2593 "[\n\t ]*\narguments: ?\\((.*)\\)\n?\\'" doc) |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2594 (ad-define-subr-args |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2595 subr-name |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2596 (car (read-from-string |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2597 doc (match-beginning 1) (match-end 1)))) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2598 (ad-get-subr-args subr-name)) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2599 (t '(&rest ad-subr-args))))))) |
| 4110 | 2600 |
| 2601 (defun ad-docstring (definition) | |
| 26217 | 2602 "Return the unexpanded docstring of DEFINITION." |
| 4110 | 2603 (let ((docstring |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2604 (if (ad-compiled-p definition) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2605 (ad-real-documentation definition t) |
| 4110 | 2606 (car (cdr (cdr (ad-lambda-expression definition))))))) |
| 2607 (if (or (stringp docstring) | |
| 2608 (natnump docstring)) | |
| 2609 docstring))) | |
| 2610 | |
| 2611 (defun ad-interactive-form (definition) | |
| 26217 | 2612 "Return the interactive form of DEFINITION." |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2613 (cond ((ad-compiled-p definition) |
| 4110 | 2614 (and (commandp definition) |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2615 (list 'interactive (aref (ad-compiled-code definition) 5)))) |
| 4110 | 2616 ((or (ad-advice-p definition) |
| 2617 (ad-lambda-p definition)) | |
| 2618 (commandp (ad-lambda-expression definition))))) | |
| 2619 | |
| 2620 (defun ad-body-forms (definition) | |
| 26217 | 2621 "Return the list of body forms of DEFINITION." |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2622 (cond ((ad-compiled-p definition) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2623 nil) |
| 4110 | 2624 ((consp definition) |
| 2625 (nthcdr (+ (if (ad-docstring definition) 1 0) | |
| 2626 (if (ad-interactive-form definition) 1 0)) | |
| 2627 (cdr (cdr (ad-lambda-expression definition))))))) | |
| 2628 | |
| 2629 ;; Matches the docstring of an advised definition. | |
| 2630 ;; The first group of the regexp matches the function name: | |
| 2631 (defvar ad-advised-definition-docstring-regexp "^\\$ad-doc: \\(.+\\)\\$$") | |
| 2632 | |
| 2633 (defun ad-make-advised-definition-docstring (function) | |
| 26217 | 2634 "Make an identifying docstring for the advised definition of FUNCTION. |
| 2635 Put function name into the documentation string so we can infer | |
| 2636 the name of the advised function from the docstring. This is needed | |
| 2637 to generate a proper advised docstring even if we are just given a | |
| 2638 definition (also see the defadvice for `documentation')." | |
| 4110 | 2639 (format "$ad-doc: %s$" (prin1-to-string function))) |
| 2640 | |
| 2641 (defun ad-advised-definition-p (definition) | |
| 26217 | 2642 "Return non-nil if DEFINITION was generated from advice information." |
| 4110 | 2643 (if (or (ad-lambda-p definition) |
| 2644 (ad-macro-p definition) | |
| 2645 (ad-compiled-p definition)) | |
| 2646 (let ((docstring (ad-docstring definition))) | |
| 2647 (and (stringp docstring) | |
| 2648 (string-match | |
| 2649 ad-advised-definition-docstring-regexp docstring))))) | |
| 2650 | |
| 2651 (defun ad-definition-type (definition) | |
| 26217 | 2652 "Return symbol that describes the type of DEFINITION." |
| 4110 | 2653 (if (ad-macro-p definition) |
| 2654 'macro | |
| 2655 (if (ad-subr-p definition) | |
| 2656 (if (ad-special-form-p definition) | |
| 2657 'special-form | |
| 2658 'subr) | |
| 2659 (if (or (ad-lambda-p definition) | |
| 2660 (ad-compiled-p definition)) | |
| 2661 'function | |
| 2662 (if (ad-advice-p definition) | |
| 2663 'advice))))) | |
| 2664 | |
| 2665 (defun ad-has-proper-definition (function) | |
| 26217 | 2666 "True if FUNCTION is a symbol with a proper definition. |
| 2667 For that it has to be fbound with a non-autoload definition." | |
| 4110 | 2668 (and (symbolp function) |
| 2669 (fboundp function) | |
| 2670 (not (eq (car-safe (symbol-function function)) 'autoload)))) | |
| 2671 | |
| 2672 ;; The following two are necessary for the sake of packages such as | |
| 2673 ;; ange-ftp which redefine functions via fcell indirection: | |
| 2674 (defun ad-real-definition (function) | |
| 26217 | 2675 "Find FUNCTION's definition at the end of function cell indirection." |
| 4110 | 2676 (if (ad-has-proper-definition function) |
| 2677 (let ((definition (symbol-function function))) | |
| 2678 (if (symbolp definition) | |
| 2679 (ad-real-definition definition) | |
| 2680 definition)))) | |
| 2681 | |
| 2682 (defun ad-real-orig-definition (function) | |
| 26217 | 2683 "Find FUNCTION's real original definition starting from its `origname'." |
| 4110 | 2684 (if (ad-is-advised function) |
| 2685 (ad-real-definition (ad-get-advice-info-field function 'origname)))) | |
| 2686 | |
| 2687 (defun ad-is-compilable (function) | |
| 26217 | 2688 "True if FUNCTION has an interpreted definition that can be compiled." |
| 4110 | 2689 (and (ad-has-proper-definition function) |
| 2690 (or (ad-lambda-p (symbol-function function)) | |
| 2691 (ad-macro-p (symbol-function function))) | |
| 2692 (not (ad-compiled-p (symbol-function function))))) | |
| 2693 | |
| 2694 (defun ad-compile-function (function) | |
| 2695 "Byte-compiles FUNCTION (or macro) if it is not yet compiled." | |
| 2696 (interactive "aByte-compile function: ") | |
| 2697 (if (ad-is-compilable function) | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2698 ;; Need to turn off auto-activation |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2699 ;; because `byte-compile' uses `fset': |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2700 (ad-with-auto-activation-disabled |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
2701 (byte-compile function)))) |
| 4110 | 2702 |
| 2703 | |
| 2704 ;; @@ Constructing advised definitions: | |
| 2705 ;; ==================================== | |
| 2706 ;; | |
| 2707 ;; Main design decisions about the form of advised definitions: | |
| 2708 ;; | |
| 2709 ;; A) How will original definitions be called? | |
| 2710 ;; B) What will argument lists of advised functions look like? | |
| 2711 ;; | |
| 2712 ;; Ad A) | |
| 2713 ;; I chose to use function indirection for all four types of original | |
| 2714 ;; definitions (functions, macros, subrs and special forms), i.e., create | |
| 2715 ;; a unique symbol `ad-Orig-<name>' which is fbound to the original | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2716 ;; definition and call it according to type and arguments. Functions and |
| 4110 | 2717 ;; subrs that don't have any &rest arguments can be called directly in a |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2718 ;; `(ad-Orig-<name> ....)' form. If they have a &rest argument we have to |
| 26217 | 2719 ;; use `apply'. Macros will be called with |
| 4110 | 2720 ;; `(macroexpand '(ad-Orig-<name> ....))', and special forms also need a |
| 2721 ;; form like that with `eval' instead of `macroexpand'. | |
| 2722 ;; | |
| 2723 ;; Ad B) | |
| 2724 ;; Use original arguments where possible and `(&rest ad-subr-args)' | |
| 2725 ;; otherwise, even though this seems to be more complicated and less | |
| 2726 ;; uniform than a general `(&rest args)' approach. My reason to still | |
| 2727 ;; do it that way is that in most cases my approach leads to the more | |
| 2728 ;; efficient form for the advised function, and portability (e.g., to | |
| 2729 ;; make the same advice work regardless of whether something is a | |
| 2730 ;; function or a subr) can still be achieved with argument access macros. | |
| 2731 | |
| 2732 | |
| 2733 (defun ad-prognify (forms) | |
| 2734 (cond ((<= (length forms) 1) | |
| 2735 (car forms)) | |
| 2736 (t (cons 'progn forms)))) | |
| 2737 | |
| 2738 ;; @@@ Accessing argument lists: | |
| 2739 ;; ============================= | |
| 2740 | |
| 2741 (defun ad-parse-arglist (arglist) | |
| 26217 | 2742 "Parse ARGLIST into its required, optional and rest parameters. |
| 2743 A three-element list is returned, where the 1st element is the list of | |
| 2744 required arguments, the 2nd is the list of optional arguments, and the 3rd | |
| 2745 is the name of an optional rest parameter (or nil)." | |
| 4110 | 2746 (let* (required optional rest) |
| 2747 (setq rest (car (cdr (memq '&rest arglist)))) | |
| 2748 (if rest (setq arglist (reverse (cdr (memq '&rest (reverse arglist)))))) | |
| 2749 (setq optional (cdr (memq '&optional arglist))) | |
| 2750 (if optional | |
| 2751 (setq required (reverse (cdr (memq '&optional (reverse arglist))))) | |
| 2752 (setq required arglist)) | |
| 2753 (list required optional rest))) | |
| 2754 | |
| 2755 (defun ad-retrieve-args-form (arglist) | |
| 26217 | 2756 "Generate a form which evaluates into names/values/types of ARGLIST. |
| 2757 When the form gets evaluated within a function with that argument list | |
| 2758 it will result in a list with one entry for each argument, where the | |
| 2759 first element of each entry is the name of the argument, the second | |
| 2760 element is its actual current value, and the third element is either | |
| 2761 `required', `optional' or `rest' depending on the type of the argument." | |
| 4110 | 2762 (let* ((parsed-arglist (ad-parse-arglist arglist)) |
| 2763 (rest (nth 2 parsed-arglist))) | |
| 2764 (` (list | |
| 2765 (,@ (mapcar (function | |
| 2766 (lambda (req) | |
| 2767 (` (list '(, req) (, req) 'required)))) | |
| 2768 (nth 0 parsed-arglist))) | |
| 2769 (,@ (mapcar (function | |
| 2770 (lambda (opt) | |
| 2771 (` (list '(, opt) (, opt) 'optional)))) | |
| 2772 (nth 1 parsed-arglist))) | |
| 2773 (,@ (if rest (list (` (list '(, rest) (, rest) 'rest))))) | |
| 2774 )))) | |
| 2775 | |
| 2776 (defun ad-arg-binding-field (binding field) | |
| 2777 (cond ((eq field 'name) (car binding)) | |
| 2778 ((eq field 'value) (car (cdr binding))) | |
| 2779 ((eq field 'type) (car (cdr (cdr binding)))))) | |
| 2780 | |
| 2781 (defun ad-list-access (position list) | |
| 2782 (cond ((= position 0) list) | |
| 2783 ((= position 1) (list 'cdr list)) | |
| 2784 (t (list 'nthcdr position list)))) | |
| 2785 | |
| 2786 (defun ad-element-access (position list) | |
| 2787 (cond ((= position 0) (list 'car list)) | |
| 2788 ((= position 1) (` (car (cdr (, list))))) | |
| 2789 (t (list 'nth position list)))) | |
| 2790 | |
| 2791 (defun ad-access-argument (arglist index) | |
| 26217 | 2792 "Tell how to access ARGLIST's actual argument at position INDEX. |
| 2793 For a required/optional arg it simply returns it, if a rest argument has | |
| 2794 to be accessed, it returns a list with the index and name." | |
| 4110 | 2795 (let* ((parsed-arglist (ad-parse-arglist arglist)) |
| 2796 (reqopt-args (append (nth 0 parsed-arglist) | |
| 2797 (nth 1 parsed-arglist))) | |
| 2798 (rest-arg (nth 2 parsed-arglist))) | |
| 2799 (cond ((< index (length reqopt-args)) | |
| 2800 (nth index reqopt-args)) | |
| 2801 (rest-arg | |
| 2802 (list (- index (length reqopt-args)) rest-arg))))) | |
| 2803 | |
| 2804 (defun ad-get-argument (arglist index) | |
| 26217 | 2805 "Return form to access ARGLIST's actual argument at position INDEX." |
| 4110 | 2806 (let ((argument-access (ad-access-argument arglist index))) |
| 2807 (cond ((consp argument-access) | |
| 2808 (ad-element-access | |
| 2809 (car argument-access) (car (cdr argument-access)))) | |
| 2810 (argument-access)))) | |
| 2811 | |
| 2812 (defun ad-set-argument (arglist index value-form) | |
| 26217 | 2813 "Return form to set ARGLIST's actual arg at INDEX to VALUE-FORM." |
| 4110 | 2814 (let ((argument-access (ad-access-argument arglist index))) |
| 2815 (cond ((consp argument-access) | |
| 2816 ;; should this check whether there actually is something to set? | |
| 2817 (` (setcar (, (ad-list-access | |
| 2818 (car argument-access) (car (cdr argument-access)))) | |
| 2819 (, value-form)))) | |
| 2820 (argument-access | |
| 2821 (` (setq (, argument-access) (, value-form)))) | |
| 2822 (t (error "ad-set-argument: No argument at position %d of `%s'" | |
| 2823 index arglist))))) | |
| 2824 | |
| 2825 (defun ad-get-arguments (arglist index) | |
| 26217 | 2826 "Return form to access all actual arguments starting at position INDEX." |
| 4110 | 2827 (let* ((parsed-arglist (ad-parse-arglist arglist)) |
| 2828 (reqopt-args (append (nth 0 parsed-arglist) | |
| 2829 (nth 1 parsed-arglist))) | |
| 2830 (rest-arg (nth 2 parsed-arglist)) | |
| 2831 args-form) | |
| 2832 (if (< index (length reqopt-args)) | |
| 2833 (setq args-form (` (list (,@ (nthcdr index reqopt-args)))))) | |
| 2834 (if rest-arg | |
| 2835 (if args-form | |
| 2836 (setq args-form (` (nconc (, args-form) (, rest-arg)))) | |
| 2837 (setq args-form (ad-list-access (- index (length reqopt-args)) | |
| 2838 rest-arg)))) | |
| 2839 args-form)) | |
| 2840 | |
| 2841 (defun ad-set-arguments (arglist index values-form) | |
| 26217 | 2842 "Make form to assign elements of VALUES-FORM as actual ARGLIST args. |
| 2843 The assignment starts at position INDEX." | |
| 4110 | 2844 (let ((values-index 0) |
| 2845 argument-access set-forms) | |
| 2846 (while (setq argument-access (ad-access-argument arglist index)) | |
| 2847 (if (symbolp argument-access) | |
| 2848 (setq set-forms | |
| 2849 (cons (ad-set-argument | |
| 2850 arglist index | |
| 2851 (ad-element-access values-index 'ad-vAlUeS)) | |
| 2852 set-forms)) | |
| 2853 (setq set-forms | |
| 2854 (cons (if (= (car argument-access) 0) | |
| 2855 (list 'setq | |
| 2856 (car (cdr argument-access)) | |
| 2857 (ad-list-access values-index 'ad-vAlUeS)) | |
| 2858 (list 'setcdr | |
| 2859 (ad-list-access (1- (car argument-access)) | |
| 2860 (car (cdr argument-access))) | |
| 2861 (ad-list-access values-index 'ad-vAlUeS))) | |
| 2862 set-forms)) | |
| 2863 ;; terminate loop | |
| 2864 (setq arglist nil)) | |
| 2865 (setq index (1+ index)) | |
| 2866 (setq values-index (1+ values-index))) | |
| 2867 (if (null set-forms) | |
| 2868 (error "ad-set-arguments: No argument at position %d of `%s'" | |
| 2869 index arglist) | |
| 2870 (if (= (length set-forms) 1) | |
| 2871 ;; For exactly one set-form we can use values-form directly,... | |
| 2872 (ad-substitute-tree | |
| 2873 (function (lambda (form) (eq form 'ad-vAlUeS))) | |
| 2874 (function (lambda (form) values-form)) | |
| 2875 (car set-forms)) | |
| 2876 ;; ...if we have more we have to bind it to a variable: | |
| 2877 (` (let ((ad-vAlUeS (, values-form))) | |
| 2878 (,@ (reverse set-forms)) | |
| 2879 ;; work around the old backquote bug: | |
| 2880 (, 'ad-vAlUeS))))))) | |
| 2881 | |
| 2882 (defun ad-insert-argument-access-forms (definition arglist) | |
| 26217 | 2883 "Expands arg-access text macros in DEFINITION according to ARGLIST." |
| 4110 | 2884 (ad-substitute-tree |
| 2885 (function | |
| 2886 (lambda (form) | |
| 2887 (or (eq form 'ad-arg-bindings) | |
| 2888 (and (memq (car-safe form) | |
| 2889 '(ad-get-arg ad-get-args ad-set-arg ad-set-args)) | |
| 2890 (integerp (car-safe (cdr form))))))) | |
| 2891 (function | |
| 2892 (lambda (form) | |
| 2893 (if (eq form 'ad-arg-bindings) | |
| 2894 (ad-retrieve-args-form arglist) | |
| 2895 (let ((accessor (car form)) | |
| 2896 (index (car (cdr form))) | |
| 2897 (val (car (cdr (ad-insert-argument-access-forms | |
| 2898 (cdr form) arglist))))) | |
| 2899 (cond ((eq accessor 'ad-get-arg) | |
| 2900 (ad-get-argument arglist index)) | |
| 2901 ((eq accessor 'ad-set-arg) | |
| 2902 (ad-set-argument arglist index val)) | |
| 2903 ((eq accessor 'ad-get-args) | |
| 2904 (ad-get-arguments arglist index)) | |
| 2905 ((eq accessor 'ad-set-args) | |
| 2906 (ad-set-arguments arglist index val))))))) | |
| 2907 definition)) | |
| 2908 | |
| 2909 ;; @@@ Mapping argument lists: | |
| 2910 ;; =========================== | |
| 2911 ;; Here is the problem: | |
| 2912 ;; Suppose function foo was called with (foo 1 2 3 4 5), and foo has the | |
| 2913 ;; argument list (x y &rest z), and we want to call the function bar which | |
| 2914 ;; has argument list (a &rest b) with a combination of x, y and z so that | |
| 26217 | 2915 ;; the effect is just as if we had called (bar 1 2 3 4 5) directly. |
| 4110 | 2916 ;; The mapping should work for any two argument lists. |
| 2917 | |
| 2918 (defun ad-map-arglists (source-arglist target-arglist) | |
| 26217 | 2919 "Make `funcall/apply' form to map SOURCE-ARGLIST to TARGET-ARGLIST. |
| 4110 | 2920 The arguments supplied to TARGET-ARGLIST will be taken from SOURCE-ARGLIST just |
| 26217 | 2921 as if they had been supplied to a function with TARGET-ARGLIST directly. |
| 2922 Excess source arguments will be neglected, missing source arguments will be | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2923 supplied as nil. Returns a `funcall' or `apply' form with the second element |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2924 being `function' which has to be replaced by an actual function argument. |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2925 Example: `(ad-map-arglists '(a &rest args) '(w x y z))' will return |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2926 `(funcall function a (car args) (car (cdr args)) (nth 2 args))'." |
| 4110 | 2927 (let* ((parsed-source-arglist (ad-parse-arglist source-arglist)) |
| 2928 (source-reqopt-args (append (nth 0 parsed-source-arglist) | |
| 2929 (nth 1 parsed-source-arglist))) | |
| 2930 (source-rest-arg (nth 2 parsed-source-arglist)) | |
| 2931 (parsed-target-arglist (ad-parse-arglist target-arglist)) | |
| 2932 (target-reqopt-args (append (nth 0 parsed-target-arglist) | |
| 2933 (nth 1 parsed-target-arglist))) | |
| 2934 (target-rest-arg (nth 2 parsed-target-arglist)) | |
| 2935 (need-apply (and source-rest-arg target-rest-arg)) | |
| 2936 (target-arg-index -1)) | |
| 2937 ;; This produces ``error-proof'' target function calls with the exception | |
| 2938 ;; of a case like (&rest a) mapped onto (x &rest y) where the actual args | |
| 2939 ;; supplied to A might not be enough to supply the required target arg X | |
| 2940 (append (list (if need-apply 'apply 'funcall) 'function) | |
| 2941 (cond (need-apply | |
| 2942 ;; `apply' can take care of that directly: | |
| 2943 (append source-reqopt-args (list source-rest-arg))) | |
| 2944 (t (mapcar (function | |
| 2945 (lambda (arg) | |
| 2946 (setq target-arg-index (1+ target-arg-index)) | |
| 2947 (ad-get-argument | |
| 2948 source-arglist target-arg-index))) | |
| 2949 (append target-reqopt-args | |
| 2950 (and target-rest-arg | |
| 2951 ;; If we have a rest arg gobble up | |
| 2952 ;; remaining source args: | |
| 2953 (nthcdr (length target-reqopt-args) | |
| 2954 source-reqopt-args))))))))) | |
| 2955 | |
| 2956 (defun ad-make-mapped-call (source-arglist target-arglist target-function) | |
| 26217 | 2957 "Make form to call TARGET-FUNCTION with args from SOURCE-ARGLIST." |
| 4110 | 2958 (let* ((mapped-form (ad-map-arglists source-arglist target-arglist))) |
| 2959 (if (eq (car mapped-form) 'funcall) | |
| 2960 (cons target-function (cdr (cdr mapped-form))) | |
| 2961 (prog1 mapped-form | |
| 2962 (setcar (cdr mapped-form) (list 'quote target-function)))))) | |
| 2963 | |
| 2964 ;; @@@ Making an advised documentation string: | |
| 2965 ;; =========================================== | |
| 2966 ;; New policy: The documentation string for an advised function will be built | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2967 ;; at the time the advised `documentation' function is called. This has the |
| 4110 | 2968 ;; following advantages: |
| 2969 ;; 1) command-key substitutions will automatically be correct | |
| 2970 ;; 2) No wasted string space due to big advised docstrings in caches or | |
| 2971 ;; compiled files that contain preactivations | |
| 2972 ;; The overall overhead for this should be negligible because people normally | |
| 2973 ;; don't lookup documentation for the same function over and over again. | |
| 2974 | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2975 (defun ad-make-single-advice-docstring (advice class &optional style) |
| 4110 | 2976 (let ((advice-docstring (ad-docstring (ad-advice-definition advice)))) |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2977 (cond ((eq style 'plain) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2978 advice-docstring) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2979 ((eq style 'freeze) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2980 (format "Permanent %s-advice `%s':%s%s" |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2981 class (ad-advice-name advice) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2982 (if advice-docstring "\n" "") |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2983 (or advice-docstring ""))) |
|
25208
76f5f50e7742
(ad-make-single-advice-docstring): Treat case with no doctring specially.
Dave Love <fx@gnu.org>
parents:
24875
diff
changeset
|
2984 (t (if advice-docstring |
|
76f5f50e7742
(ad-make-single-advice-docstring): Treat case with no doctring specially.
Dave Love <fx@gnu.org>
parents:
24875
diff
changeset
|
2985 (format "%s-advice `%s':\n%s" |
|
76f5f50e7742
(ad-make-single-advice-docstring): Treat case with no doctring specially.
Dave Love <fx@gnu.org>
parents:
24875
diff
changeset
|
2986 (capitalize (symbol-name class)) |
|
76f5f50e7742
(ad-make-single-advice-docstring): Treat case with no doctring specially.
Dave Love <fx@gnu.org>
parents:
24875
diff
changeset
|
2987 (ad-advice-name advice) |
|
76f5f50e7742
(ad-make-single-advice-docstring): Treat case with no doctring specially.
Dave Love <fx@gnu.org>
parents:
24875
diff
changeset
|
2988 advice-docstring) |
|
76f5f50e7742
(ad-make-single-advice-docstring): Treat case with no doctring specially.
Dave Love <fx@gnu.org>
parents:
24875
diff
changeset
|
2989 (format "%s-advice `%s'." |
|
76f5f50e7742
(ad-make-single-advice-docstring): Treat case with no doctring specially.
Dave Love <fx@gnu.org>
parents:
24875
diff
changeset
|
2990 (capitalize (symbol-name class)) |
|
76f5f50e7742
(ad-make-single-advice-docstring): Treat case with no doctring specially.
Dave Love <fx@gnu.org>
parents:
24875
diff
changeset
|
2991 (ad-advice-name advice))))))) |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2992 |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2993 (defun ad-make-advised-docstring (function &optional style) |
| 4110 | 2994 ;;"Constructs a documentation string for the advised FUNCTION. |
| 2995 ;;It concatenates the original documentation with the documentation | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2996 ;;strings of the individual pieces of advice which will be formatted |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2997 ;;according to STYLE. STYLE can be `plain' or `freeze', everything else |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
2998 ;;will be interpreted as `default'. The order of the advice documentation |
| 4110 | 2999 ;;strings corresponds to before/around/after and the individual ordering |
| 3000 ;;in any of these classes." | |
| 3001 (let* ((origdef (ad-real-orig-definition function)) | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3002 (origtype (symbol-name (ad-definition-type origdef))) |
| 4110 | 3003 (origdoc |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3004 ;; Retrieve raw doc, key substitution will be taken care of later: |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3005 (ad-real-documentation origdef t)) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3006 paragraphs advice-docstring) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3007 (if origdoc (setq paragraphs (list origdoc))) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3008 (if (not (eq style 'plain)) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3009 (setq paragraphs (cons (concat "This " origtype " is advised.") |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3010 paragraphs))) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3011 (ad-dolist (class ad-advice-classes) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3012 (ad-dolist (advice (ad-get-enabled-advices function class)) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3013 (setq advice-docstring |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3014 (ad-make-single-advice-docstring advice class style)) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3015 (if advice-docstring |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3016 (setq paragraphs (cons advice-docstring paragraphs))))) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3017 (if paragraphs |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3018 ;; separate paragraphs with blank lines: |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3019 (mapconcat 'identity (nreverse paragraphs) "\n\n")))) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3020 |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3021 (defun ad-make-plain-docstring (function) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3022 (ad-make-advised-docstring function 'plain)) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3023 (defun ad-make-freeze-docstring (function) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3024 (ad-make-advised-docstring function 'freeze)) |
| 4110 | 3025 |
| 3026 ;; @@@ Accessing overriding arglists and interactive forms: | |
| 3027 ;; ======================================================== | |
| 3028 | |
| 3029 (defun ad-advised-arglist (function) | |
| 26217 | 3030 "Find first defined arglist in FUNCTION's redefining advices." |
| 4110 | 3031 (ad-dolist (advice (append (ad-get-enabled-advices function 'before) |
| 3032 (ad-get-enabled-advices function 'around) | |
| 3033 (ad-get-enabled-advices function 'after))) | |
| 3034 (let ((arglist (ad-arglist (ad-advice-definition advice)))) | |
| 3035 (if arglist | |
| 3036 ;; We found the first one, use it: | |
| 3037 (ad-do-return arglist))))) | |
| 3038 | |
| 3039 (defun ad-advised-interactive-form (function) | |
| 26217 | 3040 "Find first interactive form in FUNCTION's redefining advices." |
| 4110 | 3041 (ad-dolist (advice (append (ad-get-enabled-advices function 'before) |
| 3042 (ad-get-enabled-advices function 'around) | |
| 3043 (ad-get-enabled-advices function 'after))) | |
| 3044 (let ((interactive-form | |
| 3045 (ad-interactive-form (ad-advice-definition advice)))) | |
| 3046 (if interactive-form | |
| 3047 ;; We found the first one, use it: | |
| 3048 (ad-do-return interactive-form))))) | |
| 3049 | |
| 3050 ;; @@@ Putting it all together: | |
| 3051 ;; ============================ | |
| 3052 | |
| 3053 (defun ad-make-advised-definition (function) | |
| 26217 | 3054 "Generate an advised definition of FUNCTION from its advice info." |
| 4110 | 3055 (if (and (ad-is-advised function) |
| 3056 (ad-has-redefining-advice function)) | |
| 3057 (let* ((origdef (ad-real-orig-definition function)) | |
| 3058 (origname (ad-get-advice-info-field function 'origname)) | |
| 3059 (orig-interactive-p (ad-interactive-p origdef)) | |
| 3060 (orig-subr-p (ad-subr-p origdef)) | |
| 3061 (orig-special-form-p (ad-special-form-p origdef)) | |
| 3062 (orig-macro-p (ad-macro-p origdef)) | |
| 3063 ;; Construct the individual pieces that we need for assembly: | |
| 3064 (orig-arglist (ad-arglist origdef function)) | |
| 3065 (advised-arglist (or (ad-advised-arglist function) | |
| 3066 orig-arglist)) | |
| 3067 (advised-interactive-form (ad-advised-interactive-form function)) | |
| 3068 (interactive-form | |
| 3069 (cond (orig-macro-p nil) | |
| 3070 (advised-interactive-form) | |
| 3071 ((ad-interactive-form origdef)) | |
| 3072 ;; Otherwise we must have a subr: make it interactive if | |
| 3073 ;; we have to and initialize required arguments in case | |
| 3074 ;; it is called interactively: | |
|
37056
543952c0704a
(ad-make-advised-definition): Call
Gerd Moellmann <gerd@gnu.org>
parents:
33665
diff
changeset
|
3075 (orig-interactive-p (interactive-form origdef)))) |
| 4110 | 3076 (orig-form |
| 3077 (cond ((or orig-special-form-p orig-macro-p) | |
| 3078 ;; Special forms and macros will be advised into macros. | |
| 3079 ;; The trick is to construct an expansion for the advised | |
| 3080 ;; macro that does the correct thing when it gets eval'ed. | |
| 3081 ;; For macros we'll just use the expansion of the original | |
| 3082 ;; macro and return that. This way compiled advised macros | |
| 3083 ;; will be expanded into something useful. Note that after | |
| 3084 ;; advices have full control over whether they want to | |
| 3085 ;; evaluate the expansion (the value of `ad-return-value') | |
| 3086 ;; at macro expansion time or not. For special forms there | |
| 3087 ;; is no solution that interacts reasonably with the | |
| 3088 ;; compiler, hence we just evaluate the original at macro | |
| 3089 ;; expansion time and return the result. The moral of that | |
| 3090 ;; is that one should always deactivate advised special | |
| 3091 ;; forms before one byte-compiles a file. | |
|
37304
9ca19dfc32fb
(ad-make-advised-definition): Construct
Gerd Moellmann <gerd@gnu.org>
parents:
37056
diff
changeset
|
3092 `(,(if orig-macro-p 'macroexpand 'eval) |
|
9ca19dfc32fb
(ad-make-advised-definition): Construct
Gerd Moellmann <gerd@gnu.org>
parents:
37056
diff
changeset
|
3093 (cons ',origname |
|
9ca19dfc32fb
(ad-make-advised-definition): Construct
Gerd Moellmann <gerd@gnu.org>
parents:
37056
diff
changeset
|
3094 ,(ad-get-arguments advised-arglist 0)))) |
| 4110 | 3095 ((and orig-subr-p |
| 3096 orig-interactive-p | |
|
37304
9ca19dfc32fb
(ad-make-advised-definition): Construct
Gerd Moellmann <gerd@gnu.org>
parents:
37056
diff
changeset
|
3097 (not interactive-form) |
| 4110 | 3098 (not advised-interactive-form)) |
| 3099 ;; Check whether we were called interactively | |
| 3100 ;; in order to do proper prompting: | |
|
37304
9ca19dfc32fb
(ad-make-advised-definition): Construct
Gerd Moellmann <gerd@gnu.org>
parents:
37056
diff
changeset
|
3101 `(if (interactive-p) |
|
9ca19dfc32fb
(ad-make-advised-definition): Construct
Gerd Moellmann <gerd@gnu.org>
parents:
37056
diff
changeset
|
3102 (call-interactively ',origname) |
|
9ca19dfc32fb
(ad-make-advised-definition): Construct
Gerd Moellmann <gerd@gnu.org>
parents:
37056
diff
changeset
|
3103 ,(ad-make-mapped-call orig-arglist |
|
9ca19dfc32fb
(ad-make-advised-definition): Construct
Gerd Moellmann <gerd@gnu.org>
parents:
37056
diff
changeset
|
3104 advised-arglist |
|
9ca19dfc32fb
(ad-make-advised-definition): Construct
Gerd Moellmann <gerd@gnu.org>
parents:
37056
diff
changeset
|
3105 origname))) |
| 4110 | 3106 ;; And now for normal functions and non-interactive subrs |
| 3107 ;; (or subrs whose interactive behavior was advised): | |
| 3108 (t (ad-make-mapped-call | |
| 3109 advised-arglist orig-arglist origname))))) | |
| 3110 | |
| 3111 ;; Finally, build the sucker: | |
| 3112 (ad-assemble-advised-definition | |
| 3113 (cond (orig-macro-p 'macro) | |
| 3114 (orig-special-form-p 'special-form) | |
| 3115 (t 'function)) | |
| 3116 advised-arglist | |
| 3117 (ad-make-advised-definition-docstring function) | |
| 3118 interactive-form | |
| 3119 orig-form | |
| 3120 (ad-get-enabled-advices function 'before) | |
| 3121 (ad-get-enabled-advices function 'around) | |
| 3122 (ad-get-enabled-advices function 'after))))) | |
| 3123 | |
| 3124 (defun ad-assemble-advised-definition | |
| 3125 (type args docstring interactive orig &optional befores arounds afters) | |
| 3126 | |
| 26217 | 3127 "Assembles an original and its advices into an advised function. |
| 3128 It constructs a function or macro definition according to TYPE which has to | |
| 3129 be either `macro', `function' or `special-form'. ARGS is the argument list | |
| 3130 that has to be used, DOCSTRING if non-nil defines the documentation of the | |
| 3131 definition, INTERACTIVE if non-nil is the interactive form to be used, | |
| 3132 ORIG is a form that calls the body of the original unadvised function, | |
| 3133 and BEFORES, AROUNDS and AFTERS are the lists of advices with which ORIG | |
| 3134 should be modified. The assembled function will be returned." | |
| 4110 | 3135 |
| 3136 (let (before-forms around-form around-form-protected after-forms definition) | |
| 3137 (ad-dolist (advice befores) | |
| 3138 (cond ((and (ad-advice-protected advice) | |
| 3139 before-forms) | |
| 3140 (setq before-forms | |
| 3141 (` ((unwind-protect | |
| 3142 (, (ad-prognify before-forms)) | |
| 3143 (,@ (ad-body-forms | |
| 3144 (ad-advice-definition advice)))))))) | |
| 3145 (t (setq before-forms | |
| 3146 (append before-forms | |
| 3147 (ad-body-forms (ad-advice-definition advice))))))) | |
| 3148 | |
| 3149 (setq around-form (` (setq ad-return-value (, orig)))) | |
| 3150 (ad-dolist (advice (reverse arounds)) | |
| 3151 ;; If any of the around advices is protected then we | |
| 3152 ;; protect the complete around advice onion: | |
| 3153 (if (ad-advice-protected advice) | |
| 3154 (setq around-form-protected t)) | |
| 3155 (setq around-form | |
| 3156 (ad-substitute-tree | |
| 3157 (function (lambda (form) (eq form 'ad-do-it))) | |
| 3158 (function (lambda (form) around-form)) | |
| 3159 (ad-prognify (ad-body-forms (ad-advice-definition advice)))))) | |
| 3160 | |
| 3161 (setq after-forms | |
| 3162 (if (and around-form-protected before-forms) | |
| 3163 (` ((unwind-protect | |
| 3164 (, (ad-prognify before-forms)) | |
| 3165 (, around-form)))) | |
| 3166 (append before-forms (list around-form)))) | |
| 3167 (ad-dolist (advice afters) | |
| 3168 (cond ((and (ad-advice-protected advice) | |
| 3169 after-forms) | |
| 3170 (setq after-forms | |
| 3171 (` ((unwind-protect | |
| 3172 (, (ad-prognify after-forms)) | |
| 3173 (,@ (ad-body-forms | |
| 3174 (ad-advice-definition advice)))))))) | |
| 3175 (t (setq after-forms | |
| 3176 (append after-forms | |
| 3177 (ad-body-forms (ad-advice-definition advice))))))) | |
| 3178 | |
| 3179 (setq definition | |
| 3180 (` ((,@ (if (memq type '(macro special-form)) '(macro))) | |
| 3181 lambda | |
| 3182 (, args) | |
| 3183 (,@ (if docstring (list docstring))) | |
| 3184 (,@ (if interactive (list interactive))) | |
| 3185 (let (ad-return-value) | |
| 3186 (,@ after-forms) | |
| 3187 (, (if (eq type 'special-form) | |
| 3188 '(list 'quote ad-return-value) | |
| 3189 'ad-return-value)))))) | |
| 3190 | |
| 3191 (ad-insert-argument-access-forms definition args))) | |
| 3192 | |
| 3193 ;; This is needed for activation/deactivation hooks: | |
| 3194 (defun ad-make-hook-form (function hook-name) | |
| 26217 | 3195 "Make hook-form from FUNCTION's advice bodies in class HOOK-NAME." |
| 4110 | 3196 (let ((hook-forms |
| 3197 (mapcar (function (lambda (advice) | |
| 3198 (ad-body-forms (ad-advice-definition advice)))) | |
| 3199 (ad-get-enabled-advices function hook-name)))) | |
| 3200 (if hook-forms | |
| 3201 (ad-prognify (apply 'append hook-forms))))) | |
| 3202 | |
| 3203 | |
| 3204 ;; @@ Caching: | |
| 3205 ;; =========== | |
| 3206 ;; Generating an advised definition of a function is moderately expensive, | |
| 3207 ;; hence, it makes sense to cache it so we can reuse it in appropriate | |
| 3208 ;; circumstances. Of course, it only makes sense to reuse a cached | |
| 3209 ;; definition if the current advice and function definition state is the | |
| 3210 ;; same as it was at the time when the cached definition was generated. | |
| 3211 ;; For that purpose we associate every cache with an id so we can verify | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3212 ;; if it is still valid at a certain point in time. This id mechanism |
| 4110 | 3213 ;; makes it possible to preactivate advised functions, write the compiled |
| 3214 ;; advised definitions to a file and reuse them during the actual | |
| 3215 ;; activation without having to risk that the resulting definition will be | |
| 3216 ;; incorrect, well, almost. | |
| 3217 ;; | |
| 3218 ;; A cache id is a list with six elements: | |
| 3219 ;; 1) the list of names of enabled before advices | |
| 3220 ;; 2) the list of names of enabled around advices | |
| 3221 ;; 3) the list of names of enabled after advices | |
| 3222 ;; 4) the type of the original function (macro, subr, etc.) | |
| 3223 ;; 5) the arglist of the original definition (or t if it was equal to the | |
| 3224 ;; arglist of the cached definition) | |
| 3225 ;; 6) t if the interactive form of the original definition was equal to the | |
| 3226 ;; interactive form of the cached definition | |
| 3227 ;; | |
| 3228 ;; Here's how a cache can get invalidated or be incorrect: | |
| 3229 ;; A) a piece of advice used in the cache gets redefined | |
| 3230 ;; B) the current list of enabled advices is different from the ones used | |
| 3231 ;; for the cache | |
| 3232 ;; C) the type of the original function changed, e.g., a function became a | |
| 3233 ;; macro, or a subr became a function | |
| 3234 ;; D) the arglist of the original function changed | |
| 3235 ;; E) the interactive form of the original function changed | |
| 3236 ;; F) a piece of advice used in the cache got redefined before the | |
| 3237 ;; defadvice with the cached definition got loaded: This is a PROBLEM! | |
| 3238 ;; | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3239 ;; Cases A and B are the normal ones. A is taken care of by `ad-add-advice' |
| 4110 | 3240 ;; which clears the cache in such a case, B is easily checked during |
| 3241 ;; verification at activation time. | |
| 3242 ;; | |
| 3243 ;; Cases C, D and E have to be considered if one is slightly paranoid, i.e., | |
| 3244 ;; if one considers the case that the original function could be different | |
| 3245 ;; from the one available at caching time (e.g., for forward advice of | |
| 3246 ;; functions that get redefined by some packages - such as `eval-region' gets | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3247 ;; redefined by edebug). All these cases can be easily checked during |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3248 ;; verification. Element 4 of the id lets one check case C, element 5 takes |
| 4110 | 3249 ;; care of case D (using t in the equality case saves some space, because the |
| 3250 ;; arglist can be recovered at validation time from the cached definition), | |
| 3251 ;; and element 6 takes care of case E which is only a problem if the original | |
| 3252 ;; was actually a function whose interactive form was not overridden by a | |
| 3253 ;; piece of advice. | |
| 3254 ;; | |
| 3255 ;; Case F is the only one which will lead to an incorrect advised function. | |
| 3256 ;; There is no way to avoid this without storing the complete advice definition | |
| 3257 ;; in the cache-id which is not feasible. | |
| 3258 ;; | |
| 3259 ;; The cache-id of a typical advised function with one piece of advice and | |
| 3260 ;; no arglist redefinition takes 7 conses which is a small price to pay for | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3261 ;; the added efficiency. The validation itself is also pretty cheap, certainly |
| 4110 | 3262 ;; a lot cheaper than reconstructing an advised definition. |
| 3263 | |
| 3264 (defmacro ad-get-cache-definition (function) | |
| 3265 (` (car (ad-get-advice-info-field (, function) 'cache)))) | |
| 3266 | |
| 3267 (defmacro ad-get-cache-id (function) | |
| 3268 (` (cdr (ad-get-advice-info-field (, function) 'cache)))) | |
| 3269 | |
| 3270 (defmacro ad-set-cache (function definition id) | |
| 3271 (` (ad-set-advice-info-field | |
| 3272 (, function) 'cache (cons (, definition) (, id))))) | |
| 3273 | |
| 3274 (defun ad-clear-cache (function) | |
| 3275 "Clears a previously cached advised definition of FUNCTION. | |
| 3276 Clear the cache if you want to force `ad-activate' to construct a new | |
| 3277 advised definition from scratch." | |
| 3278 (interactive | |
| 3279 (list (ad-read-advised-function "Clear cached definition of: "))) | |
| 3280 (ad-set-advice-info-field function 'cache nil)) | |
| 3281 | |
| 3282 (defun ad-make-cache-id (function) | |
| 26217 | 3283 "Generate an identifying image of the current advices of FUNCTION." |
| 4110 | 3284 (let ((original-definition (ad-real-orig-definition function)) |
| 3285 (cached-definition (ad-get-cache-definition function))) | |
| 3286 (list (mapcar (function (lambda (advice) (ad-advice-name advice))) | |
| 3287 (ad-get-enabled-advices function 'before)) | |
| 3288 (mapcar (function (lambda (advice) (ad-advice-name advice))) | |
| 3289 (ad-get-enabled-advices function 'around)) | |
| 3290 (mapcar (function (lambda (advice) (ad-advice-name advice))) | |
| 3291 (ad-get-enabled-advices function 'after)) | |
| 3292 (ad-definition-type original-definition) | |
| 3293 (if (equal (ad-arglist original-definition function) | |
| 3294 (ad-arglist cached-definition)) | |
| 3295 t | |
| 3296 (ad-arglist original-definition function)) | |
| 3297 (if (eq (ad-definition-type original-definition) 'function) | |
| 3298 (equal (ad-interactive-form original-definition) | |
| 3299 (ad-interactive-form cached-definition)))))) | |
| 3300 | |
| 3301 (defun ad-get-cache-class-id (function class) | |
| 26217 | 3302 "Return the part of FUNCTION's cache id that identifies CLASS." |
| 4110 | 3303 (let ((cache-id (ad-get-cache-id function))) |
| 3304 (if (eq class 'before) | |
| 3305 (car cache-id) | |
| 3306 (if (eq class 'around) | |
| 3307 (nth 1 cache-id) | |
| 3308 (nth 2 cache-id))))) | |
| 3309 | |
| 3310 (defun ad-verify-cache-class-id (cache-class-id advices) | |
| 3311 (ad-dolist (advice advices (null cache-class-id)) | |
| 3312 (if (ad-advice-enabled advice) | |
| 3313 (if (eq (car cache-class-id) (ad-advice-name advice)) | |
| 3314 (setq cache-class-id (cdr cache-class-id)) | |
| 3315 (ad-do-return nil))))) | |
| 3316 | |
| 3317 ;; There should be a way to monitor if and why a cache verification failed | |
| 3318 ;; in order to determine whether a certain preactivation could be used or | |
| 26217 | 3319 ;; not. Right now the only way to find out is to trace |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3320 ;; `ad-cache-id-verification-code'. The code it returns indicates where the |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3321 ;; verification failed. Tracing `ad-verify-cache-class-id' might provide |
| 4110 | 3322 ;; some additional useful information. |
| 3323 | |
| 3324 (defun ad-cache-id-verification-code (function) | |
| 3325 (let ((cache-id (ad-get-cache-id function)) | |
| 3326 (code 'before-advice-mismatch)) | |
| 3327 (and (ad-verify-cache-class-id | |
| 3328 (car cache-id) (ad-get-advice-info-field function 'before)) | |
| 3329 (setq code 'around-advice-mismatch) | |
| 3330 (ad-verify-cache-class-id | |
| 3331 (nth 1 cache-id) (ad-get-advice-info-field function 'around)) | |
| 3332 (setq code 'after-advice-mismatch) | |
| 3333 (ad-verify-cache-class-id | |
| 3334 (nth 2 cache-id) (ad-get-advice-info-field function 'after)) | |
| 3335 (setq code 'definition-type-mismatch) | |
| 3336 (let ((original-definition (ad-real-orig-definition function)) | |
| 3337 (cached-definition (ad-get-cache-definition function))) | |
| 3338 (and (eq (nth 3 cache-id) (ad-definition-type original-definition)) | |
| 3339 (setq code 'arglist-mismatch) | |
| 3340 (equal (if (eq (nth 4 cache-id) t) | |
| 3341 (ad-arglist original-definition function) | |
| 3342 (nth 4 cache-id) ) | |
| 3343 (ad-arglist cached-definition)) | |
| 3344 (setq code 'interactive-form-mismatch) | |
| 3345 (or (null (nth 5 cache-id)) | |
| 3346 (equal (ad-interactive-form original-definition) | |
| 3347 (ad-interactive-form cached-definition))) | |
| 3348 (setq code 'verified)))) | |
| 3349 code)) | |
| 3350 | |
| 3351 (defun ad-verify-cache-id (function) | |
| 26217 | 3352 "True if FUNCTION's cache-id is compatible with its current advices." |
| 4110 | 3353 (eq (ad-cache-id-verification-code function) 'verified)) |
| 3354 | |
| 3355 | |
| 3356 ;; @@ Preactivation: | |
| 3357 ;; ================= | |
| 3358 ;; Preactivation can be used to generate compiled advised definitions | |
| 3359 ;; at compile time without having to give up the dynamic runtime flexibility | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3360 ;; of the advice mechanism. Preactivation is a special feature of `defadvice', |
| 4110 | 3361 ;; it involves the following steps: |
| 3362 ;; - remembering the function's current state (definition and advice-info) | |
| 3363 ;; - advising it with the defined piece of advice | |
| 3364 ;; - clearing its cache | |
| 3365 ;; - generating an interpreted advised definition by activating it, this will | |
| 3366 ;; make use of all its current active advice and its current definition | |
| 3367 ;; - saving the so generated cached definition and id | |
| 3368 ;; - resetting the function's advice and definition state to what it was | |
| 3369 ;; before the preactivation | |
| 3370 ;; - Returning the saved definition and its id to be used in the expansion of | |
| 3371 ;; `defadvice' to assign it as an initial cache, hence it will be compiled | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3372 ;; at time the `defadvice' gets compiled. |
| 4110 | 3373 ;; Naturally, for preactivation to be effective it has to be applied/compiled |
| 3374 ;; at the right time, i.e., when the current state of advices and function | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3375 ;; definition exactly reflects the state at activation time. Should that not |
| 4110 | 3376 ;; be the case, the precompiled definition will just be discarded and a new |
| 3377 ;; advised definition will be generated. | |
| 3378 | |
| 3379 (defun ad-preactivate-advice (function advice class position) | |
| 26217 | 3380 "Preactivate FUNCTION and returns the constructed cache." |
| 4110 | 3381 (let* ((function-defined-p (fboundp function)) |
| 3382 (old-definition | |
| 3383 (if function-defined-p | |
| 3384 (symbol-function function))) | |
| 3385 (old-advice-info (ad-copy-advice-info function)) | |
| 3386 (ad-advised-functions ad-advised-functions)) | |
| 3387 (unwind-protect | |
| 3388 (progn | |
| 3389 (ad-add-advice function advice class position) | |
| 3390 (ad-enable-advice function class (ad-advice-name advice)) | |
| 3391 (ad-clear-cache function) | |
|
26206
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
3392 (ad-activate function -1) |
| 4110 | 3393 (if (and (ad-is-active function) |
| 3394 (ad-get-cache-definition function)) | |
| 3395 (list (ad-get-cache-definition function) | |
| 3396 (ad-get-cache-id function)))) | |
| 3397 (ad-set-advice-info function old-advice-info) | |
| 3398 ;; Don't `fset' function to nil if it was previously unbound: | |
| 3399 (if function-defined-p | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3400 (ad-safe-fset function old-definition) |
| 4110 | 3401 (fmakunbound function))))) |
| 3402 | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3403 |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3404 ;; @@ Freezing: |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3405 ;; ============ |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3406 ;; Freezing transforms a `defadvice' into a redefining `defun/defmacro' |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3407 ;; for the advised function without keeping any advice information. This |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3408 ;; feature was jwz's idea: It generates a dumpable function definition |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3409 ;; whose documentation can be written to the DOC file, and the generated |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3410 ;; code does not need any Advice runtime support. Of course, frozen advices |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3411 ;; cannot be undone. |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3412 |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3413 ;; Freezing only considers the advice of the particular `defadvice', other |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3414 ;; already existing advices for the same function will be ignored. To ensure |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3415 ;; proper interaction when an already advised function gets redefined with |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3416 ;; a frozen advice, frozen advices always use the actual original definition |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3417 ;; of the function, i.e., they are always at the core of the onion. E.g., if |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3418 ;; an already advised function gets redefined with a frozen advice and then |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3419 ;; unadvised, the frozen advice remains as the new definition of the function. |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3420 |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3421 ;; While multiple freeze advices for a single function or freeze-advising |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3422 ;; of an already advised function are possible, they are better avoided, |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3423 ;; because definition/compile/load ordering is relevant, and it becomes |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3424 ;; incomprehensible pretty quickly. |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3425 |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3426 (defun ad-make-freeze-definition (function advice class position) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3427 (if (not (ad-has-proper-definition function)) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3428 (error |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3429 "ad-make-freeze-definition: `%s' is not yet defined" |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3430 function)) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3431 (let* ((name (ad-advice-name advice)) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3432 ;; With a unique origname we can have multiple freeze advices |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3433 ;; for the same function, each overloading the previous one: |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3434 (unique-origname |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3435 (intern (format "%s-%s-%s" (ad-make-origname function) class name))) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3436 (orig-definition |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3437 ;; If FUNCTION is already advised, we'll use its current origdef |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3438 ;; as the original definition of the frozen advice: |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3439 (or (ad-get-orig-definition function) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3440 (symbol-function function))) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3441 (old-advice-info |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3442 (if (ad-is-advised function) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3443 (ad-copy-advice-info function))) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3444 (real-docstring-fn |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3445 (symbol-function 'ad-make-advised-definition-docstring)) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3446 (real-origname-fn |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3447 (symbol-function 'ad-make-origname)) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3448 (frozen-definition |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3449 (unwind-protect |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3450 (progn |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3451 ;; Make sure we construct a proper docstring: |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3452 (ad-safe-fset 'ad-make-advised-definition-docstring |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3453 'ad-make-freeze-docstring) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3454 ;; Make sure `unique-origname' is used as the origname: |
|
29579
05016ef95d0f
(ad-advice-class-completion-table)
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
26627
diff
changeset
|
3455 (ad-safe-fset 'ad-make-origname (lambda (x) unique-origname)) |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3456 ;; No we reset all current advice information to nil and |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3457 ;; generate an advised definition that's solely determined |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3458 ;; by ADVICE and the current origdef of FUNCTION: |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3459 (ad-set-advice-info function nil) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3460 (ad-add-advice function advice class position) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3461 ;; The following will provide proper real docstrings as |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3462 ;; well as a definition that will make the compiler happy: |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3463 (ad-set-orig-definition function orig-definition) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3464 (ad-make-advised-definition function)) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3465 ;; Restore the old advice state: |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3466 (ad-set-advice-info function old-advice-info) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3467 ;; Restore functions: |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3468 (ad-safe-fset |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3469 'ad-make-advised-definition-docstring real-docstring-fn) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3470 (ad-safe-fset 'ad-make-origname real-origname-fn)))) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3471 (if frozen-definition |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3472 (let* ((macro-p (ad-macro-p frozen-definition)) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3473 (body (cdr (if macro-p |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3474 (ad-lambdafy frozen-definition) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3475 frozen-definition)))) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3476 (` (progn |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3477 (if (not (fboundp '(, unique-origname))) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3478 (fset '(, unique-origname) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3479 ;; avoid infinite recursion in case the function |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3480 ;; we want to freeze is already advised: |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3481 (or (ad-get-orig-definition '(, function)) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3482 (symbol-function '(, function))))) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3483 ((, (if macro-p 'defmacro 'defun)) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3484 (, function) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3485 (,@ body)))))))) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3486 |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3487 |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3488 ;; @@ Activation and definition handling: |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3489 ;; ====================================== |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3490 |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3491 (defun ad-should-compile (function compile) |
| 26217 | 3492 "Return non-nil if the advised FUNCTION should be compiled. |
| 3493 If COMPILE is non-nil and not a negative number then it returns t. | |
| 3494 If COMPILE is a negative number then it returns nil. | |
| 3495 If COMPILE is nil then the result depends on the value of | |
| 3496 `ad-default-compilation-action' (which see)." | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3497 (if (integerp compile) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3498 (>= compile 0) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3499 (if compile |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3500 compile |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3501 (cond ((eq ad-default-compilation-action 'never) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3502 nil) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3503 ((eq ad-default-compilation-action 'always) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3504 t) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3505 ((eq ad-default-compilation-action 'like-original) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3506 (or (ad-subr-p (ad-get-orig-definition function)) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3507 (ad-compiled-p (ad-get-orig-definition function)))) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3508 ;; everything else means `maybe': |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3509 (t (featurep 'byte-compile)))))) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3510 |
| 4110 | 3511 (defun ad-activate-advised-definition (function compile) |
| 26217 | 3512 "Redefine FUNCTION with its advised definition from cache or scratch. |
| 3513 The resulting FUNCTION will be compiled if `ad-should-compile' returns t. | |
| 3514 The current definition and its cache-id will be put into the cache." | |
| 4110 | 3515 (let ((verified-cached-definition |
| 3516 (if (ad-verify-cache-id function) | |
| 3517 (ad-get-cache-definition function)))) | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3518 (ad-safe-fset function |
| 4110 | 3519 (or verified-cached-definition |
| 3520 (ad-make-advised-definition function))) | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3521 (if (ad-should-compile function compile) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3522 (ad-compile-function function)) |
| 4110 | 3523 (if verified-cached-definition |
| 3524 (if (not (eq verified-cached-definition (symbol-function function))) | |
| 3525 ;; we must have compiled, cache the compiled definition: | |
| 3526 (ad-set-cache | |
| 3527 function (symbol-function function) (ad-get-cache-id function))) | |
| 3528 ;; We created a new advised definition, cache it with a proper id: | |
| 3529 (ad-clear-cache function) | |
| 3530 ;; ad-make-cache-id needs the new cached definition: | |
| 3531 (ad-set-cache function (symbol-function function) nil) | |
| 3532 (ad-set-cache | |
| 3533 function (symbol-function function) (ad-make-cache-id function))))) | |
| 3534 | |
| 3535 (defun ad-handle-definition (function) | |
| 26622 | 3536 "Handle re/definition of an advised FUNCTION during de/activation. |
| 4110 | 3537 If FUNCTION does not have an original definition associated with it and |
| 3538 the current definition is usable, then it will be stored as FUNCTION's | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3539 original definition. If no current definition is available (even in the |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3540 case of undefinition) nothing will be done. In the case of redefinition |
| 4110 | 3541 the action taken depends on the value of `ad-redefinition-action' (which |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3542 see). Redefinition occurs when FUNCTION already has an original definition |
| 4110 | 3543 associated with it but got redefined with a new definition and then |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3544 de/activated. If you do not like the current redefinition action change |
| 4110 | 3545 the value of `ad-redefinition-action' and de/activate again." |
| 3546 (let ((original-definition (ad-get-orig-definition function)) | |
| 3547 (current-definition (if (ad-real-definition function) | |
| 3548 (symbol-function function)))) | |
| 3549 (if original-definition | |
| 3550 (if current-definition | |
| 3551 (if (and (not (eq current-definition original-definition)) | |
| 3552 ;; Redefinition with an advised definition from a | |
| 3553 ;; different function won't count as such: | |
| 3554 (not (ad-advised-definition-p current-definition))) | |
| 3555 ;; we have a redefinition: | |
| 3556 (if (not (memq ad-redefinition-action '(accept discard warn))) | |
| 3557 (error "ad-handle-definition (see its doc): `%s' %s" | |
|
22061
eed26995bfad
(ad-handle-definition, defadvice): Fix error messages.
Richard M. Stallman <rms@gnu.org>
parents:
21365
diff
changeset
|
3558 function "invalidly redefined") |
| 4110 | 3559 (if (eq ad-redefinition-action 'discard) |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3560 (ad-safe-fset function original-definition) |
| 4110 | 3561 (ad-set-orig-definition function current-definition) |
| 3562 (if (eq ad-redefinition-action 'warn) | |
| 3563 (message "ad-handle-definition: `%s' got redefined" | |
| 3564 function)))) | |
| 3565 ;; either advised def or correct original is in place: | |
| 3566 nil) | |
| 3567 ;; we have an undefinition, ignore it: | |
| 3568 nil) | |
| 3569 (if current-definition | |
| 3570 ;; we have a first definition, save it as original: | |
| 3571 (ad-set-orig-definition function current-definition) | |
| 3572 ;; we don't have anything noteworthy: | |
| 3573 nil)))) | |
| 3574 | |
| 3575 | |
| 3576 ;; @@ The top-level advice interface: | |
| 3577 ;; ================================== | |
| 3578 | |
|
26206
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
3579 (defun ad-activate (function &optional compile) |
| 26622 | 3580 "Activate all the advice information of an advised FUNCTION. |
| 4110 | 3581 If FUNCTION has a proper original definition then an advised |
| 3582 definition will be generated from FUNCTION's advice info and the | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3583 definition of FUNCTION will be replaced with it. If a previously |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3584 cached advised definition was available, it will be used. |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3585 The optional COMPILE argument determines whether the resulting function |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3586 or a compilable cached definition will be compiled. If it is negative |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3587 no compilation will be performed, if it is positive or otherwise non-nil |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3588 the resulting function will be compiled, if it is nil the behavior depends |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3589 on the value of `ad-default-compilation-action' (which see). |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3590 Activation of an advised function that has an advice info but no actual |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3591 pieces of advice is equivalent to a call to `ad-unadvise'. Activation of |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3592 an advised function that has actual pieces of advice but none of them are |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3593 enabled is equivalent to a call to `ad-deactivate'. The current advised |
| 4110 | 3594 definition will always be cached for later usage." |
| 3595 (interactive | |
| 3596 (list (ad-read-advised-function "Activate advice of: ") | |
| 3597 current-prefix-arg)) | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3598 (if ad-activate-on-top-level |
|
26206
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
3599 ;; avoid recursive calls to `ad-activate': |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3600 (ad-with-auto-activation-disabled |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3601 (if (not (ad-is-advised function)) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3602 (error "ad-activate: `%s' is not advised" function) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3603 (ad-handle-definition function) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3604 ;; Just return for forward advised and not yet defined functions: |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3605 (if (ad-get-orig-definition function) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3606 (if (not (ad-has-any-advice function)) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3607 (ad-unadvise function) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3608 ;; Otherwise activate the advice: |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3609 (cond ((ad-has-redefining-advice function) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3610 (ad-activate-advised-definition function compile) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3611 (ad-set-advice-info-field function 'active t) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3612 (eval (ad-make-hook-form function 'activation)) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3613 function) |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3614 ;; Here we are if we have all disabled advices: |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3615 (t (ad-deactivate function))))))))) |
| 4110 | 3616 |
|
26247
f96b2bc4ef08
(ad-activate-on): Make it an alias for ad-activate.
Gerd Moellmann <gerd@gnu.org>
parents:
26217
diff
changeset
|
3617 (defalias 'ad-activate-on 'ad-activate) |
|
f96b2bc4ef08
(ad-activate-on): Make it an alias for ad-activate.
Gerd Moellmann <gerd@gnu.org>
parents:
26217
diff
changeset
|
3618 |
| 4110 | 3619 (defun ad-deactivate (function) |
| 26622 | 3620 "Deactivate the advice of an actively advised FUNCTION. |
| 4110 | 3621 If FUNCTION has a proper original definition, then the current |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3622 definition of FUNCTION will be replaced with it. All the advice |
| 4110 | 3623 information will still be available so it can be activated again with |
| 3624 a call to `ad-activate'." | |
| 3625 (interactive | |
| 3626 (list (ad-read-advised-function "Deactivate advice of: " 'ad-is-active))) | |
| 3627 (if (not (ad-is-advised function)) | |
| 3628 (error "ad-deactivate: `%s' is not advised" function) | |
| 3629 (cond ((ad-is-active function) | |
| 3630 (ad-handle-definition function) | |
| 3631 (if (not (ad-get-orig-definition function)) | |
| 3632 (error "ad-deactivate: `%s' has no original definition" | |
| 3633 function) | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3634 (ad-safe-fset function (ad-get-orig-definition function)) |
| 4110 | 3635 (ad-set-advice-info-field function 'active nil) |
| 3636 (eval (ad-make-hook-form function 'deactivation)) | |
| 3637 function))))) | |
| 3638 | |
| 3639 (defun ad-update (function &optional compile) | |
| 3640 "Update the advised definition of FUNCTION if its advice is active. | |
|
26206
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
3641 See `ad-activate' for documentation on the optional COMPILE argument." |
| 4110 | 3642 (interactive |
| 3643 (list (ad-read-advised-function | |
| 3644 "Update advised definition of: " 'ad-is-active))) | |
| 3645 (if (ad-is-active function) | |
|
26206
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
3646 (ad-activate function compile))) |
| 4110 | 3647 |
| 3648 (defun ad-unadvise (function) | |
| 26622 | 3649 "Deactivate FUNCTION and then remove all its advice information. |
| 4110 | 3650 If FUNCTION was not advised this will be a noop." |
| 3651 (interactive | |
| 3652 (list (ad-read-advised-function "Unadvise function: "))) | |
| 3653 (cond ((ad-is-advised function) | |
| 3654 (if (ad-is-active function) | |
| 3655 (ad-deactivate function)) | |
| 3656 (ad-clear-orig-definition function) | |
| 3657 (ad-set-advice-info function nil) | |
| 3658 (ad-pop-advised-function function)))) | |
| 3659 | |
| 3660 (defun ad-recover (function) | |
| 26622 | 3661 "Try to recover FUNCTION's original definition, and unadvise it. |
| 3662 This is more low-level than `ad-unadvise' in that it does not do | |
| 26627 | 3663 deactivation, which might run hooks and get into other trouble. |
| 4110 | 3664 Use in emergencies." |
| 3665 ;; Use more primitive interactive behavior here: Accept any symbol that's | |
| 3666 ;; currently defined in obarray, not necessarily with a function definition: | |
| 3667 (interactive | |
| 3668 (list (intern | |
| 3669 (completing-read "Recover advised function: " obarray nil t)))) | |
| 3670 (cond ((ad-is-advised function) | |
| 3671 (cond ((ad-get-orig-definition function) | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3672 (ad-safe-fset function (ad-get-orig-definition function)) |
| 4110 | 3673 (ad-clear-orig-definition function))) |
| 3674 (ad-set-advice-info function nil) | |
| 3675 (ad-pop-advised-function function)))) | |
| 3676 | |
| 3677 (defun ad-activate-regexp (regexp &optional compile) | |
| 26622 | 3678 "Activate functions with an advice name containing a REGEXP match. |
| 3679 This activates the advice for each function | |
| 3680 that has at least one piece of advice whose name includes a match for REGEXP. | |
|
26206
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
3681 See `ad-activate' for documentation on the optional COMPILE argument." |
| 4110 | 3682 (interactive |
| 3683 (list (ad-read-regexp "Activate via advice regexp: ") | |
| 3684 current-prefix-arg)) | |
| 3685 (ad-do-advised-functions (function) | |
| 3686 (if (ad-find-some-advice function 'any regexp) | |
|
26206
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
3687 (ad-activate function compile)))) |
| 4110 | 3688 |
| 3689 (defun ad-deactivate-regexp (regexp) | |
| 26622 | 3690 "Deactivate functions with an advice name containing REGEXP match. |
| 3691 This deactivates the advice for each function | |
| 3692 that has at least one piece of advice whose name includes a match for REGEXP." | |
| 4110 | 3693 (interactive |
| 3694 (list (ad-read-regexp "Deactivate via advice regexp: "))) | |
| 3695 (ad-do-advised-functions (function) | |
| 3696 (if (ad-find-some-advice function 'any regexp) | |
| 3697 (ad-deactivate function)))) | |
| 3698 | |
| 3699 (defun ad-update-regexp (regexp &optional compile) | |
| 26217 | 3700 "Update functions with an advice name containing a REGEXP match. |
| 26622 | 3701 This reactivates the advice for each function |
| 3702 that has at least one piece of advice whose name includes a match for REGEXP. | |
|
26206
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
3703 See `ad-activate' for documentation on the optional COMPILE argument." |
| 4110 | 3704 (interactive |
| 3705 (list (ad-read-regexp "Update via advice regexp: ") | |
| 3706 current-prefix-arg)) | |
| 3707 (ad-do-advised-functions (function) | |
| 3708 (if (ad-find-some-advice function 'any regexp) | |
| 3709 (ad-update function compile)))) | |
| 3710 | |
| 3711 (defun ad-activate-all (&optional compile) | |
| 26622 | 3712 "Activate all currently advised functions. |
|
26206
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
3713 See `ad-activate' for documentation on the optional COMPILE argument." |
| 4110 | 3714 (interactive "P") |
| 3715 (ad-do-advised-functions (function) | |
|
26206
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
3716 (ad-activate function compile))) |
| 4110 | 3717 |
| 3718 (defun ad-deactivate-all () | |
| 26622 | 3719 "Deactivate all currently advised functions." |
| 4110 | 3720 (interactive) |
| 3721 (ad-do-advised-functions (function) | |
| 3722 (ad-deactivate function))) | |
| 3723 | |
| 3724 (defun ad-update-all (&optional compile) | |
| 26217 | 3725 "Update all currently advised functions. |
| 3726 With prefix argument, COMPILE resulting advised definitions." | |
| 4110 | 3727 (interactive "P") |
| 3728 (ad-do-advised-functions (function) | |
| 3729 (ad-update function compile))) | |
| 3730 | |
| 3731 (defun ad-unadvise-all () | |
| 26622 | 3732 "Unadvise all currently advised functions." |
| 4110 | 3733 (interactive) |
| 3734 (ad-do-advised-functions (function) | |
| 3735 (ad-unadvise function))) | |
| 3736 | |
| 3737 (defun ad-recover-all () | |
| 26622 | 3738 "Recover all currently advised functions. Use in emergencies. |
| 3739 To recover a function means to try to find its original (pre-advice) | |
| 3740 definition, and delete all advice. | |
| 3741 This is more low-level than `ad-unadvise' in that it does not do | |
| 3742 deactivation, which might run hooks and get into other trouble." | |
| 4110 | 3743 (interactive) |
| 3744 (ad-do-advised-functions (function) | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3745 (condition-case nil |
| 4110 | 3746 (ad-recover function) |
| 3747 (error nil)))) | |
| 3748 | |
| 3749 | |
| 3750 ;; Completion alist of legal `defadvice' flags | |
| 3751 (defvar ad-defadvice-flags | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3752 '(("protect") ("disable") ("activate") |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3753 ("compile") ("preactivate") ("freeze"))) |
| 4110 | 3754 |
| 3755 ;;;###autoload | |
| 3756 (defmacro defadvice (function args &rest body) | |
| 26217 | 3757 "Define a piece of advice for FUNCTION (a symbol). |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3758 The syntax of `defadvice' is as follows: |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3759 |
| 26217 | 3760 \(defadvice FUNCTION (CLASS NAME [POSITION] [ARGLIST] FLAG...) |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3761 [DOCSTRING] [INTERACTIVE-FORM] |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3762 BODY... ) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3763 |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3764 FUNCTION ::= Name of the function to be advised. |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3765 CLASS ::= `before' | `around' | `after' | `activation' | `deactivation'. |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3766 NAME ::= Non-nil symbol that names this piece of advice. |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3767 POSITION ::= `first' | `last' | NUMBER. Optional, defaults to `first', |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3768 see also `ad-add-advice'. |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3769 ARGLIST ::= An optional argument list to be used for the advised function |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3770 instead of the argument list of the original. The first one found in |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3771 before/around/after-advices will be used. |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3772 FLAG ::= `protect'|`disable'|`activate'|`compile'|`preactivate'|`freeze'. |
| 4110 | 3773 All flags can be specified with unambiguous initial substrings. |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3774 DOCSTRING ::= Optional documentation for this piece of advice. |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3775 INTERACTIVE-FORM ::= Optional interactive form to be used for the advised |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3776 function. The first one found in before/around/after-advices will be used. |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3777 BODY ::= Any s-expression. |
| 4110 | 3778 |
| 3779 Semantics of the various flags: | |
| 3780 `protect': The piece of advice will be protected against non-local exits in | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3781 any code that precedes it. If any around-advice of a function is protected |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3782 then automatically all around-advices will be protected (the complete onion). |
| 4110 | 3783 |
| 3784 `activate': All advice of FUNCTION will be activated immediately if | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3785 FUNCTION has been properly defined prior to this application of `defadvice'. |
| 4110 | 3786 |
| 3787 `compile': In conjunction with `activate' specifies that the resulting | |
| 3788 advised function should be compiled. | |
| 3789 | |
| 26217 | 3790 `disable': The defined advice will be disabled, hence, it will not be used |
| 4110 | 3791 during activation until somebody enables it. |
| 3792 | |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3793 `preactivate': Preactivates the advised FUNCTION at macro-expansion/compile |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3794 time. This generates a compiled advised definition according to the current |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3795 advice state that will be used during activation if appropriate. Only use |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3796 this if the `defadvice' gets actually compiled. |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3797 |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3798 `freeze': Expands the `defadvice' into a redefining `defun/defmacro' according |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3799 to this particular single advice. No other advice information will be saved. |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3800 Frozen advices cannot be undone, they behave like a hard redefinition of |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3801 the advised function. `freeze' implies `activate' and `preactivate'. The |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3802 documentation of the advised function can be dumped onto the `DOC' file |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3803 during preloading. |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3804 |
| 26217 | 3805 See Info node `(elisp)Advising Functions' for comprehensive documentation." |
| 4110 | 3806 (if (not (ad-name-p function)) |
|
22061
eed26995bfad
(ad-handle-definition, defadvice): Fix error messages.
Richard M. Stallman <rms@gnu.org>
parents:
21365
diff
changeset
|
3807 (error "defadvice: Invalid function name: %s" function)) |
| 4110 | 3808 (let* ((class (car args)) |
| 3809 (name (if (not (ad-class-p class)) | |
|
22061
eed26995bfad
(ad-handle-definition, defadvice): Fix error messages.
Richard M. Stallman <rms@gnu.org>
parents:
21365
diff
changeset
|
3810 (error "defadvice: Invalid advice class: %s" class) |
| 4110 | 3811 (nth 1 args))) |
| 3812 (position (if (not (ad-name-p name)) | |
|
22061
eed26995bfad
(ad-handle-definition, defadvice): Fix error messages.
Richard M. Stallman <rms@gnu.org>
parents:
21365
diff
changeset
|
3813 (error "defadvice: Invalid advice name: %s" name) |
| 4110 | 3814 (setq args (nthcdr 2 args)) |
| 3815 (if (ad-position-p (car args)) | |
| 3816 (prog1 (car args) | |
| 3817 (setq args (cdr args)))))) | |
| 3818 (arglist (if (listp (car args)) | |
| 3819 (prog1 (car args) | |
| 3820 (setq args (cdr args))))) | |
| 3821 (flags | |
| 3822 (mapcar | |
| 3823 (function | |
| 3824 (lambda (flag) | |
| 3825 (let ((completion | |
| 3826 (try-completion (symbol-name flag) ad-defadvice-flags))) | |
| 3827 (cond ((eq completion t) flag) | |
| 3828 ((assoc completion ad-defadvice-flags) | |
| 3829 (intern completion)) | |
|
22061
eed26995bfad
(ad-handle-definition, defadvice): Fix error messages.
Richard M. Stallman <rms@gnu.org>
parents:
21365
diff
changeset
|
3830 (t (error "defadvice: Invalid or ambiguous flag: %s" |
| 4110 | 3831 flag)))))) |
| 3832 args)) | |
| 3833 (advice (ad-make-advice | |
| 3834 name (memq 'protect flags) | |
| 3835 (not (memq 'disable flags)) | |
| 3836 (` (advice lambda (, arglist) (,@ body))))) | |
| 3837 (preactivation (if (memq 'preactivate flags) | |
| 3838 (ad-preactivate-advice | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3839 function advice class position)))) |
| 4110 | 3840 ;; Now for the things to be done at evaluation time: |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3841 (if (memq 'freeze flags) |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3842 ;; jwz's idea: Freeze the advised definition into a dumpable |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3843 ;; defun/defmacro whose docs can be written to the DOC file: |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3844 (ad-make-freeze-definition function advice class position) |
| 26217 | 3845 ;; the normal case: |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3846 (` (progn |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3847 (ad-add-advice '(, function) '(, advice) '(, class) '(, position)) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3848 (,@ (if preactivation |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3849 (` ((ad-set-cache |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3850 '(, function) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3851 ;; the function will get compiled: |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3852 (, (cond ((ad-macro-p (car preactivation)) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3853 (` (ad-macrofy |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3854 (function |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3855 (, (ad-lambdafy |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3856 (car preactivation))))))) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3857 (t (` (function |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3858 (, (car preactivation))))))) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3859 '(, (car (cdr preactivation)))))))) |
|
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3860 (,@ (if (memq 'activate flags) |
|
26206
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
3861 (` ((ad-activate '(, function) |
|
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
3862 (, (if (memq 'compile flags) t))))))) |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3863 '(, function)))))) |
| 4110 | 3864 |
| 3865 | |
| 3866 ;; @@ Tools: | |
| 3867 ;; ========= | |
| 3868 | |
| 3869 (defmacro ad-with-originals (functions &rest body) | |
| 26217 | 3870 "Binds FUNCTIONS to their original definitions and execute BODY. |
| 4110 | 3871 For any members of FUNCTIONS that are not currently advised the rebinding will |
|
6038
2f1deaa86ee2
Removed all support for Emacs-18:
Richard M. Stallman <rms@gnu.org>
parents:
5746
diff
changeset
|
3872 be a noop. Any modifications done to the definitions of FUNCTIONS will be |
| 4110 | 3873 undone on exit of this macro." |
| 3874 (let* ((index -1) | |
| 3875 ;; Make let-variables to store current definitions: | |
| 3876 (current-bindings | |
| 3877 (mapcar (function | |
| 3878 (lambda (function) | |
| 3879 (setq index (1+ index)) | |
| 3880 (list (intern (format "ad-oRiGdEf-%d" index)) | |
| 3881 (` (symbol-function '(, function)))))) | |
| 3882 functions))) | |
| 3883 (` (let (, current-bindings) | |
| 3884 (unwind-protect | |
| 3885 (progn | |
| 3886 (,@ (progn | |
| 3887 ;; Make forms to redefine functions to their | |
| 3888 ;; original definitions if they are advised: | |
| 3889 (setq index -1) | |
| 3890 (mapcar | |
| 3891 (function | |
| 3892 (lambda (function) | |
| 3893 (setq index (1+ index)) | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3894 (` (ad-safe-fset |
| 4110 | 3895 '(, function) |
| 3896 (or (ad-get-orig-definition '(, function)) | |
| 3897 (, (car (nth index current-bindings)))))))) | |
| 3898 functions))) | |
| 3899 (,@ body)) | |
| 3900 (,@ (progn | |
| 3901 ;; Make forms to back-define functions to the definitions | |
| 3902 ;; they had outside this macro call: | |
| 3903 (setq index -1) | |
| 3904 (mapcar | |
| 3905 (function | |
| 3906 (lambda (function) | |
| 3907 (setq index (1+ index)) | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3908 (` (ad-safe-fset |
| 4110 | 3909 '(, function) |
| 3910 (, (car (nth index current-bindings))))))) | |
| 3911 functions)))))))) | |
| 3912 | |
| 3913 (if (not (get 'ad-with-originals 'lisp-indent-hook)) | |
| 3914 (put 'ad-with-originals 'lisp-indent-hook 1)) | |
| 3915 | |
| 3916 | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3917 ;; @@ Advising `documentation': |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3918 ;; ============================ |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3919 ;; Use the advice mechanism to advise `documentation' to make it |
|
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3920 ;; generate proper documentation strings for advised definitions: |
| 4110 | 3921 |
| 3922 (defadvice documentation (after ad-advised-docstring first disable preact) | |
| 3923 "Builds an advised docstring if FUNCTION is advised." | |
| 3924 ;; Because we get the function name from the advised docstring | |
| 3925 ;; this will work for function names as well as for definitions: | |
| 3926 (if (and (stringp ad-return-value) | |
| 3927 (string-match | |
| 3928 ad-advised-definition-docstring-regexp ad-return-value)) | |
| 3929 (let ((function | |
| 3930 (car (read-from-string | |
| 3931 ad-return-value (match-beginning 1) (match-end 1))))) | |
| 3932 (cond ((ad-is-advised function) | |
| 3933 (setq ad-return-value (ad-make-advised-docstring function)) | |
| 26217 | 3934 ;; Handle optional `raw' argument: |
| 4110 | 3935 (if (not (ad-get-arg 1)) |
| 3936 (setq ad-return-value | |
| 3937 (substitute-command-keys ad-return-value)))))))) | |
|
5746
94535442be19
(ad-execute-defadvices): Don't allocate advice-infos in pure space, in case we
Karl Heuer <kwzh@gnu.org>
parents:
5140
diff
changeset
|
3938 |
| 4110 | 3939 |
| 3940 ;; @@ Starting, stopping and recovering from the advice package magic: | |
| 3941 ;; =================================================================== | |
| 3942 | |
| 3943 (defun ad-start-advice () | |
| 26217 | 3944 "Start the automatic advice handling magic." |
| 4110 | 3945 (interactive) |
|
26206
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
3946 ;; Advising `ad-activate-internal' means death!! |
|
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
3947 (ad-set-advice-info 'ad-activate-internal nil) |
|
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
3948 (ad-safe-fset 'ad-activate-internal 'ad-activate) |
| 4110 | 3949 (ad-enable-advice 'documentation 'after 'ad-advised-docstring) |
|
26206
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
3950 (ad-activate 'documentation 'compile)) |
| 4110 | 3951 |
| 3952 (defun ad-stop-advice () | |
| 26622 | 3953 "Stop the automatic advice handling magic. |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3954 You should only need this in case of Advice-related emergencies." |
| 4110 | 3955 (interactive) |
|
26206
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
3956 ;; Advising `ad-activate-internal' means death!! |
|
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
3957 (ad-set-advice-info 'ad-activate-internal nil) |
| 4110 | 3958 (ad-disable-advice 'documentation 'after 'ad-advised-docstring) |
| 3959 (ad-update 'documentation) | |
|
26206
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
3960 (ad-safe-fset 'ad-activate-internal 'ad-activate-internal-off)) |
| 4110 | 3961 |
| 3962 (defun ad-recover-normality () | |
| 26217 | 3963 "Undo all advice related redefinitions and unadvises everything. |
| 4110 | 3964 Use only in REAL emergencies." |
| 3965 (interactive) | |
|
26206
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
3966 ;; Advising `ad-activate-internal' means death!! |
|
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
3967 (ad-set-advice-info 'ad-activate-internal nil) |
|
3d9818475597
(ad-activate-internal): Renamed from
Gerd Moellmann <gerd@gnu.org>
parents:
25260
diff
changeset
|
3968 (ad-safe-fset 'ad-activate-internal 'ad-activate-internal-off) |
| 4110 | 3969 (ad-recover-all) |
| 3970 (setq ad-advised-functions nil)) | |
| 3971 | |
|
8445
81f7b5d9b990
New handling of automatic advice activation that
Richard M. Stallman <rms@gnu.org>
parents:
6082
diff
changeset
|
3972 (ad-start-advice) |
| 4110 | 3973 |
| 3974 (provide 'advice) | |
| 3975 | |
| 3976 ;;; advice.el ends here |
