home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #30 / NN_1992_30.iso / spool / gnu / emacs / sources / 863 < prev    next >
Encoding:
Internet Message Format  |  1992-12-15  |  67.4 KB

  1. Path: sparky!uunet!zaphod.mps.ohio-state.edu!darwin.sura.net!rsg1.er.usgs.gov!ukma!cs.widener.edu!dsinc!ub!acsu.buffalo.edu!hans
  2. From: hans@acsu.buffalo.edu (Hans Chalupsky)
  3. Newsgroups: gnu.emacs.sources
  4. Subject: advice.el - code
  5. Message-ID: <BzABs5.9EL@acsu.buffalo.edu>
  6. Date: 15 Dec 92 05:12:04 GMT
  7. Sender: nntp@acsu.buffalo.edu
  8. Distribution: gnu
  9. Organization: State University of New York at Buffalo/Comp Sci
  10. Lines: 1649
  11. Nntp-Posting-Host: hadar.cs.buffalo.edu
  12.  
  13. Here's the code promised in the previous announcement message. Look for
  14. the ;; eof at the end of the message to check whether you got the complete
  15. file (about 70k).
  16.  
  17. Enjoy,
  18.  
  19. Hans
  20.  
  21. hans@cs.buffalo.edu                       Thm 4.2.7: The number of polar bears
  22.                                                      at an italian funeral is 
  23.                                                      always even.
  24.  
  25. ;; ------------------------ cut here -----------------------------------------
  26. ;; -*-Emacs-Lisp-*-
  27. ;;
  28. ;; Copyright (C) 1992 Hans Chalupsky
  29. ;;
  30. ;; File:     advice.el
  31. ;; Revision: $Revision: 1.7 $
  32. ;; Author:   Hans Chalupsky (hans@cs.buffalo.edu)
  33. ;; Created:   Date: 92/12/08 17:37:33
  34. ;; Modified: $Date: 92/12/14 22:41:49 $
  35. ;;
  36. ;;
  37. ;; This program is free software; you can redistribute it and/or modify
  38. ;; it under the terms of the GNU General Public License as published by
  39. ;; the Free Software Foundation; either version 1, or (at your option)
  40. ;; any later version.
  41. ;;
  42. ;; This program is distributed in the hope that it will be useful,
  43. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  44. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  45. ;; GNU General Public License for more details.
  46. ;;
  47. ;; A copy of the GNU General Public License can be obtained from this
  48. ;; program's author (send electronic mail to hans@cs.buffalo.edu) or from
  49. ;; the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
  50. ;; 02139, USA.
  51. ;;
  52. ;;
  53. ;; Description:
  54. ;; ============
  55. ;; This package implements a full-fledged Lisp-style advice mechanism
  56. ;; for Emacs Lisp. Advice is a clean and efficient way to modify the 
  57. ;; behavior of Emacs Lisp functions without having to keep  personal
  58. ;; modified copies of such functions around. A great number of such 
  59. ;; modifications can be achieved by treating the original function as a 
  60. ;; black box and specifying a different execution environment for it 
  61. ;; with a piece of advice. Think of a piece of advice as a kind of fancy
  62. ;; hook that you can attach to any function/macro/subr.
  63. ;;
  64. ;; Highlights:
  65. ;; ===========
  66. ;; - Clean definition of multiple, named before/around/after advices
  67. ;;   for functions, macros, subrs and special forms
  68. ;; - Full control over the arguments an advised function will receive,
  69. ;;   the binding environment in which it will be executed, as well as the
  70. ;;   value it will return.
  71. ;; - Allows redefinition of interactive behavior of functions and subrs,
  72. ;;   as well as making previously non-interactive functions and subrs
  73. ;;   interactive.
  74. ;; - Every piece of advice can have a documentation string which will be 
  75. ;;   combined with the original documentation of the advised function
  76. ;; - Documentation indirection ensures that command-key substitution of 
  77. ;;   documentation strings occurs when the documentation function is called,
  78. ;;   and not when the advised function is constructed.
  79. ;; - Forward advice is possible, that is functions which have autoload 
  80. ;;   definitions, or functions which might be defined later during a
  81. ;;   load/autoload can be advised without having to preload the file in
  82. ;;   which they are defined. 
  83. ;; - Forward redefinition is possible because around advice can be used to
  84. ;;   completely redefine a function.
  85. ;; - The execution of every piece of advice can be protected against error
  86. ;;   and non-local exits in preceding code or advices.
  87. ;; - Advised functions can be byte-compiled.
  88. ;; - Separation of advice definition and activation/deactivation
  89. ;; - Allows definition of load-hooks for arbitrary Emacs Lisp files without
  90. ;;   modification of these files
  91. ;;
  92. ;; How to get the latest advice.el:
  93. ;; ================================
  94. ;; You can get the latest version of this file either via anonymous ftp from 
  95. ;; ftp.cs.buffalo.edu (128.205.32.9) with pathname /pub/Emacs/advice.el,
  96. ;; or send email to hans@cs.buffalo.edu and I'll mail it to you.
  97. ;;
  98. ;; Overview:
  99. ;; =========
  100. ;; This file was subject to serious documentation overkill, and hence had to
  101. ;; be organized into the following parts (search for the items in double
  102. ;; quotes to skip to that part):
  103. ;;
  104. ;;   1) Initial information     (short but insufficient)
  105. ;;   2) "General Documentation" (boring and/or confusing)
  106. ;;   3) "Foo games", a tutorial (hopefully less boring; for people who
  107. ;;                               like to learn by example)
  108. ;;   4) "Advice Implementation" (boring code)
  109. ;;   5) "Advising DEFUN"        (exiting application of advice to 
  110. ;;                               bootstrap parts of the system)
  111. ;;
  112. ;; Restrictions:
  113. ;; =============
  114. ;; - When an advised subr is called directly from other subrs or C-code 
  115. ;;   it will not exhibit the advised behavior. The same holds for advised
  116. ;;   macros which were expanded during byte-compilation before their advice
  117. ;;   was activated.
  118. ;; - This package was developed under GNU-Emacs version 18.57. For different 
  119. ;;   versions your mileage may vary. In particular, running this under
  120. ;;   version 19 will probably need some work.
  121. ;;
  122. ;; Credits:
  123. ;; ========
  124. ;; This package is an extension and generalization of packages such as
  125. ;; insert-hooks.el written by Noah S. Friedman (friedman@prep.ai.mit.edu),
  126. ;; and advise.el written by Raul J. Acevedo (acevedo@MIT.EDU). Some ideas
  127. ;; used in here come from these packages, others come from the various Lisp
  128. ;; advice mechanisms I've come across so far, and a few are simply mine.
  129. ;;
  130. ;; Installation:
  131. ;; =============
  132. ;; Put this file somewhere into your Emacs load-path, byte-compile it for
  133. ;; efficiency, and put the following autoload declaration into your .emacs
  134. ;;
  135. ;;    (autoload 'defadvice "advice" "Define a piece of advice" nil t)
  136. ;;
  137. ;; or explicitly load it with (require 'advice) or (load "advice").
  138. ;;
  139. ;; Comments, suggestions, bug reports
  140. ;; ==================================
  141. ;; are strongly appreciated, please email them to hans@cs.buffalo.edu.
  142. ;; Also feel free to mail me any questions you might have about advice.el.
  143. ;;
  144. ;; Motivation:
  145. ;; ===========
  146. ;; Before I go on explaining how advice works, here are three examples how
  147. ;; this package can be used. The first two are very useful, the third one
  148. ;; is just a joke:
  149. ;;
  150. ;;(defadvice switch-to-buffer (before existing-buffer activate)
  151. ;;  "  Switch to existing buffers only when called interactively, unless 
  152. ;;when called with a prefix argument."
  153. ;;  (interactive 
  154. ;;   (list (call-interactively 
  155. ;;          (if (call-interactively '(lambda (arg) (interactive "P") arg))
  156. ;;              '(lambda (buffer) (interactive "BSwitch to buffer: ") buffer)
  157. ;;           '(lambda (buffer) (interactive "bSwitch to buffer: ") buffer))))))
  158. ;;
  159. ;;(defadvice find-file (before existing-file activate)
  160. ;;  "  Find existing files only"
  161. ;;  (interactive "fFind file: "))
  162. ;;
  163. ;;(defadvice car (around interactive activate)
  164. ;;  "  Make car an interactive function."
  165. ;;   (interactive "xCar of list: ")
  166. ;;   ad-do-it
  167. ;;   (if (interactive-p)
  168. ;;       (message "%s" ad-return-value)))
  169. ;;
  170. ;; Planned Extensions:
  171. ;; ===================
  172. ;; - A caching mechanism that reuses previously constructed advised definitions
  173. ;;   on activation if the advice info of a function hasn't changed
  174. ;; - Associate an enable flag with every single piece of advice such that only
  175. ;;   enabled pieces of advice will be used on activation
  176. ;; - Generalize the advice mechanism to a transformation mechanism that uses
  177. ;;   a source definition according to some specification, changes it according
  178. ;;   to the pieces of advice defined on it, and transforms it into a target
  179. ;;   definition according to some specification. With this not just named 
  180. ;;   functions but also hook-functions (values of some hook-variables) and
  181. ;;   definitions of any kind could make use of the advice facility.
  182. ;; 
  183. ;; General Documentation:
  184. ;; ======================
  185. ;; The main means of defining a piece of advice for some function is the macro
  186. ;; defadvice (type C-h d defadvice to learn more about defadvice). There is no
  187. ;; interactive way of specifying a piece of advice. However, the following
  188. ;; interactive functions can be used to manipulate the state of functions
  189. ;; advised with defadvice:
  190. ;;
  191. ;; - ad-activate combines all currently defined pieces of advice of a certain
  192. ;;               function with its original definition and redefines it with
  193. ;;               this advised definition
  194. ;; - ad-deactivate defines a function back to its unadvised original definition
  195. ;;               but keeps all advice information around so it can be
  196. ;;               activated again
  197. ;; - ad-unadvise deactivates a function and removes all of its advice 
  198. ;;               information, hence it cannot be activated again
  199. ;; - ad-recover tries to redefine a function to its original definition and
  200. ;;               discards all advice information (a low-level ad-unadvise).
  201. ;;               Use this function in emergencies only.
  202. ;;
  203. ;; - ad-remove-advice removes a particular piece of advice of a function.
  204. ;;               You still have to do ad-activate to activate the new state
  205. ;;               of advice.
  206. ;;
  207. ;; - ad-activate-all   activates all advised functions
  208. ;; - ad-deactivate-all deactivates all advised functions
  209. ;; - ad-unadvise-all   unadvises all advised functions
  210. ;; - ad-recover-all    recovers all advised functions
  211. ;;
  212. ;; - ad-compile byte-compiles a function/macro if it is compilable.
  213. ;;
  214. ;; The non-interactive function ad-add-advice can be used to add a piece of
  215. ;; advice to some function without using defadvice. This is useful if advice
  216. ;; has to be added somewhere by a function (also look at ad-make-advice).
  217. ;;
  218. ;; Separation of advice definition and activation, forward advice:
  219. ;; ===============================================================
  220. ;; Advising happens in two stages:
  221. ;;
  222. ;;   1) definition of various pieces of advice
  223. ;;   2) activation of all advice currently defined
  224. ;;
  225. ;; The advantage of this is that various pieces of advice can be defined before
  226. ;; they get combined into an advised definition which avoids unnecessary
  227. ;; constructions of intermediate advised definitions. The more important
  228. ;; advantage is that it allows a simple implementation of forward advice.
  229. ;; Advice information for a certain function accumulates as the value of the
  230. ;; advice-info property of the function symbol. This accumulation is completely
  231. ;; independent of the fact that that function might not yet be defined. The
  232. ;; special forms defun and defmacro have been advised to check whether the
  233. ;; function/macro they defined had advice information associated with it. If
  234. ;; so, the original definition will be saved, and then the advice will be
  235. ;; activated. When a file is loaded the functions/macros it defines are defined
  236. ;; with calls to defun/defmacro. Hence, we can forward advise functions/macros
  237. ;; which will be defined later during a load/autoload of some file.
  238. ;;
  239. ;; As an extension of the current activation method one could associate an
  240. ;; enable/disable flag with every piece of advice such that during activation
  241. ;; only enabled pieces of advice would be considered.
  242. ;;
  243. ;; Defining a piece of advice with defadvice:
  244. ;; ==========================================
  245. ;; A call to defadvice has the following syntax which is very similar
  246. ;; to the syntax of defun/defmacro with the difference that defadvice
  247. ;; does not specify any argument variables:
  248. ;;
  249. ;; (defadvice <function> (<class> <name> [<position>] {<flags>}*)
  250. ;;   [ [<documentation-string>] [(interactive ...)] ]
  251. ;;   {<body-form>}* )
  252. ;;
  253. ;; <function> is the name of the function to be advised. 
  254. ;;
  255. ;; <class> is the class of the advice which has to be one of `before',
  256. ;; `around', `after', `activation' or `deactivation' (the last two allow
  257. ;; definition of special act/deactivation hooks).
  258. ;;
  259. ;; <name> is the name of the advice which has to be a symbol (nil can be used
  260. ;; for unnamed advices). Names uniquely identify a piece of advice in a 
  261. ;; certain advice class, hence named advices can be redefined by defining
  262. ;; an advice with the same class and name. They can also be removed with
  263. ;; ad-remove-advice. Unnamed advices can not be redefined or removed, the
  264. ;; only way to get rid of them is to completely unadvise the function.
  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 be
  268. ;; either `first', `last' or a number that specifies a zero-based position
  269. ;; (`first' is equivalent to 0). If no position is specified `first' will be
  270. ;; used as a default. If this call to defadvice redefines an already existing
  271. ;; advice (see above) then the position argument will be ignored and the 
  272. ;; position of the already existing advice will be used.
  273. ;;
  274. ;; <flags> is a list of flags that specify further information about the
  275. ;; advice. An `activate' flag specifies that the advice information of the
  276. ;; advised function should be activated right after this advice has been
  277. ;; defined. In forward advices `activate' will be ignored. `protect'
  278. ;; specifies that this advice should be protected against non-local exits
  279. ;; and errors in preceding code/advices.  `compile' specifies that the
  280. ;; advised function should be byte-compiled. This flag will be ignored
  281. ;; unless `activate' is also specified.
  282. ;;
  283. ;; An optional <documentation-string> can be supplied to document the advice.
  284. ;; On activation of the advice it will be combined with the documentation of
  285. ;; the original function. 
  286. ;;
  287. ;; An optional (interactive ...) form can be supplied to change/add interactive
  288. ;; behavior of the original function. If more than one advice has an 
  289. ;; (interactive ...) specification then the one from the advice with the 
  290. ;; smallest position will be used. `before' advices go before `around' 
  291. ;; advices and only interactive specifications in these two advice classes
  292. ;; will be considered.
  293. ;;
  294. ;; A possibly empty list of <body-forms> specifies the body of the advice in
  295. ;; an implicit progn. The body of an advice can access/change arguments,
  296. ;; the return value, the binding environment, and can have all sorts of 
  297. ;; other side effects.
  298. ;;
  299. ;; Assembling advised definitions:
  300. ;; ===============================
  301. ;; Suppose a function/macro/subr/special-form has N pieces of before advice,
  302. ;; M pieces of around advice and K pieces of after advice. Assuming none of
  303. ;; the advices is protected, its advised definition will look like this
  304. ;; (body-form indices correspond to the position of the respective advice in
  305. ;; that advice class):
  306. ;;
  307. ;;    ([macro] lambda <arglist>
  308. ;;       [ [<combined-docstring>] [(interactive ...)] ]
  309. ;;       (let (ad-return-value)
  310. ;;         {<before-0-body-form>}*
  311. ;;               ....
  312. ;;         {<before-N-1-body-form>}*
  313. ;;         {<around-0-body-form>}*
  314. ;;            {<around-1-body-form>}*
  315. ;;                  ....
  316. ;;               {<around-M-1-body-form>}*
  317. ;;                  (setq ad-return-value
  318. ;;                        <apply original-body to arglist>)
  319. ;;               {<other-around-M-1-body-form>}*
  320. ;;                  ....
  321. ;;            {<other-around-1-body-form>}*
  322. ;;         {<other-around-0-body-form>}*
  323. ;;         {<after-0-body-form>}*
  324. ;;               ....
  325. ;;         {<after-K-1-body-form>}*
  326. ;;         ad-return-value))
  327. ;;
  328. ;; Macros and special forms will be redefined as macros, hence the optional
  329. ;; [macro] in the beginning of the definition.
  330. ;;
  331. ;; <arglist> is the argument list of the original function, hence values of
  332. ;; <arglist> variables can be accessed/changed in the body of an advice by
  333. ;; simply referring to them by their original name.  For subrs/special forms
  334. ;; <arglist> will be (&rest ad-subr-args) because argument lists of subrs
  335. ;; are not accessible.  Changing the value of ad-subr-args will change the
  336. ;; arguments supplied to the original subr.
  337. ;;
  338. ;; <combined-docstring> is the optional documentation string constructed from
  339. ;; the original documentation and the advice documentation strings.
  340. ;;
  341. ;; (interactive ...) is an optional interactive form either taken from the
  342. ;; original function or from a before/around advice. For advised interactive
  343. ;; subrs that do not have an interactive form specified in any advice we
  344. ;; have to use (interactive) and then call the subr interactively if the
  345. ;; advised function was called interactively, because the interactive
  346. ;; specification of subrs is not accessible. This is the only case where
  347. ;; changing the values of arguments will not have an affect because they
  348. ;; will be reset by the interactive specification of the subr. If this is a
  349. ;; problem one can always specify an interactive form in a before/around
  350. ;; advice to gain control over argument values that were supplied
  351. ;; interactively.
  352. ;; 
  353. ;; Then the body forms of the various advices in the various classes of advice
  354. ;; are assembled in order.  The forms of around advice L are normally part of
  355. ;; one of the forms of around advice L-1. An around advice can specify where
  356. ;; the forms of the wrapped or surrounded forms should go with the special
  357. ;; keyword ad-do-it, which will be substituted with a progn containing the
  358. ;; forms of the surrounded code.
  359. ;;
  360. ;; The innermost part of the around advice onion is 
  361. ;;      <apply original-body to arglist> 
  362. ;; whose form depends on the type of the original function. The variable
  363. ;; ad-return-value will be set to its result. This variable is visible to
  364. ;; all pieces of advice which can access and modify it before it gets returned.
  365. ;; 
  366. ;; The semantic structure of advised functions that contain protected pieces
  367. ;; of advice is the same. The only difference is that unwind-protect forms
  368. ;; make sure that the protected advice gets executed even if some previous
  369. ;; piece of advice had an error or a non-local exit. If any around advice is
  370. ;; protected then the whole around advice onion will be protected.
  371. ;;
  372. ;; Accessing argument bindings of arbitrary functions:
  373. ;; ===================================================
  374. ;; Some functions (such as trace) need a general method of accessing the 
  375. ;; names and bindings of the arguments of an advised function. To do that
  376. ;; within an advice one can use the special keyword ad-arg-bindings which
  377. ;; is a text macro that will be substituted with a form that will evaluate
  378. ;; to a list of binding specifications, one for every argument variable.
  379. ;; These binding specifications can then be examined in the body of the advice.
  380. ;; For example, somewhere in an advice we could do this:
  381. ;;
  382. ;;   (let* ((bindings ad-arg-bindings)
  383. ;;          (firstarg (car bindings))
  384. ;;          (secondarg (car (cdr bindings))))
  385. ;;     ;; Print info about first argument
  386. ;;     (print (format "%s=%s (%s)"
  387. ;;                    (ad-arg-binding-field firstarg 'name)
  388. ;;                    (ad-arg-binding-field firstarg 'value)
  389. ;;                    (ad-arg-binding-field firstarg 'type)))
  390. ;;     ;; Set value of second argument to nil unless it was a number:
  391. ;;     (if (not (numberp (ad-arg-binding-field secondarg 'value)))
  392. ;;         (set (ad-arg-binding-field secondarg 'name) nil))
  393. ;;     ....)
  394. ;;
  395. ;; The `type' of an argument is either `required', `optional' or `rest'.
  396. ;; Wherever ad-arg-bindings appears a form will be inserted that evaluates
  397. ;; to the list of bindings, hence, in order to avoid multiple unnecessary
  398. ;; evaluations one should always bind it to some variable.
  399. ;;
  400. ;; Summary of symbols with special meanings when used within an advice:
  401. ;; ====================================================================
  402. ;;   ad-return-value   name of the return value variable (get/settable)
  403. ;;   ad-subr-args      name of &rest argument variable used for advised
  404. ;;                     subrs (get/settable)
  405. ;;   ad-arg-bindings   text macro that returns the actual names, values
  406. ;;                     and types of the arguments as a list of bindings. The
  407. ;;                     order of the bindings corresponds to the order of the
  408. ;;                     arguments. The individual fields of every binding (name,
  409. ;;                     value and type) can be accessed with the function
  410. ;;                     ad-arg-binding-field (see example above).
  411. ;;   ad-do-it          text macro that identifies the place where the original
  412. ;;                     or wrapped definition should go in an around advice
  413. ;;
  414. ;; Activation/deactivation advices, file load hooks:
  415. ;; =================================================
  416. ;; There are two special classes of advice called `activation' and 
  417. ;; `deactivation'. The body forms of these advices are not included into the
  418. ;; advised definition of a function, they rather are assembled into a hook
  419. ;; form which will be evaluated whenever the advice info of the advised 
  420. ;; function gets activated or deactivated. One application of this mechanism
  421. ;; is to define file load hooks for files that do not provide such hooks.
  422. ;; For example, suppose you want to print a message whenever file-x gets
  423. ;; loaded, and suppose the last function defined in file-x is file-x-last-fn.
  424. ;; Then we can define the following advice:
  425. ;;
  426. ;;   (defadvice file-x-last-fn (activation file-x-load-hook)
  427. ;;      "Executed whenever file-x is loaded"
  428. ;;      (if load-in-progress (message "Loaded file-x")))
  429. ;;
  430. ;; This will constitute a forward advice for function file-x-last-fn which
  431. ;; will get activated when file-x is loaded. Because there are no "real"
  432. ;; pieces of advice available for it, its definition will not be changed,
  433. ;; but the activation advice will be run during its activation which is 
  434. ;; equivalent to having a file load hook for file-x.
  435. ;;
  436. ;;
  437. ;; Foo games: An advice tutorial
  438. ;; =============================
  439. ;;  ;; We start with a very innocent looking function foo that just
  440. ;;  ;; adds 1 to its argument x:
  441. ;;
  442. ;;  (defun foo (x)
  443. ;;    "Add 1 to x."
  444. ;;    (1+ x))
  445. ;;  foo
  446. ;;  
  447. ;;  (foo 3)
  448. ;;  4
  449. ;;  
  450. ;;  ;; Let's define the first piece of advice for function foo.  To do that we
  451. ;;  ;; use the macro defadvice which takes a function name, a list of advice
  452. ;;  ;; specifiers and a list of body forms as arguments.  The first element of
  453. ;;  ;; the advice specifiers is the class of the advice, the second is its
  454. ;;  ;; name, the third its position and the rest are some flags. The class of
  455. ;;  ;; our first advice is `before', its name is `add2', its position among
  456. ;;  ;; the currently defined before advices (none so far) is `first', and the
  457. ;;  ;; advice will be `activate'ed immediately.  In the body of an advice we
  458. ;;  ;; can refer to the argument variables of the original function by name.
  459. ;;  ;; Here we add 1 to x so the effect of calling foo will be to actually add
  460. ;;  ;; 2. All of the advice definitions below only have one body form for
  461. ;;  ;; simplicity, but there is no restriction to that extent. Every piece of
  462. ;;  ;; advice can have a documentation string which will be combined with the
  463. ;;  ;; documentation of the original function.
  464. ;;  
  465. ;;  (defadvice foo (before add2 first activate)
  466. ;;    "  Add 2 to x"
  467. ;;    (setq x (1+ x)))
  468. ;;  foo
  469. ;;  
  470. ;;  (foo 3)
  471. ;;  5
  472. ;;  
  473. ;;  ;; Now we define the second `before' advice which will cancel the effect
  474. ;;  ;; of the previous advice. This time we specify the position as 0 which is
  475. ;;  ;; equivalent to `first'. A number can be used to specify the zero-based
  476. ;;  ;; position of an advice among the list of advices in the same class. This
  477. ;;  ;; time we already have one before advice hence the position specification
  478. ;;  ;; actually has an effect. So, after the following definition the position
  479. ;;  ;; of the previous advice will be 1 even though we specified it with
  480. ;;  ;; `first' above, the reason for this is that the position argument is
  481. ;;  ;; relative to the currently defined pieces of advice which by now has
  482. ;;  ;; changed.
  483. ;;  
  484. ;;  (defadvice foo (before cancel-add2 0 activate)
  485. ;;    "  Again only add 1 to x"
  486. ;;    (setq x (1- x)))
  487. ;;  foo
  488. ;;  
  489. ;;  (foo 3)
  490. ;;  4
  491. ;;  
  492. ;;  ;; Now we define an advice with the same class and same name but with a
  493. ;;  ;; different position. Defining an advice in a class in which an advice
  494. ;;  ;; with that name already exists is interpreted as a redefinition of that
  495. ;;  ;; particular advice, in which case the position argument will be ignored
  496. ;;  ;; and the previous position of the redefined piece of advice is used:
  497. ;;  
  498. ;;  (defadvice foo (before cancel-add2 last activate)
  499. ;;    "  Again only add 1 to x"
  500. ;;    (setq x (1- x)))
  501. ;;  foo
  502. ;;  
  503. ;;  ;; The documentation strings of the various pieces of advice are assembled
  504. ;;  ;; in order which shows that advice `cancel-add2' is still the first
  505. ;;  ;; `before' advice even though we specified position `last' above:
  506. ;;  
  507. ;;  (documentation 'foo)
  508. ;;  "Add 1 to x.
  509. ;;  
  510. ;;  Function foo is advised:
  511. ;;  
  512. ;;  cancel-add2 (before):
  513. ;;    Again only add 1 to x
  514. ;;  add2 (before):
  515. ;;    Add 2 to x"
  516. ;;  
  517. ;;  ;; We can make a function interactive (or changing its interactive
  518. ;;  ;; behavior) by specifying an interactive form in one of the `before' or
  519. ;;  ;; `around' advices (there could be more body forms in this advice). The
  520. ;;  ;; particular definition always assigns 5 as an argument to x which gives
  521. ;;  ;; us 6 as a result when we call foo interactively:
  522. ;;  
  523. ;;  (defadvice foo (before inter last activate)
  524. ;;    "  Use 5 as argument when called interactively"
  525. ;;    (interactive (list 5)))
  526. ;;  foo
  527. ;;  
  528. ;;  (call-interactively 'foo)
  529. ;;  6
  530. ;;  
  531. ;;  ;; If more than one advices have an interactive declaration, then the one
  532. ;;  ;; of the advice with the smallest position will be used (`before' advices
  533. ;;  ;; go before `around' advices), hence the declaration below does not have
  534. ;;  ;; any effect:
  535. ;;  
  536. ;;  (defadvice foo (before inter2 last activate)
  537. ;;    (interactive (list 6)))
  538. ;;  foo
  539. ;;  
  540. ;;  (call-interactively 'foo)
  541. ;;  6
  542. ;;  
  543. ;;  ;; Let's have a look at what the definition of foo looks like now 
  544. ;;  ;; (indentation added by hand for legibility):
  545. ;;  
  546. ;;  (symbol-function 'foo)
  547. ;;  (lambda (x)
  548. ;;    "\\^origdoc
  549. ;;  
  550. ;;  Function foo is advised:
  551. ;;  
  552. ;;  cancel-add2 (before):
  553. ;;    Again only add 1 to x
  554. ;;  add2 (before):
  555. ;;    Add 2 to x
  556. ;;  inter (before):
  557. ;;    Use 5 as argument when called interactively"
  558. ;;    (interactive (list 5))
  559. ;;    (let (ad-return-value)
  560. ;;      (setq x (1- x))
  561. ;;      (setq x (1+ x))
  562. ;;      (setq ad-return-value (1+ x))
  563. ;;      ad-return-value))
  564. ;;  
  565. ;;  ;; Now we'll try some `around' advices. An `around' advice is a wrapper
  566. ;;  ;; around the original definition. It can shadow or establish bindings for
  567. ;;  ;; the original definition, and it can look at and manipulate the value
  568. ;;  ;; returned by the original function. The position of the special keyword
  569. ;;  ;; `ad-do-it' specifies where the code of the original function will be
  570. ;;  ;; executed. The keyword can appear multiple times which will result in
  571. ;;  ;; multiple copies of the original function in the resulting advised code.
  572. ;;  ;; Note, that if we don't specify a position argument (i.e., `first',
  573. ;;  ;; `last' or a number), then `first' (or 0) is the default):
  574. ;;  
  575. ;;  (defadvice foo (around times-2 activate)
  576. ;;    "  First double x"
  577. ;;    (let ((x (* x 2)))
  578. ;;      ad-do-it))
  579. ;;  foo
  580. ;;  
  581. ;;  (foo 3)
  582. ;;  7
  583. ;;  
  584. ;;  ;; Around advices are assembled like onion skins where the around advice
  585. ;;  ;; with position 0 is the outermost skin and the advice at the last
  586. ;;  ;; position is the innermost skin which is directly wrapped around the
  587. ;;  ;; original definition of the function. Hence after the next defadvice we
  588. ;;  ;; will first multiply x by 2 then add 1 and then call the original
  589. ;;  ;; definition (i.e., add 1 again):
  590. ;;  
  591. ;;  (defadvice foo (around add-1 last activate)
  592. ;;    "  Add 1 to x"
  593. ;;    (let ((x (1+ x)))
  594. ;;      ad-do-it))
  595. ;;  foo
  596. ;;  
  597. ;;  (foo 3)
  598. ;;  8
  599. ;;  
  600. ;;  ;; Again, let's see what the definition of foo looks like so far:
  601. ;;  (symbol-function 'foo)
  602. ;;  (lambda (x)
  603. ;;    "\\^origdoc
  604. ;;  
  605. ;;  Function foo is advised:
  606. ;;  
  607. ;;  cancel-add2 (before):
  608. ;;    Again only add 1 to x
  609. ;;  add2 (before):
  610. ;;    Add 2 to x
  611. ;;  inter (before):
  612. ;;    Use 5 as argument when called interactively
  613. ;;  times-2 (around):
  614. ;;    First double x
  615. ;;  add-1 (around):
  616. ;;    Add 1 to x"
  617. ;;    (interactive (list 5))
  618. ;;    (let (ad-return-value)
  619. ;;      (setq x (1- x))
  620. ;;      (setq x (1+ x))
  621. ;;      (let ((x (* x 2)))
  622. ;;        (let ((x (1+ x)))
  623. ;;          (setq ad-return-value (1+ x))))
  624. ;;      ad-return-value))
  625. ;;  
  626. ;;  ;; In every defadvice so far we have used the flag `activate' to activate
  627. ;;  ;; the advice immediately after its definition, and that's what we want in
  628. ;;  ;; most cases. However, if we define multiple pieces of advice for a
  629. ;;  ;; single function then activating every advice immediately is
  630. ;;  ;; inefficient. A better way to do this is to only activate the last
  631. ;;  ;; defined advice.  For example:
  632. ;;  
  633. ;;  (defadvice foo (after times-x)
  634. ;;    "  Multiply the result with x"
  635. ;;    (setq ad-return-value (* ad-return-value x)))
  636. ;;  foo
  637. ;;  
  638. ;;  ;; This still yields the same result as before:
  639. ;;  (foo 3)
  640. ;;  8
  641. ;;  
  642. ;;  ;; Now we define another advice and activate it which will also activate
  643. ;;  ;; the previous advice `times-x'. Note the use of the special variable
  644. ;;  ;; ad-return-value in the body of the advice which is set to the result of
  645. ;;  ;; the original function. If we change its value then the value returned
  646. ;;  ;; by the advised function will be changed accordingly:
  647. ;;  
  648. ;;  (defadvice foo (after times-x-again activate)
  649. ;;    "  Again multiply the result with x"
  650. ;;    (setq ad-return-value (* ad-return-value x)))
  651. ;;  foo
  652. ;;  
  653. ;;  ;; Now the advices have an effect:
  654. ;;  (foo 3)
  655. ;;  72
  656. ;;  
  657. ;;  ;; Once in a while we define an advice to perform some cleanup action, 
  658. ;;  ;; for example:
  659. ;;  
  660. ;;  (defadvice foo (after cleanup last activate)
  661. ;;    "  Do some cleanup"
  662. ;;    (print "Let's clean up now!"))
  663. ;;  foo
  664. ;;  
  665. ;;  ;; However, in case of an error the cleanup won't be performed:
  666. ;;  (condition-case error
  667. ;;      (foo t)
  668. ;;    (error 'error-in-foo))
  669. ;;  error-in-foo
  670. ;;  
  671. ;;  ;; To make sure a certain piece of advice gets executed even if some error
  672. ;;  ;; or non-local exit occurred in any preceding code, we can protect it by
  673. ;;  ;; using the `protect' keyword. (if any of the around advices is protected
  674. ;;  ;; then the whole around advice onion will be protected):
  675. ;;  
  676. ;;  (defadvice foo (after cleanup protect activate)
  677. ;;    "  Do some protected cleanup"
  678. ;;    (print "Let's clean up now!"))
  679. ;;  foo
  680. ;;  
  681. ;;  ;; Now the cleanup form will be executed even in case of an error:
  682. ;;  (condition-case error
  683. ;;      (foo t)
  684. ;;    (error 'error-in-foo))
  685. ;;  "Let's clean up now!"
  686. ;;  error-in-foo
  687. ;;  
  688. ;;  ;; Again, let's see what foo looks like:
  689. ;;  (symbol-function 'foo)
  690. ;;  (lambda (x)
  691. ;;    "\\^origdoc
  692. ;;  
  693. ;;  Function foo is advised:
  694. ;;  
  695. ;;  cancel-add2 (before):
  696. ;;    Again only add 1 to x
  697. ;;  add2 (before):
  698. ;;    Add 2 to x
  699. ;;  inter (before):
  700. ;;    Use 5 as argument when called interactively
  701. ;;  times-2 (around):
  702. ;;    First double x
  703. ;;  add-1 (around):
  704. ;;    Add 1 to x
  705. ;;  times-x-again (after):
  706. ;;    Again multiply the result with x
  707. ;;  times-x (after):
  708. ;;    Multiply the result with x
  709. ;;  cleanup (after):
  710. ;;    Do some protected cleanup"
  711. ;;    (interactive (list 5))
  712. ;;    (let (ad-return-value)
  713. ;;      (unwind-protect
  714. ;;          (progn (setq x (1- x))
  715. ;;                 (setq x (1+ x))
  716. ;;                 (let ((x (* x 2)))
  717. ;;                   (let ((x (1+ x)))
  718. ;;                     (setq ad-return-value (1+ x))))
  719. ;;                 (setq ad-return-value (* ad-return-value x))
  720. ;;                 (setq ad-return-value (* ad-return-value x)))
  721. ;;        (print "Let's clean up now!"))
  722. ;;      ad-return-value))
  723. ;;  
  724. ;;  ;; Finally, we can specify the `compile' keyword in a defadvice to say
  725. ;;  ;; that we want the resulting advised function to be byte-compiled
  726. ;;  ;; (`compile' will be ignored unless we also specified `activate'):
  727. ;;  
  728. ;;  (defadvice foo (after cleanup protect activate compile)
  729. ;;    "  Do some protected cleanup"
  730. ;;    (print "Let's clean up now!"))
  731. ;;  foo
  732. ;;  
  733. ;;  ;; Now foo is byte-compiled:
  734. ;;  (symbol-function 'foo)
  735. ;;  (lambda (x)
  736. ;;    "\\^origdoc
  737. ;;  
  738. ;;  Function foo is advised:
  739. ;;  
  740. ;;  cancel-add2 (before):
  741. ;;    Again only add 1 to x
  742. ;;  add2 (before):
  743. ;;    Add 2 to x
  744. ;;  inter (before):
  745. ;;    Use 5 as argument when called interactively
  746. ;;  times-2 (around):
  747. ;;    First double x
  748. ;;  add-1 (around):
  749. ;;    Add 1 to x
  750. ;;  times-x-again (after):
  751. ;;    Again multiply the result with x
  752. ;;  times-x (after):
  753. ;;    Multiply the result with x
  754. ;;  cleanup (after):
  755. ;;    Do some protected cleanup"
  756. ;;    (interactive (byte-code "\300C\207" [5] 1))
  757. ;;    (byte-code "\302\210\302^X303\216    S\211^Q\210    T\211^Q\210\304    \305\"^Y    T^Y    T\211^P))\210\304^H    \"\211^P\210\304^H    \"\211^P)\210^H)\207" [ad-return-value x nil ((byte-code "\300\301!\207" [print "Let's clean up now!"] 2)) * 2] 5))
  758. ;;  
  759. ;;  (foo 3)
  760. ;;  "Let's clean up now!"
  761. ;;  72
  762. ;;
  763. ;;
  764. ;;  ;; Forward Advice:
  765. ;;  ;; ===============
  766. ;;  
  767. ;;  ;; Define a piece of advice for an undefined function:
  768. ;;  
  769. ;;  (defadvice bar (before sub-1-more activate)
  770. ;;    "  Subtract one more from x"
  771. ;;    (setq x (1- x)))
  772. ;;  bar
  773. ;;  
  774. ;;  ;; bar it is not yet defined:
  775. ;;  (fboundp 'bar)
  776. ;;  nil
  777. ;;  
  778. ;;  ;; Now we define it and the forward advice will get activated:
  779. ;;  
  780. ;;  (defun bar (x)
  781. ;;    "Subtract 1 from x"
  782. ;;    (1- x))
  783. ;;  bar
  784. ;;  
  785. ;;  (bar 4)
  786. ;;  2
  787. ;;  
  788. ;;  ;; Redefinition will also activate any available advice:
  789. ;;
  790. ;;  (defun bar (x)
  791. ;;    "Subtract 2 from x"
  792. ;;    (- x 2))
  793. ;;  bar
  794. ;;  
  795. ;;  (bar 4)
  796. ;;  1
  797. ;;
  798.  
  799.  
  800. ;; Advice Implementation:
  801. ;; ======================
  802.  
  803. (require 'backquote)
  804.  
  805. ;; I need a function to be defined during byte-compilation for 
  806. ;; proper macro expansion, hence I preload the file if necessary
  807. ;; (bummer, no eval-when available in Emacs-Lisp):
  808. (provide 'advice)
  809. (require 'advice)
  810.  
  811. (defconst ad-version (substring "$Revision: 1.7 $" 11 -2))
  812.  
  813. (defvar ad-advised-functions nil
  814.   "List of currently advised though not necessarily activated functions")
  815.  
  816.  
  817. ;; First some utilities:
  818. ;; =====================
  819.  
  820. (defun ad-map-tree (subtree-test function tree)
  821.   "Maps over TREE and returns a tree with identical structure but every
  822. subtree for which SUBTREE-TEST is T replaced by the result of applying
  823. FUNCTION to it. TREE might be an atom or a list."
  824.   (cond ((funcall subtree-test tree)
  825.      (funcall function tree))
  826.     ((listp tree)
  827.      (mapcar (function
  828.           (lambda (subtree)
  829.             (ad-map-tree subtree-test function subtree)))
  830.          tree))
  831.     (t tree)))
  832.  
  833. (defun ad-substitute (old new tree)
  834.   "Substitutes all occurrences of OLD in TREE with NEW and returns the
  835. modified tree."
  836.   (ad-map-tree (function (lambda (subtree) (equal subtree old)))
  837.            (function (lambda (subtree) new))
  838.            tree))
  839.  
  840. (defmacro ad-dolist (varform &rest body)
  841.   "A Common-Lisp-style dolist iterator with the following syntax:
  842.  
  843.     (ad-dolist (<var> <init-form> [<result-form>])
  844.        {body-form}*)
  845.  
  846. which will iterate over the list yielded by <init-form> binding <var> to the
  847. current head at every iteration. If <result-form> is supplied its value will
  848. be returned at the end of the iteration, NIL otherwise. The iteration can be
  849. exited prematurely with (ad-do-return [<value>])."
  850.    (let* ((var (car varform))
  851.           (init (car (cdr varform)))
  852.           (result (car (cdr (cdr varform))))
  853.       ;; Use uninterned symbols that won't conflict with anything:
  854.           (listvar (make-symbol "ad-do-var"))
  855.       (tagsym (make-symbol "ad-do-exit"))
  856.       (code (` (let (((, listvar) (, init))
  857.              (, var))
  858.              (while (, listvar)
  859.                (setq (, var) (car (, listvar)))
  860.                (,@ body)
  861.                (setq (, listvar) (cdr (, listvar))))
  862.              (, result))))
  863.       contains-return)
  864.      ;; Look for ad-do-return forms and substitute them with throw's:
  865.      (setq code (ad-map-tree
  866.          (function (lambda (subtree)
  867.                  (and (consp subtree)
  868.                   (eq (car subtree) 'ad-do-return)
  869.                   (setq contains-return t))))
  870.          (function (lambda (subtree)
  871.                  (` (throw '(, tagsym) (, (car (cdr subtree)))))))
  872.          code))
  873.      ;; If we had an ad-do-return we need a catch:
  874.      (cond (contains-return (` (catch '(, tagsym) (, code))))
  875.        (t code))))
  876.  
  877.  
  878. ;; Advice info access fns:
  879. ;; =======================
  880.  
  881. ;; Advice information for a particular function is stored on the
  882. ;; advice-info property of the function symbol. It is stored as an
  883. ;; alist of the following format:
  884. ;;
  885. ;;      ((active . t/nil)
  886. ;;       (before adv1 adv2 ...)
  887. ;;       (around adv1 adv2 ...)
  888. ;;       (after  adv1 adv2 ...)
  889. ;;       (activation  adv1 adv2 ...)
  890. ;;       (deactivation  adv1 adv2 ...)
  891. ;;       (origdef . <definition>))
  892.  
  893. (defun ad-get-advice-info (function)
  894.   "Retrieves all the advice info for FUNCTION"
  895.   (get function 'ad-advice-info))
  896.  
  897. (defun ad-set-advice-info (function advice-info)
  898.   "Sets the advice info for FUNCTION"
  899.   (put function 'ad-advice-info advice-info))
  900.  
  901. (defun ad-is-advised (function)
  902.   "Returns non-NIL if FUNCTION has any advice info associated with it. This
  903. does not mean that the advice is also active."
  904.   (ad-get-advice-info function))
  905.  
  906. (defun ad-initialize-advice-info (function)
  907.   "Initializes the advice info for FUNCTION. Assumes that FUNCTION
  908. has not yet been advised."
  909.   (if (not (member function ad-advised-functions))
  910.       (setq ad-advised-functions (cons function ad-advised-functions)))
  911.   (ad-set-advice-info function (list (cons 'active nil))))
  912.  
  913. (defun ad-get-advice-info-field (function field)
  914.   "Retrieves the value of the advice info FIELD of FUNCTION."
  915.   (and (ad-is-advised function)
  916.        (cdr (assoc field (ad-get-advice-info function)))))
  917.  
  918. (defun ad-set-advice-info-field (function field value)
  919.   "Destructively modifies the VALUE of the advice info FIELD of FUNCTION."
  920.   (and (ad-is-advised function)
  921.        (cond ((assoc field (ad-get-advice-info function))
  922.           ;; A field with that name is already present:
  923.               (rplacd (assoc field (ad-get-advice-info function)) value))
  924.          (t;; otherwise, create a new field with that name:
  925.           (nconc (ad-get-advice-info function)
  926.              (list (cons field value)))))))
  927.  
  928. (defvar ad-advice-classes '(before around after activation deactivation)
  929.   "List of defined advice classes")
  930.  
  931. (defun ad-has-at-least-one-redefining-advice (function)
  932.   "non-NIL if the advice info of FUNCTION defines at least one advice that
  933. will lead to its redefinition on activation of the advice."
  934.   (and (ad-is-advised function)
  935.        (or (ad-get-advice-info-field function 'before)
  936.        (ad-get-advice-info-field function 'around)
  937.        (ad-get-advice-info-field function 'after))))
  938.  
  939. (defun ad-has-at-least-one-advice (function)
  940.   "non-NIL if the advice info of FUNCTION defines at least one advice."
  941.   (and (ad-is-advised function)
  942.        (ad-dolist (class ad-advice-classes nil)
  943.       (if (ad-get-advice-info-field function class)
  944.           (ad-do-return t)))))
  945.   
  946. (defun ad-is-active (function)
  947.   "non-NIL if FUNCTION is advised and activated"
  948.   (and (ad-is-advised function)
  949.        (ad-get-advice-info-field function 'active)))
  950.  
  951.  
  952. ;; Access fns for single pieces of advice and related predicates:
  953. ;; ==============================================================
  954.  
  955. (defun ad-make-advice (name protect forms)
  956.   "Constructs a single piece of advice to be stored in some advice field of
  957. the advice info of some function."
  958.   (list name protect forms))
  959.  
  960. (defun ad-advice-name (advice)
  961.   (nth 0 advice))
  962. (defun ad-advice-protected (advice)
  963.   (nth 1 advice))
  964. (defun ad-advice-forms (advice)
  965.   (nth 2 advice))
  966.  
  967. (defun ad-class-p (thing)
  968.   (member thing ad-advice-classes))
  969. (defun ad-name-p (thing)
  970.   (symbolp thing))
  971. (defun ad-position-p (thing)
  972.   (or (natnump thing)
  973.       (member thing '(first last))))
  974.  
  975.  
  976. ;; Adding and removing pieces of advice:
  977. ;; =====================================
  978.  
  979. (defun ad-remove-advice (function class name)
  980.   "If FUNCTION has a piece of advice of CLASS with a non-NIL NAME, then this
  981. advice will be removed from the list of advices in this class. If such an
  982. advice could be found its zero-based position will be returned. NIL otherwise."
  983.   (interactive
  984.    "SRemove advice of function: \nSClass (before, around, after): \nSName: ")
  985.   (if (ad-is-advised function)
  986.       (let ((index 0) new-advices found-at-index)
  987.     (ad-dolist (advice (ad-get-advice-info-field function class))
  988.       (cond ((and name (eq name (ad-advice-name advice)))
  989.          (setq found-at-index index))
  990.         (t (setq new-advices (cons advice new-advices))))
  991.       (setq index (1+ index)))
  992.     (ad-set-advice-info-field function class (reverse new-advices))
  993.     (if (and (interactive-p)
  994.          (not found-at-index))
  995.         (error "ad-remove-advice: No such advice found for %s: %s %s"
  996.            function class name))
  997.     found-at-index)
  998.     (if (interactive-p)
  999.     (error "ad-remove-advice: Function %s is not advised" function))
  1000.     nil))
  1001.      
  1002. (defun ad-add-advice (function advice class position)
  1003.   "Adds a piece of ADVICE of CLASS to the advice info of FUNCTION. If FUNCTION
  1004. has already one or more pieces of advice of the specified CLASS then POSITION
  1005. determines where the new piece will go. The value of POSITION can either be 
  1006. first, last or a number where 0 corresponds to first. Numbers outside the range
  1007. will be mapped to the closest extreme position. If there was already a piece
  1008. of ADVICE with the same name, then the position argument will be ignored and
  1009. the old advice will be overwritten with the new one.
  1010.     If the FUNCTION was not advised already, then its advice info will be 
  1011. initialized and its original definition will be saved (this is not the case
  1012. for forward advice of functions that might get autoloaded later)"
  1013.   (cond ((not (ad-is-advised function))
  1014.          (ad-initialize-advice-info function)
  1015.      (if (ad-has-proper-definition function)
  1016.          (ad-set-advice-info-field
  1017.           function 'origdef (symbol-function function)))))
  1018.   (let* ((previous-position
  1019.       ;; Check whether we already had an advice with the same name:
  1020.       (ad-remove-advice function class (ad-advice-name advice)))
  1021.      (advices (ad-get-advice-info-field function class))
  1022.      ;; Determine a numerical position of the new advice:
  1023.      (position (cond (previous-position)
  1024.              ((eq position 'first) 0)
  1025.              ((eq position 'last) (length advices))
  1026.              ((numberp position)
  1027.               (max 0 (min position (length advices))))
  1028.              (t (length advices))))
  1029.      (index 0)
  1030.      pre-advices)
  1031.     (while (< index position)
  1032.       (setq pre-advices (append pre-advices (list (car advices))))
  1033.       (setq advices (cdr advices))
  1034.       (setq index (1+ index)))
  1035.     (ad-set-advice-info-field
  1036.      function class (append pre-advices (cons advice advices)))))
  1037.  
  1038.  
  1039. ;; Accessing and manipulating function definitions:
  1040. ;; ================================================
  1041. ;; Some of these functions most likely have to be changed in order to work
  1042. ;; under Emacs 19.
  1043.  
  1044. (defun ad-parse-definition (definition part)
  1045.   "Takes a function/macro/advice DEFINITION (a list of forms) and returns
  1046. the form(s) identified by PART. If PART is `arglist' then the argument list
  1047. of the function will be returned, if it is `docstring' then the documentation
  1048. string will be returned, if it is `interactive' then the interactive form will
  1049. be returned, and if it is `body' then the body forms without any arglists,
  1050. docstrings or interactive forms will be returned."
  1051.   (let* ((args-index (cond ((eq (car definition) 'macro) 2)
  1052.                ((eq (car definition) 'lambda) 1)
  1053.                ;; for advice definitions:
  1054.                (t -1)))
  1055.      (doc-skip (cond ((or (stringp (nth (1+ args-index) definition))
  1056.                   (natnump (nth (1+ args-index) definition)))
  1057.               1)
  1058.              (t 0)))
  1059.      (inter-form (nth (+ args-index doc-skip 1) definition))
  1060.      (inter-skip (cond ((eq (car-safe inter-form) 'interactive) 1)
  1061.                (t 0))))
  1062.     (cond ((and (eq part 'arglist)
  1063.         (> args-index 0))
  1064.        (nth args-index definition))
  1065.       ((and (eq part 'docstring)
  1066.         (> doc-skip 0))
  1067.        (nth (1+ args-index) definition))
  1068.       ((and (eq part 'interactive)
  1069.         (> inter-skip 0))
  1070.        inter-form)
  1071.       ((eq part 'body)
  1072.        (nthcdr (+ args-index doc-skip inter-skip 1) definition)))))
  1073.  
  1074. (defvar ad-special-forms '(and catch cond condition-case defconst defmacro
  1075.                    defun defvar function if interactive let let*
  1076.                    or prog1 prog2 progn quote save-excursion
  1077.                                save-restriction save-window-excursion setq
  1078.                    setq-default unwind-protect while
  1079.                    with-output-to-temp-buffer)
  1080.   "There is no way to determine whether some subr is a special form or not,
  1081. hence we need this list.")
  1082.  
  1083. (defun ad-special-form-p (subr-name)
  1084.   "non-NIL if SUBR-NAME is the name of a special form."
  1085.   (member subr-name ad-special-forms))
  1086.  
  1087. (defun ad-interactive-p (definition)
  1088.   "non-NIL if DEFINITION can be called interactively"
  1089.   (commandp definition))
  1090.  
  1091. (defun ad-subr-p (definition)
  1092.   "non-NIL if DEFINITION is a subr"
  1093.   (subrp definition))
  1094.  
  1095. (defun ad-macro-p (definition)
  1096.   "non-NIL if DEFINITION is a macro"
  1097.   (eq (car-safe definition) 'macro))
  1098.  
  1099. (defun ad-lambda-p (definition)
  1100.   "non-NIL if DEFINITION is a lambda expression"
  1101.   (eq (car-safe definition) 'lambda))
  1102.  
  1103. (defun ad-compiled-p (definition)
  1104.   "non-NIL if DEFINITION is byte compiled"
  1105.   (and (or (ad-lambda-p definition)
  1106.        (ad-macro-p definition))
  1107.        (eq (car-safe (car-safe (ad-parse-definition definition 'body)))
  1108.        'byte-code)))
  1109.  
  1110. (defun ad-has-proper-definition (function)
  1111.   "Returns T if FUNCTION is a symbol with a proper definition, i.e., it is
  1112. fbound and its definition is not an autoload declaration."
  1113.   (and (symbolp function)
  1114.        (fboundp function)
  1115.        (not (eq (car-safe (symbol-function function)) 'autoload))))
  1116.  
  1117. (defun ad-real-definition (function)
  1118.   "Chases function cell indirection of FUNCTION until if finds an actual
  1119. definition which it will return"
  1120.   (if (ad-has-proper-definition function)
  1121.       (let ((definition (symbol-function function)))
  1122.     (if (symbolp definition)
  1123.         (ad-real-definition definition)
  1124.       definition))))
  1125.  
  1126. (defun ad-real-orig-definition (function)
  1127.   "Chases function cell indirection of the original definition of FUNCTION
  1128. until if finds an actual definition which it will return"
  1129.   (if (and (ad-is-advised function)
  1130.        (ad-get-advice-info-field function 'origdef))
  1131.       (let ((origdef (ad-get-advice-info-field function 'origdef)))
  1132.     (if (symbolp origdef)
  1133.         (ad-real-definition origdef)
  1134.       origdef))))
  1135.  
  1136. (defun ad-interactive-form (definition)
  1137.   "Returns the interactive form of DEFINITION if it is available"
  1138.   (if (consp (commandp definition))
  1139.       (commandp definition)))
  1140.  
  1141. (defun ad-lambda-expression (definition)
  1142.   "Returns the lambda expression of DEFINITION if it is a macro or a lambda"
  1143.   (cond ((ad-macro-p definition)
  1144.      (cdr definition))
  1145.     ((ad-lambda-p definition) definition)))
  1146.  
  1147. (defun ad-is-compilable (function)
  1148.   "Check whether FUNCTION has an interpreted definition that can be compiled."
  1149.   (and (ad-has-proper-definition function)
  1150.        (or (ad-lambda-p (symbol-function function))
  1151.        (ad-macro-p (symbol-function function)))
  1152.        (not (ad-compiled-p (symbol-function function)))))
  1153.  
  1154. (defun ad-compile-function (function)
  1155.   "Byte-compiles FUNCTION if it is not yet compiled."
  1156.   (interactive "aByte-compile function: ")
  1157.   (require 'byte-compile "bytecomp")
  1158.   (if (ad-is-compilable function)
  1159.       (let* ((definition (symbol-function function))
  1160.          (is-macro (ad-macro-p definition))
  1161.          (lambda (ad-lambda-expression definition))
  1162.          (compiled-lambda
  1163.           (byte-compile-lambda lambda)))
  1164.     (fset function
  1165.           (cond (is-macro (cons 'macro compiled-lambda))
  1166.             (t compiled-lambda))))))
  1167.  
  1168. (defun ad-optimize-definition (definition)
  1169.   "Takes a function DEFINITION and replaces all one-element progn forms
  1170. in it with the according body form."
  1171.   (ad-map-tree
  1172.    (function
  1173.     (lambda (form)
  1174.       (and (eq (car-safe form) 'progn)
  1175.        (= (length (cdr form)) 1))))
  1176.    (function
  1177.     (lambda (progn-form)
  1178.       (car (ad-optimize-definition (cdr progn-form)))))
  1179.    definition))
  1180.  
  1181. (defun ad-retrieve-args-form (arglist)
  1182.   "Generates a form from ARGLIST which when evaluated within a function with
  1183. that argument list will result in a list with one entry for each argument, 
  1184. where the first element of each entry is the name of the argument, the second
  1185. element is its actual current value, and the third element is either 
  1186. `required', `optional' or `rest' depending on the type of the argument."
  1187.   (let* (required optional rest)
  1188.     (setq rest (cdr (member '&rest arglist)))
  1189.     (if rest (setq arglist (reverse (cdr (member '&rest (reverse arglist))))))
  1190.     (setq optional (cdr (member '&optional arglist)))
  1191.     (if optional
  1192.     (setq required (reverse (cdr (member '&optional (reverse arglist)))))
  1193.       (setq required arglist))
  1194.     (` (list
  1195.     (,@ (mapcar (function
  1196.              (lambda (req)
  1197.                (` (list '(, req) (, req) 'required))))
  1198.             required))
  1199.     (,@ (mapcar (function
  1200.              (lambda (opt)
  1201.                (` (list '(, opt) (, opt) 'optional))))
  1202.             optional))
  1203.     (,@ (if rest (list (` (list '(, (car rest)) (, (car rest)) 'rest)))))
  1204.     ))))
  1205.  
  1206. (defun ad-arg-binding-field (binding field)
  1207.   (cond ((eq field 'name) (car binding))
  1208.     ((eq field 'value) (car (cdr binding)))
  1209.     ((eq field 'type) (car (cdr (cdr binding))))))
  1210.  
  1211.  
  1212. ;; Body access fns for pieces of advice:
  1213. ;; =====================================
  1214.  
  1215. (defun ad-advice-docstring (advice)
  1216.   (ad-parse-definition (ad-advice-forms advice) 'docstring))
  1217. (defun ad-advice-interactive (advice)
  1218.   (ad-parse-definition (ad-advice-forms advice) 'interactive))
  1219. (defun ad-advice-body-forms (advice)
  1220.   (ad-parse-definition (ad-advice-forms advice) 'body))
  1221.  
  1222.  
  1223. ;; Constructing advised definitions:
  1224. ;; =================================
  1225.  
  1226. (defun ad-assemble-advised-definition
  1227.   (type args docstring interactive orig &optional befores arounds afters)
  1228.  
  1229.   "Constructs a function or macro definition according to TYPE which has to
  1230. be either `macro', `function' or `special-form'. ARGS is the argument list
  1231. that has to be used, DOCSTRING if non-NIL defines the documentation of the
  1232. definition, INTERACTIVE if non-NIL is the interactive form that has to be used,
  1233. ORIG is a form that evaluates the body of the original unadvised function,
  1234. and BEFORES, AROUNDS and AFTERS are the lists of advices with which ORIG
  1235. should be modified. The assembled function will be returned."
  1236.  
  1237.   (let (before-forms around-form around-form-protected after-forms definition)
  1238.     (ad-dolist (advice befores)
  1239.       (cond ((and (ad-advice-protected advice)
  1240.           before-forms)
  1241.          (setq before-forms
  1242.            (` ((unwind-protect
  1243.                (progn (,@ before-forms))
  1244.              (,@ (ad-advice-body-forms advice)))))))
  1245.         (t (setq before-forms
  1246.              (append before-forms
  1247.                  (ad-advice-body-forms advice))))))
  1248.  
  1249.     (setq around-form (` (setq ad-return-value (, orig))))
  1250.     (setq arounds (reverse arounds))
  1251.     (ad-dolist (advice arounds)
  1252.       ;; If any of the around advices is protected then we
  1253.       ;; protect the complete around advice onion:
  1254.       (if (ad-advice-protected advice)
  1255.       (setq around-form-protected t))
  1256.       (setq around-form
  1257.         (ad-substitute
  1258.          'ad-do-it around-form
  1259.          (` (progn (,@ (ad-advice-body-forms advice)))))))
  1260.  
  1261.     (setq after-forms
  1262.       (if (and around-form-protected before-forms)
  1263.           (` ((unwind-protect
  1264.               (progn (,@ before-forms))
  1265.             (, around-form))))
  1266.         (append before-forms (list around-form))))
  1267.     (ad-dolist (advice afters)
  1268.       (cond ((and (ad-advice-protected advice)
  1269.           after-forms)
  1270.          (setq after-forms
  1271.            (` ((unwind-protect
  1272.                (progn (,@ after-forms))
  1273.              (,@ (ad-advice-body-forms advice)))))))
  1274.         (t (setq after-forms
  1275.              (append after-forms
  1276.                  (ad-advice-body-forms advice))))))
  1277.  
  1278.     (setq definition
  1279.       (` ((,@ (if (member type '(macro special-form)) '(macro)))
  1280.           lambda
  1281.           (, args)
  1282.           (,@ (if docstring (list docstring)))
  1283.           (,@ (if interactive (list interactive)))
  1284.           (let (ad-return-value)
  1285.         ;; Construct part of this "by hand" because of some
  1286.         ;; strange backquote behavior (or bug):
  1287.         (,@ (append after-forms
  1288.                 (if (eq type 'special-form)
  1289.                 ;; Do this because special forms become macros:
  1290.                 (list '(list 'quote ad-return-value))
  1291.                   (list 'ad-return-value))))
  1292.         ))))
  1293.  
  1294.     ;; Insert argument bindings access form if we need to:
  1295.     (setq definition
  1296.       (ad-substitute
  1297.        'ad-arg-bindings (ad-retrieve-args-form args) definition))
  1298.  
  1299.     ;; Optimize one-element progns away (I guess a special constructor
  1300.     ;; function that checked for this special case would have worked too):
  1301.     (ad-optimize-definition definition)))
  1302.  
  1303. (defvar ad-doc-indirection-pointer "\\^origdoc"
  1304.   "String used in a docstring to indicate the position where the docstring of 
  1305. the original function should get included.")
  1306.  
  1307. (defvar ad-doc-indirection-pointer-regexp
  1308.   (regexp-quote ad-doc-indirection-pointer)
  1309.   "Regexp that matches an indirection pointer in a docstring")
  1310.  
  1311. (defun ad-make-single-advice-docstring (advice class)
  1312.   (let ((advice-docstring (ad-advice-docstring advice)))
  1313.     (if advice-docstring
  1314.         (format "%s (%s):\n%s"
  1315.         (if (ad-advice-name advice)
  1316.             (ad-advice-name advice)
  1317.           "unnamed")
  1318.         class
  1319.         advice-docstring))))
  1320.  
  1321. (defun ad-make-advised-docstring (function)
  1322.   "Constructs a documentation string for the advised FUNCTION by
  1323. concatenating the original documentation with the advice documentation
  1324. strings. Every advice documentation string will start on a new line."
  1325.   (let* ((origdef (ad-real-orig-definition function))
  1326.      (origdoc (documentation origdef))
  1327.      (advice-docstring
  1328.       ;; Combine advice docstrings with original docstring, for now
  1329.       ;; just concatenate them with newlines inbetween:
  1330.       (mapconcat
  1331.        (function
  1332.         (lambda (class)
  1333.           (mapconcat (function
  1334.               (lambda (advice)
  1335.                 (let ((doc (ad-make-single-advice-docstring
  1336.                     advice class)))
  1337.                   (and doc (format "\n%s" doc)))))
  1338.              (ad-get-advice-info-field function class)
  1339.              "")))
  1340.        ad-advice-classes "")))
  1341.     (if (and origdoc (ad-is-active 'documentation))
  1342.     (setq origdoc ad-doc-indirection-pointer))
  1343.     (if (not (equal advice-docstring ""))
  1344.     (setq advice-docstring
  1345.           (format "%s %s is advised:\n%s"
  1346.               (cond ((ad-special-form-p function) "Special form")
  1347.                 ((ad-subr-p origdef) "Subr")
  1348.                 ((ad-macro-p origdef) "Macro")
  1349.                 (t "Function"))
  1350.               function
  1351.               advice-docstring)))
  1352.     (cond ((equal advice-docstring "") origdoc)
  1353.       (origdoc (format "%s\n\n%s" origdoc advice-docstring))
  1354.       (t advice-docstring))))
  1355.  
  1356. (defun ad-advised-interactive-form (function)
  1357.   "Maps over before and around advices of FUNCTION and returns the first
  1358. interactive form it finds, NIL otherwise."
  1359.   (ad-dolist (advice (append (ad-get-advice-info-field function 'before)
  1360.                  (ad-get-advice-info-field function 'around)))
  1361.      (if (ad-advice-interactive advice)
  1362.      ;; We found the first one, use it:
  1363.      (ad-do-return (ad-advice-interactive advice)))))
  1364.  
  1365. ;; There are various decisions to be made about what the advised definition
  1366. ;; of a function/macro/subr/special form should look like:
  1367. ;; - Should it have the same argument list as the original (when possible),
  1368. ;;   or should it use a universal (&rest args) form? I chose the former
  1369. ;;   because it allows pieces of advice to refer to arguments by name, instead
  1370. ;;   of having to fiddle them out of a list and changing the whole list
  1371. ;;   (for subrs we still need the &rest approach though)
  1372. ;; - What should the call to the original code look like? With a &rest argument
  1373. ;;   form one could use (apply orig args) for functions and subrs, but not for
  1374. ;;   macros and special forms. With function indirection one could construct
  1375. ;;   a form (orig-fn-symbol arg1 ... argn) as long as there are no &rest
  1376. ;;   variables. I chose to copy the code of the original function/macro into
  1377. ;;   the advised function, which is a bit of a waste but avoids all the 
  1378. ;;   argument list problems and works for macros as well. Subrs still have
  1379. ;;   to be applied though. If somebody has a better idea how to do this
  1380. ;;   let me know.
  1381.  
  1382. (defun ad-make-advised-definition (function)
  1383.   "Generates an advised definition of FUNCTION from its advice info."
  1384.   (if (and (ad-is-advised function)
  1385.        (ad-has-at-least-one-redefining-advice function))
  1386.       (let* ((origdef (ad-real-orig-definition function))
  1387.          (orig-interactive-p (ad-interactive-p origdef))
  1388.          (orig-subr-p (ad-subr-p origdef))
  1389.          (orig-special-form-p (ad-special-form-p function))
  1390.          (orig-macro-p (ad-macro-p origdef))
  1391.          ;; Construct the individual pieces that we need for assembly:
  1392.          (arglist (cond ((or orig-subr-p orig-special-form-p)
  1393.                          ;; The argument lists of subrs/special forms are
  1394.                  ;; not accessible, hence we use &rest ad-subr-args
  1395.                  '(&rest ad-subr-args))
  1396.                 ;; otherwise, use same args as the original fn
  1397.                 (t (ad-parse-definition origdef 'arglist))))
  1398.          (advised-interactive-form (ad-advised-interactive-form function))
  1399.          (interactive-form
  1400.           (cond (orig-macro-p nil)
  1401.             (advised-interactive-form)
  1402.             ((ad-interactive-form origdef))
  1403.             ;; Otherwise, just make it interactive if we have to:
  1404.             (orig-interactive-p '(interactive))))
  1405.          (orig-form
  1406.           (cond (orig-special-form-p
  1407.              ;; Special forms are tricky because they are not apply-
  1408.              ;; able, hence we temporarily bind ad-original-subr to
  1409.              ;; their original definition and construct an EVAL form
  1410.              ;; that provides the proper arguments. This is save even
  1411.              ;; if the evaluation of the arguments causes another
  1412.              ;; advised special form to rebind ad-original-subr,
  1413.              ;; because EVAL saves the definition of the symbol in
  1414.              ;; functional position right away and later applies it
  1415.              ;; to the evaluated arguments (actually, special forms
  1416.              ;; should not lead to immediate argument evaluation
  1417.              ;; anyway):
  1418.              (` (progn (fset 'ad-original-subr '(, origdef))
  1419.                    (eval (cons 'ad-original-subr ad-subr-args)))))
  1420.             (orig-subr-p
  1421.              (cond ((or (not orig-interactive-p)
  1422.                 advised-interactive-form)
  1423.                 ;; If the advised subr is not interactive, or if
  1424.                 ;; somebody advised interactive handling then we
  1425.                 ;; can simply apply the subr without interaction...
  1426.                 (` (apply (, origdef) ad-subr-args)))
  1427.                (t;; ...otherwise we have to check whether we
  1428.                 ;; were called interactively in order to do
  1429.                 ;; proper prompting:
  1430.                 (` (if (interactive-p)
  1431.                    (call-interactively (, origdef))
  1432.                  (apply (, origdef) ad-subr-args))))))
  1433.             ;; And now for normal functions (winner, this will work
  1434.             ;; for macros as well):
  1435.             (t (` (progn (,@ (ad-parse-definition origdef 'body))))))))
  1436.  
  1437.     ;; Finally, build the sucker:
  1438.     (ad-assemble-advised-definition
  1439.      (cond (orig-macro-p 'macro)
  1440.            (orig-special-form-p 'special-form)
  1441.            (t 'lambda))
  1442.      arglist
  1443.      (ad-make-advised-docstring function)
  1444.      interactive-form
  1445.      orig-form
  1446.      (ad-get-advice-info-field function 'before)
  1447.      (ad-get-advice-info-field function 'around)
  1448.      (ad-get-advice-info-field function 'after)))))
  1449.  
  1450. (defun ad-make-hook-form (function hook-name)
  1451.   "Uses the body forms of all advices of FUNCTION that are of class HOOK-NAME
  1452. to generate a single form that can be evaluated in a hook-style fashion."
  1453.   (let ((hook-forms
  1454.      (mapcar 'ad-advice-body-forms
  1455.          (ad-get-advice-info-field function hook-name))))
  1456.     (if hook-forms
  1457.     (cons 'progn (apply 'append hook-forms)))))
  1458.  
  1459.  
  1460. ;; The top-level advice interface:
  1461. ;; ===============================
  1462.  
  1463. (defun ad-activate (function &optional compile)
  1464.   "If FUNCTION is an advised function with a proper original definition, then
  1465. an advised definition will be generated from FUNCTION's advice info and the 
  1466. definition of FUNCTION will be replaced with the advised definition. With an
  1467. argument (compile is non-NIL) the resulting function will also be compiled.
  1468. Activation of an advised function that has an advice info but no actual pieces
  1469. of advice is equivalent to a call to ad-unadvise."
  1470.   (interactive "aActivate advice of: \nP")
  1471.   (if (not (ad-is-advised function))
  1472.       (error "ad-activate: No advice information available for %s" function)
  1473.     (if (not (ad-get-advice-info-field function 'origdef))
  1474.     (error "ad-activate: Function %s has not yet been defined" function)
  1475.       (if (not (ad-has-at-least-one-advice function))
  1476.       (ad-unadvise function)
  1477.     ;; Otherwise activate the advice:
  1478.     (cond ((ad-has-at-least-one-redefining-advice function)
  1479.            (fset function (ad-make-advised-definition function))
  1480.            (if compile (ad-compile-function function))))
  1481.     (ad-set-advice-info-field function 'active t)
  1482.     (eval (ad-make-hook-form function 'activation))
  1483.     function))))
  1484.  
  1485. (defun ad-deactivate (function)
  1486.   "If FUNCTION is an advised function with a proper original definition,
  1487. then the current definition of FUNCTION will be replaced with its original 
  1488. definition. All the advice information will still be available. It can be
  1489. activated again with a call to ad-activate."
  1490.   (interactive "aDeactivate advice of: ")
  1491.   (if (not (ad-is-advised function))
  1492.       (error "ad-deactivate: %s does not have any advice information" function)
  1493.     (if (null (ad-get-advice-info-field function 'origdef))
  1494.     (error "ad-deactivate: No original definition available for %s"
  1495.            function)
  1496.       (fset function (ad-get-advice-info-field function 'origdef))
  1497.       (ad-set-advice-info-field function 'active nil)
  1498.       (eval (ad-make-hook-form function 'deactivation))
  1499.       function)))
  1500.  
  1501. (defun ad-unadvise (function)
  1502.   "Deactivates the advice of FUNCTION if its advice is currently active, and
  1503. then removes all its advice information. If FUNCTION was not advised this
  1504. will be a noop."
  1505.   (interactive "aDeactivate advice and remove all advice info of: ")
  1506.   (cond ((ad-is-advised function)
  1507.      (if (ad-is-active function)
  1508.          (ad-deactivate function))
  1509.      (ad-set-advice-info function nil)
  1510.      (setq ad-advised-functions (delq function ad-advised-functions)))))
  1511.  
  1512. (defun ad-recover (function)
  1513.   "Recovers the original definition of FUNCTION if available, and then
  1514. removes all its advice information without doing any deactivation. 
  1515. Use in emergencies."
  1516.   (interactive "aRecover and remove all advice info of: ")
  1517.   (cond ((ad-is-advised function)
  1518.      (if (ad-get-advice-info-field function 'origdef)
  1519.          (fset function (ad-get-advice-info-field function 'origdef)))
  1520.      (ad-set-advice-info function nil)
  1521.      (setq ad-advised-functions (delq function ad-advised-functions)))))
  1522.  
  1523. (defun ad-activate-all ()
  1524.   "Activates all currently advised functions"
  1525.   (interactive)
  1526.   (ad-dolist (function ad-advised-functions)
  1527.      (ad-activate function)))
  1528.  
  1529. (defun ad-deactivate-all ()
  1530.   "Deactivates all currently advised functions"
  1531.   (interactive)
  1532.   (ad-dolist (function ad-advised-functions)
  1533.      (ad-deactivate function)))
  1534.   
  1535. (defun ad-unadvise-all ()
  1536.   "Unadvises all currently advised functions"
  1537.   (interactive)
  1538.   (ad-dolist (function (copy-alist ad-advised-functions))
  1539.      (ad-unadvise function)))
  1540.  
  1541. (defun ad-recover-all ()
  1542.   "Recovers all currently advised functions. Use in emergencies"
  1543.   (interactive)
  1544.   (ad-dolist (function (copy-alist ad-advised-functions))
  1545.      (ad-recover function)))
  1546.  
  1547. (defvar ad-defadvice-flags '(protect activate compile)
  1548.   "Set of legal defadvice flags")
  1549.  
  1550. (defmacro defadvice (function args &rest body)
  1551.   "Defines a piece of advice for FUNCTION (a symbol). ARGS is a list of
  1552. symbols which specify the class, name and position of the advice and
  1553. some flags.  The first element of ARGS specifies the class and must be
  1554. one of `before', `around', `after', `activation' or `deactivation'.
  1555. The second element must be a symbol that specifies the name of the
  1556. advice.  Unnamed advices are specified with NIL as their name. If the
  1557. third element is either `first', `last' or an integer it will be used
  1558. as the position for the advice.  Otherwise the position defaults to
  1559. `first'.  The rest of ARGS is a set of flags. If `protect' is member
  1560. of these flags then the piece of advice will be protected against
  1561. non-local exits in any code that precedes it. If any around advice of
  1562. a function is protected then automatically all around advices will be
  1563. protected (the complete onion).  If `activate' is member of the flags
  1564. then all advice of FUNCTION will be activated immediately (only if
  1565. FUNCTION has been properly defined prior to the defadvice).  If
  1566. `compile' is a member of the flags together with `activate' then the
  1567. resulting advised function will be compiled.
  1568.    Finally, BODY is the list of forms that define the advice. The
  1569. format is similar to that used within defun. The BODY may have a
  1570. documentation string which will be combined with the documentation
  1571. strings of other pieces of advice as well as with the documentation of
  1572. the original definition. BODY may also have an (interactive ...)
  1573. declaration which will be used instead of the one of the original
  1574. function if this is the first advice that has such a declaration. For
  1575. example, if a function has two pieces of before advice both of which
  1576. have an interactive declaration, then the declaration of the before
  1577. advice at position 0 will be used. Interactive declarations in after
  1578. advices will be ignored. An advice that only contains an interactive
  1579. declaration can be used to change the interactive behavior of a
  1580. function without executing any additional advice code. Interactive
  1581. declarations in advices can also be used to make previously
  1582. non-interactive functions interactive."
  1583.   (if (not (and function (symbolp function)))
  1584.       (error "defadvice: Can only advise named functions: %s" function))
  1585.   (let* ((class (nth 0 args))
  1586.      (name (nth 1 args))
  1587.      (position (if (ad-position-p (nth 2 args))
  1588.                (nth 2 args)))
  1589.      (flags (cond (position (nthcdr 3 args))
  1590.              (t (nthcdr 2 args)))))
  1591.     (if (not (ad-class-p class))
  1592.     (error "defadvice: Illegal advice class: %s" class))
  1593.     (if (not (ad-name-p name))
  1594.     (error "defadvice: Illegal advice name: %s" name))
  1595.     (ad-dolist (flag flags)
  1596.        (if (not (member flag ad-defadvice-flags))
  1597.        (error "defadvice: Illegal flag: %s" flag)))
  1598.     (if (null position) (setq position 'first))
  1599.     (ad-add-advice
  1600.      function (ad-make-advice name (member 'protect flags) body)
  1601.      class position)
  1602.     (if (and (member 'activate flags)
  1603.          (ad-has-proper-definition function))
  1604.     (ad-activate function (member 'compile flags)))
  1605.     (list 'quote function)))
  1606.  
  1607.  
  1608. ;; Advising DEFUN, DEFMACRO and DOCUMENTATION
  1609. ;; ==========================================
  1610. ;; Use the advise mechanism to advise defun/defmacro so we can forward advise
  1611. ;; functions that might be defined later during load/autoload:
  1612.  
  1613. (defun ad-activate-redefined-function (function)
  1614.   "Assumes the current definition of FUNCTION to be its original definition,
  1615. and if FUNCTION has any advice info saves that as its new origdef and activates
  1616. all of its advice. If the original definition was byte-compiled the new advised
  1617. function will get compiled too."
  1618.   (cond ((ad-is-advised function)
  1619.      ;; save the original definition
  1620.      (ad-set-advice-info-field
  1621.       function 'origdef (symbol-function function))
  1622.      ;; activate the advice and compile it if the original was compiled:
  1623.      (ad-activate
  1624.       function
  1625.       (ad-compiled-p (symbol-function function))))))
  1626.  
  1627. (defadvice defun (after check-advice first activate compile)
  1628.   "Whenever an advised function gets redefined with defun all its
  1629. advices will be activated immediately after redefinition. If the
  1630. original function was compiled, e.g., when a byte-compiled file was
  1631. loaded, then the advised function will be compiled too."
  1632.   (ad-activate-redefined-function (car ad-subr-args)))
  1633.  
  1634. (defadvice defmacro (after check-advice first activate compile)
  1635.   "Whenever an advised macro gets redefined with defmacro all its
  1636. advices will be activated immediately after redefinition. If the
  1637. original macro was compiled, e.g., when a byte-compiled file was
  1638. loaded, then the advised macro will be compiled too.\n"
  1639.   (ad-activate-redefined-function (car ad-subr-args)))
  1640.  
  1641. (defadvice documentation (after expand-indirection activate compile)
  1642.   "Expands documentation indirection pointers to insert original docstrings
  1643. in order to properly substitute key bindings at the time this function 
  1644. is called.\n"
  1645.   (if (and (symbolp (car ad-subr-args))
  1646.        (stringp ad-return-value)
  1647.        (ad-is-active (car ad-subr-args))
  1648.        (string-match ad-doc-indirection-pointer-regexp ad-return-value))
  1649.       (setq ad-return-value
  1650.         (format "%s%s%s"
  1651.             (substring ad-return-value 0 (match-beginning 0))
  1652.             ;; Make sure that in the very odd case that the original
  1653.             ;; docstring of the advised functions contains the
  1654.             ;; indirection pointer we don't go into infinite recursion
  1655.             ;; by binding the regexp to something that won't ever match
  1656.                     (let ((ad-doc-indirection-pointer-regexp " \\`"))
  1657.               (documentation
  1658.                (ad-get-advice-info-field (car ad-subr-args) 'origdef)))
  1659.             (substring ad-return-value (match-end 0))))))
  1660.  
  1661. ;; eof
  1662.