File: advice.el.html
Advice is documented in the Emacs Lisp Manual.
@ Introduction:
===============
This package implements a full-fledged Lisp-style advice mechanism
for Emacs Lisp. Advice is a clean and efficient way to modify the
behavior of Emacs Lisp functions without having to keep personal
modified copies of such functions around. A great number of such
modifications can be achieved by treating the original function as a
black box and specifying a different execution environment for it
with a piece of advice. Think of a piece of advice as a kind of fancy
hook that you can attach to any function/macro/subr.
@ Highlights:
=============
- Clean definition of multiple, named before/around/after advices
for functions and macros.
- Full control over the arguments an advised function will receive,
the binding environment in which it will be executed, as well as the
value it will return.
- Allows re/definition of interactive behavior for commands.
- Every piece of advice can have its documentation string.
- The execution of every piece of advice can be protected against error
and non-local exits in preceding code or advices.
- Simple argument access either by name, or, more portable but as
efficient, via access macros
- Allows the specification of a different argument list for the advised
version of a function.
- Advised functions can be byte-compiled either at file-compile time
(see preactivation) or activation time.
- Separation of advice definition and activation.
- Forward advice is possible, that is
as yet undefined or autoload functions can be advised without having to
preload the file in which they are defined.
- Forward redefinition is possible because around advice can be used to
completely redefine a function.
- A caching mechanism for advised definition provides for cheap deactivation
and reactivation of advised functions.
- Preactivation allows efficient construction and compilation of advised
definitions at file compile time without giving up the flexibility of
the advice mechanism.
- En/disablement mechanism allows the use of different "views" of advised
functions depending on what pieces of advice are currently en/disabled
- Provides manipulation mechanisms for sets of advised functions via
regular expressions that match advice names.
@ Overview, or how to read this file:
=====================================
You can use outline-mode to help you read this documentation (set
outline-regexp to ";; @+").
The four major sections of this file are:
@ This initial information ...installation, customization etc.
@ Advice documentation: ...general documentation
@ Foo games: An advice tutorial ...teaches about Advice by example
@ Advice implementation: ...actual code, yeah!!
The latter three are actual headings which you can search for
directly in case outline-mode doesn't work for you.
@ Restrictions:
===============
- Advised functions/macros/subrs will only exhibit their advised behavior
when they are invoked via their function cell. This means that advice will
not work for the following:
+ advised subrs that are called directly from other subrs or C-code
+ advised subrs that got replaced with their byte-code during
byte-compilation (e.g., car)
+ advised macros which were expanded during byte-compilation before
their advice was activated.
@ Credits:
==========
This package is an extension and generalization of packages such as
insert-hooks.el written by Noah S. Friedman, and advise.el written by
Raul J. Acevedo. Some ideas used in here come from these packages,
others come from the various Lisp advice mechanisms I've come across
so far, and a few are simply mine.
@ Safety Rules and Emergency Exits:
===================================
Before we begin: CAUTION!!
Advice provides you with a lot of rope to hang yourself on very
easily accessible trees, so, here are a few important things you
should know:
If you experience any strange behavior/errors etc. that you attribute to Advice or to some ill-advised function do one of the following:
- M-x ad-deactivate FUNCTION (if you have a definite suspicion what
function gives you problems)
- M-x ad-deactivate-all (if you don't have a clue what's going wrong)
- M-x ad-recover-normality (for real emergencies)
- If none of the above solves your Advice-related problem go to another
terminal, kill your Emacs process and send me some hate mail.
The first two measures have restarts, i.e., once you've figured out
the problem you can reactivate advised functions with either ad-activate,
or ad-activate-all. ad-recover-normality unadvises
everything so you won't be able to reactivate any advised functions, you'll
have to stick with their standard incarnations for the rest of the session.
RELAX: Advice is pretty safe even if you are oblivious to the above. I use it extensively and haven't run into any serious trouble in a long time. Just wanted you to be warned.
@ Customization:
================
Look at the documentation of ad-redefinition-action for possible values
of this variable. Its default value is warn which will print a warning
message when an already defined advised function gets redefined with a
new original definition and de/activated.
Look at the documentation of ad-default-compilation-action for possible
values of this variable. Its default value is maybe which will compile
advised definitions during activation in case the byte-compiler is already
loaded. Otherwise, it will leave them uncompiled.
@ Motivation:
=============
Before I go on explaining how advice works, here are four simple examples
how this package can be used. The first three are very useful, the last one
is just a joke:
(defadvice switch-to-buffer (before existing-buffers-only activate)
"When called interactively switch to existing buffers only, unless
when called with a prefix argument."
(interactive
(list (read-buffer "Switch to buffer: " (other-buffer)
(null current-prefix-arg)))))
(defadvice switch-to-buffer (around confirm-non-existing-buffers activate)
"Switch to non-existing buffers only upon confirmation."
(interactive "BSwitch to buffer: ")
(if (or (get-buffer (ad-get-arg 0))
(y-or-n-p (format-message "`%s' does not exist, create? "
(ad-get-arg 0))))
ad-do-it))
(defadvice find-file (before existing-files-only activate)
"Find existing files only"
(interactive "fFind file: "))
(defadvice car (around interactive activate)
"Make `car' an interactive function."
(interactive "xCar of list: ")
ad-do-it
(if (called-interactively-p 'interactive)
(message "%s" ad-return-value)))
@ Advice documentation:
=======================
Below is general documentation of the various features of advice. For more
concrete examples check the corresponding sections in the tutorial part.
@@ Terminology:
===============
- Emacs: Emacs as released by the GNU Project
- Advice: The name of this package.
- advices: Short for "pieces of advice".
@@ Defining a piece of advice with defadvice:
===============================================
The main means of defining a piece of advice is the macro defadvice,
there is no interactive way of specifying a piece of advice. A call to
defadvice has the following syntax which is similar to the syntax of
defun/defmacro:
(defadvice <function> (<class> <name> [<position>] [<arglist>] {<flags>}*)
[ [<documentation-string>] [<interactive-form>] ]
{<body-form>}* )
<function> is the name of the function/macro/subr to be advised.
<class> is the class of the advice which has to be one of before,
around, after, activation or deactivation (the last two allow
definition of special act/deactivation hooks).
<name> is the name of the advice which has to be a non-nil symbol.
Names uniquely identify a piece of advice in a certain advice class,
hence, advices can be redefined by defining an advice with the same class
and name. Advice names are global symbols, hence, the same name space
conventions used for function names should be applied.
An optional <position> specifies where in the current list of advices of
the specified <class> this new advice will be placed. <position> has to
be either first, last or a number that specifies a zero-based
position (first is equivalent to 0). If no position is specified
first will be used as a default. If this call to defadvice redefines
an already existing advice (see above) then the position argument will
be ignored and the position of the already existing advice will be used.
An optional <arglist> which has to be a list can be used to define the argument list of the advised function. This argument list should of course be compatible with the argument list of the original function, otherwise functions that call the advised function with the original argument list in mind will break. If more than one advice specify an argument list then the first one (the one with the smallest position) found in the list of before/around/after advices will be used.
<flags> is a list of symbols that specify further information about the
advice. All flags can be specified with unambiguous initial substrings.
activate: Specifies that the advice information of the advised
function should be activated right after this advice has been
defined. In forward advices activate will be ignored.
protect: Specifies that this advice should be protected against
non-local exits and errors in preceding code/advices.
compile: Specifies that the advised function should be byte-compiled.
This flag will be ignored unless activate is also specified.
disable: Specifies that the defined advice should be disabled, hence,
it will not be used in an activation until somebody enables it.
preactivate: Specifies that the advised function should get preactivated
at macro-expansion/compile time of this defadvice. This
generates a compiled advised definition according to the
current advice state which will be used during activation
if appropriate. Only use this if the defadvice gets
actually compiled.
An optional <documentation-string> can be supplied to document the advice.
On call of the documentation function it will be combined with the
documentation strings of the original function and other advices.
An optional <interactive-form> form can be supplied to change/add
interactive behavior of the original function. If more than one advice
has an (interactive ...) specification then the first one (the one
with the smallest position) found in the list of before/around/after
advices will be used.
A possibly empty list of <body-forms> specifies the body of the advice in an implicit progn. The body of an advice can access/change arguments, the return value, the binding environment, and can have all sorts of other side effects.
@@ Assembling advised definitions:
==================================
Suppose a function/macro/subr/special-form has N pieces of before advice,
M pieces of around advice and K pieces of after advice. Assuming none of
the advices is protected, its advised definition will look like this
(body-form indices correspond to the position of the respective advice in
that advice class):
([macro] lambda <arglist>
[ [<advised-docstring>] [(interactive ...)] ]
(let (ad-return-value)
{<before-0-body-form>}*
....
{<before-N-1-body-form>}*
{<around-0-body-form>}*
{<around-1-body-form>}*
....
{<around-M-1-body-form>}*
(setq ad-return-value
<apply original definition to <arglist>>)
{<other-around-M-1-body-form>}*
....
{<other-around-1-body-form>}*
{<other-around-0-body-form>}*
{<after-0-body-form>}*
....
{<after-K-1-body-form>}*
ad-return-value))
Macros are redefined as macros, hence the optional [macro] in the beginning of the definition.
<arglist> is either the argument list of the original function or the
first argument list defined in the list of before/around/after advices.
The values of <arglist> variables can be accessed/changed in the body of
an advice by simply referring to them by their original name, however,
more portable argument access macros are also provided (see below).
<advised-docstring> is an optional, special documentation string which will
be expanded into a proper documentation string upon call of documentation.
(interactive ...) is an optional interactive form either taken from the
original function or from a before/around/after advice. For advised
interactive subrs that do not have an interactive form specified in any
advice we have to use (interactive) and then call the subr interactively
if the advised function was called interactively, because the
interactive specification of subrs is not accessible. This is the only
case where changing the values of arguments will not have an affect
because they will be reset by the interactive specification of the subr.
If this is a problem one can always specify an interactive form in a
before/around/after advice to gain control over argument values that
were supplied interactively.
Then the body forms of the various advices in the various classes of advice
are assembled in order. The forms of around advice L are normally part of
one of the forms of around advice L-1. An around advice can specify where
the forms of the wrapped or surrounded forms should go with the special
keyword ad-do-it, which will run the forms of the surrounded code.
The innermost part of the around advice onion is
<apply original definition to <arglist>>
whose form depends on the type of the original function. The variable
ad-return-value will be set to its result. This variable is visible to
all pieces of advice which can access and modify it before it gets returned.
The semantic structure of advised functions that contain protected pieces
of advice is the same. The only difference is that unwind-protect forms
make sure that the protected advice gets executed even if some previous
piece of advice had an error or a non-local exit. If any around advice is
protected then the whole around advice onion will be protected.
@@ Argument access in advised functions:
========================================
As already mentioned, the simplest way to access the arguments of an
advised function in the body of an advice is to refer to them by name.
To do that, the advice programmer needs to know either the names of the
argument variables of the original function, or the names used in the
argument list redefinition given in a piece of advice. While this simple
method might be sufficient in many cases, it has the disadvantage that it
is not very portable because it hardcodes the argument names into the
advice. If the definition of the original function changes the advice
might break even though the code might still be correct. Situations like
that arise, for example, if one advises a subr like eval-region which
gets redefined in a non-advice style into a function by the edebug
package. If the advice assumes eval-region to be a subr it might break
once edebug is loaded. Similar situations arise when one wants to use the
same piece of advice across different versions of Emacs.
As a solution to that advice provides argument list access macros that get translated into the proper access forms at activation time, i.e., when the advised definition gets constructed. Access macros access actual arguments by position regardless of how these actual argument get distributed onto the argument variables of a function. The rational behind this is that in Emacs Lisp the semantics of an argument is strictly determined by its position (there are no keyword arguments).
Suppose the function foo is defined as
(defun foo (x y &optional z &rest r) ....)
and is then called with
(foo 0 1 2 3 4 5 6)
which means that X=0, Y=1, Z=2 and R=(3 4 5 6). The assumption is that the semantics of an actual argument is determined by its position. It is this semantics that has to be known by the advice programmer. Then s/he can access these arguments in a piece of advice with some of the following macros (the arrows indicate what value they will return):
(ad-get-arg 0) -> 0
(ad-get-arg 1) -> 1
(ad-get-arg 2) -> 2
(ad-get-arg 3) -> 3
(ad-get-args 2) -> (2 3 4 5 6)
(ad-get-args 4) -> (4 5 6)
(ad-get-arg <position>) will return the actual argument that was supplied
at <position>, (ad-get-args <position>) will return the list of actual
arguments supplied starting at <position>. Note that these macros can be
used without any knowledge about the form of the actual argument list of
the original function.
Similarly, (ad-set-arg <position> <value-form>) can be used to set the
value of the actual argument at <position> to <value-form>. For example,
(ad-set-arg 5 "five")
will have the effect that R=(3 4 "five" 6) once the original function is
called. (ad-set-args <position> <value-list-form>) can be used to set
the list of actual arguments starting at <position> to <value-list-form>.
For example,
(ad-set-args 0 '(5 4 3 2 1 0))
will have the effect that X=5, Y=4, Z=3 and R=(2 1 0) once the original function is called.
All these access macros are text macros rather than real Lisp macros. When the advised definition gets constructed they get replaced with actual access forms depending on the argument list of the advised function, i.e., after that argument access is in most cases as efficient as using the argument variable names directly.
@@@ Accessing argument bindings of arbitrary functions:
=======================================================
Some functions (such as trace-function defined in trace.el) need a
method of accessing the names and bindings of the arguments of an
arbitrary advised function. To do that within an advice one can use the
special keyword ad-arg-bindings which is a text macro that will be
substituted with a form that will evaluate to a list of binding
specifications, one for every argument variable. These binding
specifications can then be examined in the body of the advice. For
example, somewhere in an advice we could do this:
(let* ((bindings ad-arg-bindings)
(firstarg (car bindings))
(secondarg (car (cdr bindings))))
;; Print info about first argument
(print (format "%s=%s (%s)"
(ad-arg-binding-field firstarg 'name)
(ad-arg-binding-field firstarg 'value)
(ad-arg-binding-field firstarg 'type)))
....)
The type of an argument is either required, optional or rest.
Wherever ad-arg-bindings appears a form will be inserted that evaluates
to the list of bindings, hence, in order to avoid multiple unnecessary
evaluations one should always bind it to some variable.
@@@ Argument list mapping:
==========================
Because defadvice allows the specification of the argument list
of the advised function we need a mapping mechanism that maps this
argument list onto that of the original function. Hence SYM and
NEWDEF have to be properly mapped onto the &rest variable when the
original definition is called. Advice automatically takes care of
that mapping, hence, the advice programmer can specify an argument
list without having to know about the exact structure of the
original argument list as long as the new argument list takes a
compatible number/magnitude of actual arguments.
@@ Activation and deactivation:
===============================
The definition of an advised function does not change until all its advice
gets actually activated. Activation can either happen with the activate
flag specified in the defadvice, with an explicit call or interactive
invocation of ad-activate, or at the time an already advised function
gets defined.
When a function gets first activated its original definition gets saved, all defined and enabled pieces of advice will get combined with the original definition, the resulting definition might get compiled depending on some conditions described below, and then the function will get redefined with the advised definition. This also means that undefined functions cannot get activated even though they might be already advised.
The advised definition will get compiled either if ad-activate was called
interactively with a prefix argument, or called explicitly with its second
argument as t, or, if ad-default-compilation-action justifies it according
to the current system state. If the advised definition was
constructed during "preactivation" (see below) then that definition will
be already compiled because it was constructed during byte-compilation of
the file that contained the defadvice with the preactivate flag.
ad-deactivate can be used to back-define an advised function to its
original definition. It can be called interactively or directly. Because
ad-activate caches the advised definition the function can be
reactivated via ad-activate with only minor overhead (it is checked
whether the current advice state is consistent with the cached
definition, see the section on caching below).
ad-activate-regexp and ad-deactivate-regexp can be used to de/activate
all currently advised function that have a piece of advice with a name that
contains a match for a regular expression. These functions can be used to
de/activate sets of functions depending on certain advice naming
conventions.
Finally, ad-activate-all and ad-deactivate-all can be used to
de/activate all currently advised functions. These are useful to
(temporarily) return to an un/advised state.
@@@ Reasons for the separation of advice definition and activation:
===================================================================
As already mentioned, advising happens in two stages:
1) definition of various pieces of advice
2) activation of all advice currently defined and enabled
The advantage of this is that various pieces of advice can be defined
before they get combined into an advised definition which avoids
unnecessary constructions of intermediate advised definitions. The more
important advantage is that it allows the implementation of forward advice.
Advice information for a certain function accumulates as the value of the
advice-info property of the function symbol. This accumulation is
completely independent of the fact that the function might not yet be
defined. The macros defun and defmacro check whether the
function/macro they defined had advice information
associated with it. If so and forward advice is enabled, the original
definition will be saved, and then the advice will be activated.
@@ Enabling/disabling pieces or sets of advice:
===============================================
A major motivation for the development of this advice package was to bring
a little bit more structure into the function overloading chaos in Emacs
Lisp. Many packages achieve some of their functionality by adding a little
bit (or a lot) to the standard functionality of some Emacs Lisp function.
ange-ftp is a very popular package that used to achieve its magic by
overloading most Emacs Lisp functions that deal with files. A popular
function that's overloaded by many packages is expand-file-name.
The situation that one function is multiply overloaded can arise easily.
Once in a while it would be desirable to be able to disable some/all overloads of a particular package while keeping all the rest. Ideally - at least in my opinion - these overloads would all be done with advice, I know I am dreaming right now... In that ideal case the enable/disable mechanism of advice could be used to achieve just that.
Every piece of advice is associated with an enablement flag. When the advised definition of a particular function gets constructed (e.g., during activation) only the currently enabled pieces of advice will be considered. This mechanism allows one to have different "views" of an advised function dependent on what pieces of advice are currently enabled.
Another motivation for this mechanism is that it allows one to define a piece of advice for some function yet keep it dormant until a certain condition is met. Until then activation of the function will not make use of that piece of advice. Once the condition is met the advice can be enabled and a reactivation of the function will add its functionality as part of the new advised definition. Hence, if somebody else advised these functions too and activates them the advices defined by advice will get used only if they are intended to be used.
The main interface to this mechanism are the interactive functions
ad-enable-advice and ad-disable-advice. For example, the following
would disable a particular advice of the function foo:
(ad-disable-advice 'foo 'before 'my-advice)
This call by itself only changes the flag, to get the proper effect in
the advised definition too one has to activate foo with
(ad-activate 'foo)
or interactively. To disable whole sets of advices one can use a regular
expression mechanism. For example, let us assume that ange-ftp actually
used advice to overload all its functions, and that it used the
"ange-ftp-" prefix for all its advice names, then we could temporarily
disable all its advices with
(ad-disable-regexp "\\\\`ange-ftp-")
and the following call would put that actually into effect:
(ad-activate-regexp "\\\\`ange-ftp-")
A safer way would have been to use
(ad-update-regexp "\\\\`ange-ftp-")
instead which would have only reactivated currently actively advised functions, but not functions that were currently inactive. All these functions can also be called interactively.
A certain piece of advice is considered a match if its name contains a
match for the regular expression. To enable ange-ftp again we would use
ad-enable-regexp and then activate or update again.
@@ Forward advice, automatic advice activation:
===============================================
Because most Emacs Lisp packages are loaded on demand via an autoload
mechanism it is essential to be able to "forward advise" functions.
Otherwise, proper advice definition and activation would make it necessary
to preload every file that defines a certain function before it can be
advised, which would partly defeat the purpose of the advice mechanism.
In the following, "forward advice" always implies its automatic activation once a function gets defined, and not just the accumulation of advice information for a possibly undefined function.
Advice implements forward advice mainly via the following: 1) Separation
of advice definition and activation that makes it possible to accumulate
advice information without having the original function already defined,
2) Use of the defalias-fset-function symbol property which lets
us advise the function when it gets defined.
Automatic advice activation means, that whenever a function gets defined
with either defun, defmacro, defalias or by loading a byte-compiled
file, and the function has some advice-info stored with it then that
advice will get activated right away.
@@ Caching of advised definitions:
==================================
After an advised definition got constructed it gets cached as part of the
advised function's advice-info so it can be reused, for example, after an
intermediate deactivation. Because the advice-info of a function might
change between the time of caching and reuse a cached definition gets
a cache-id associated with it so it can be verified whether the cached
definition is still valid (the main application of this is preactivation
- see below).
When an advised function gets activated and a verifiable cached definition
is available, then that definition will be used instead of creating a new
advised definition from scratch. If you want to make sure that a new
definition gets constructed then you should use ad-clear-cache before you
activate the advised function.
@@ Preactivation:
=================
Constructing an advised definition is moderately expensive. In a situation
where one package defines a lot of advised functions it might be
prohibitively expensive to do all the advised definition construction at
runtime. Preactivation is a mechanism that allows compile-time construction
of compiled advised definitions that can be activated cheaply during
runtime. Preactivation uses the caching mechanism to do that. Here's how
it works:
When the byte-compiler compiles a defadvice that has the preactivate
flag specified, it uses the current original definition of the advised
function plus the advice specified in this defadvice (even if it is
specified as disabled) and all other currently enabled pieces of advice to
construct an advised definition and an identifying cache-id and makes them
part of the defadvice expansion which will then be compiled by the
byte-compiler.
When the file with the compiled, preactivating defadvice gets loaded the
precompiled advised definition will be cached on the advised function's
advice-info. When it gets activated (can be immediately on execution of the
defadvice or any time later) the cache-id gets checked against the
current state of advice and if it is verified the precompiled definition
will be used directly (the verification is pretty cheap). If it couldn't
get verified a new advised definition for that function will be built from
scratch, hence, the efficiency added by the preactivation mechanism does not
at all impair the flexibility of the advice mechanism.
MORAL: In order get all the efficiency out of preactivation the advice
state of an advised function at the time the file with the
preactivating defadvice gets byte-compiled should be exactly
the same as it will be when the advice of that function gets
actually activated. If it is not there is a high chance that the
cache-id will not match and hence a new advised definition will
have to be constructed at runtime.
Preactivation and forward advice do not contradict each other. It is
perfectly ok to load a file with a preactivating defadvice before the
original definition of the advised function is available. The constructed
advised definition will be used once the original function gets defined and
its advice gets activated. The only constraint is that at the time the
file with the preactivating defadvice got compiled the original function
definition was available.
TIPS: Here are some indications that a preactivation did not work the way
you intended it to work:
- Activation of the advised function takes longer than usual/expected
- The byte-compiler gets loaded while an advised function gets
activated
- byte-compile is part of the features variable even though you
did not use the byte-compiler
Right now advice does not provide an elegant way to find out whether
and why a preactivation failed. What you can do is to trace the
function ad-cache-id-verification-code (with the function
trace-function-background defined in my trace.el package) before
any of your advised functions get activated. After they got
activated check whether all calls to ad-cache-id-verification-code
returned verified as a result. Other values indicate why the
verification failed which should give you enough information to
fix your preactivation/compile/load/activation sequence.
IMPORTANT: There is one case (that I am aware of) that can make
preactivation fail, i.e., a preconstructed advised definition that does
NOT match the current state of advice gets used nevertheless. That case
arises if one package defines a certain piece of advice which gets used
during preactivation, and another package incompatibly redefines that
very advice (i.e., same function/class/name), and it is the second advice
that is available when the preconstructed definition gets activated, and
that was the only definition of that advice so far (ad-add-advice
catches advice redefinitions and clears the cache in such a case).
Catching that would make the cache verification too expensive.
MORAL-II: Redefining somebody else's advice is BAAAAD (to speak with George Walker Bush), and why would you redefine your own advice anyway? Advice is a mechanism to facilitate function redefinition, not advice redefinition (wait until I write Meta-Advice :-). If you really have to undo somebody else's advice, try to write a "neutralizing" advice.
@@ Advising macros and other dangerous things:
==============================================
Look at the corresponding tutorial sections for more information on
these topics. Here it suffices to point out that the special treatment
of macros can lead to problems when they get advised. Macros can create
problems because they get expanded at compile or load time, hence, they
might not have all the necessary runtime support and such advice cannot be
de/activated or changed as it is possible for functions.
Special forms cannot be advised.
MORAL: - Only advise macros when you are absolutely sure what you are doing.
@@ Adding a piece of advice with ad-add-advice:
=================================================
The non-interactive function ad-add-advice can be used to add a piece of
advice to some function without using defadvice. This is useful if advice
has to be added somewhere by a function (also look at ad-make-advice).
@@ Activation/deactivation advices, file load hooks:
====================================================
There are two special classes of advice called activation and
deactivation. The body forms of these advices are not included into the
advised definition of a function, rather they are assembled into a hook
form which will be evaluated whenever the advice-info of the advised
function gets activated or deactivated. One application of this mechanism
is to define file load hooks for files that do not provide such hooks.
For example, suppose you want to print a message whenever file-x gets
loaded, and suppose the last function defined in file-x is
file-x-last-fn. Then we can define the following advice:
(defadvice file-x-last-fn (activation file-x-load-hook)
"Executed whenever file-x is loaded"
(if load-in-progress (message "Loaded file-x")))
This will constitute a forward advice for function file-x-last-fn which
will get activated when file-x is loaded (only if forward advice is
enabled of course). Because there are no "real" pieces of advice
available for it, its definition will not be changed, but the activation
advice will be run during its activation which is equivalent to having a
file load hook for file-x.
@@ Summary of main advice concepts:
===================================
- Definition:
A piece of advice gets defined with defadvice and added to the
advice-info property of a function.
- Enablement:
Every piece of advice has an enablement flag associated with it. Only
enabled advices are considered during construction of an advised
definition.
- Activation:
Redefine an advised function with its advised definition. Constructs
an advised definition from scratch if no verifiable cached advised
definition is available and caches it.
- Deactivation:
Back-define an advised function to its original definition.
- Update:
Reactivate an advised function but only if its advice is currently
active. This can be used to bring all currently advised function up
to date with the current state of advice without also activating
currently inactive functions.
- Caching:
Is the saving of an advised definition and an identifying cache-id so
it can be reused, for example, for activation after deactivation.
- Preactivation:
Is the construction of an advised definition according to the current
state of advice during byte-compilation of a file with a preactivating
defadvice. That advised definition can then rather cheaply be used
during activation without having to construct an advised definition
from scratch at runtime.
@@ Summary of interactive advice manipulation functions:
========================================================
The following interactive functions can be used to manipulate the state
of advised functions (all of them support completion on function names,
advice classes and advice names):
- ad-activate to activate the advice of a FUNCTION
- ad-deactivate to deactivate the advice of a FUNCTION
- ad-update to activate the advice of a FUNCTION unless it was not
yet activated or is currently inactive.
- ad-unadvise deactivates a FUNCTION and removes all of its advice
information, hence, it cannot be activated again
- ad-recover tries to redefine a FUNCTION to its original definition and
discards all advice information (a low-level ad-unadvise).
Use only in emergencies.
- ad-remove-advice removes a particular piece of advice of a FUNCTION.
You still have to do call ad-activate or ad-update to
activate the new state of advice.
- ad-enable-advice enables a particular piece of advice of a FUNCTION.
- ad-disable-advice disables a particular piece of advice of a FUNCTION.
- ad-enable-regexp maps over all currently advised functions and enables
every advice whose name contains a match for a regular
expression.
- ad-disable-regexp disables matching advices.
- ad-activate-regexp activates all advised function with a matching advice
- ad-deactivate-regexp deactivates all advised function with matching advice
- ad-update-regexp updates all advised function with a matching advice
- ad-activate-all activates all advised functions
- ad-deactivate-all deactivates all advised functions
- ad-update-all updates all advised functions
- ad-unadvise-all unadvises all advised functions
- ad-recover-all recovers all advised functions
- ad-compile byte-compiles a function/macro if it is compilable.
@@ Summary of forms with special meanings when used within an advice:
=====================================================================
ad-return-value name of the return value variable (get/settable)
(ad-get-arg <pos>), (ad-get-args <pos>),
(ad-set-arg <pos> <value>), (ad-set-args <pos> <value-list>)
argument access text macros to get/set the values of
actual arguments at a certain position
ad-arg-bindings text macro that returns the actual names, values
and types of the arguments as a list of bindings. The
order of the bindings corresponds to the order of the
arguments. The individual fields of every binding (name,
value and type) can be accessed with the function
ad-arg-binding-field (see example above).
ad-do-it text macro that identifies the place where the original
or wrapped definition should go in an around advice
@ Foo games: An advice tutorial
===============================
The following tutorial was created in Emacs 18.59. Left-justified
s-expressions are input forms followed by one or more result forms.
We start by defining an innocent looking function foo that simply
adds 1 to its argument X:
(defun foo (x)
"Add 1 to X."
(1+ x))
foo
(foo 3)
4
@@ Defining a simple piece of advice:
=====================================
Now let's define the first piece of advice for foo. To do that we
use the macro defadvice which takes a function name, a list of advice
specifiers and a list of body forms as arguments. The first element of
the advice specifiers is the class of the advice, the second is its name,
the third its position and the rest are some flags. The class of our
first advice is before, its name is fg-add2, its position among the
currently defined before advices (none so far) is first, and the advice
will be activateed immediately. Advice names are global symbols, hence,
the name space conventions used for function names should be applied. All
advice names in this tutorial will be prefixed with fg for Foo Games
(because everybody has the right to be inconsistent all the function names
used in this tutorial do NOT follow this convention).
In the body of an advice we can refer to the argument variables of the
original function by name. Here we add 1 to X so the effect of calling
foo will be to actually add 2. All of the advice definitions below only
have one body form for simplicity, but there is no restriction to that
extent. Every piece of advice can have a documentation string which will
be combined with the documentation of the original function.
(defadvice foo (before fg-add2 first activate)
"Add 2 to X."
(setq x (1+ x)))
foo
(foo 3)
5
@@ Specifying the position of an advice:
========================================
Now we define the second before advice which will cancel the effect of
the previous advice. This time we specify the position as 0 which is
equivalent to first. A number can be used to specify the zero-based
position of an advice among the list of advices in the same class. This
time we already have one before advice hence the position specification
actually has an effect. So, after the following definition the position
of the previous advice will be 1 even though we specified it with first
above, the reason for this is that the position argument is relative to
the currently defined pieces of advice which by now has changed.
(defadvice foo (before fg-cancel-add2 0 activate)
"Again only add 1 to X."
(setq x (1- x)))
foo
(foo 3)
4
@@ Redefining a piece of advice:
================================
Now we define an advice with the same class and same name but with a
different position. Defining an advice in a class in which an advice with
that name already exists is interpreted as a redefinition of that
particular advice, in which case the position argument will be ignored
and the previous position of the redefined piece of advice is used.
Advice flags can be specified with non-ambiguous initial substrings, hence,
from now on we'll use act instead of the verbose activate.
(defadvice foo (before fg-cancel-add2 last act)
"Again only add 1 to X."
(setq x (1- x)))
foo
@@ Assembly of advised documentation:
=====================================
The documentation strings of the various pieces of advice are assembled
in order which shows that advice fg-cancel-add2 is still the first
before advice even though we specified position last above:
(documentation 'foo)
"Add 1 to X.
This function is advised with the following advice(s):
fg-cancel-add2 (before): Again only add 1 to X.
fg-add2 (before): Add 2 to X."
@@ Advising interactive behavior:
=================================
We can make a function interactive (or change its interactive behavior)
by specifying an interactive form in one of the before or around
advices (there could also be body forms in this advice). The particular
definition always assigns 5 as an argument to X which gives us 6 as a
result when we call foo interactively:
(defadvice foo (before fg-inter last act)
"Use 5 as argument when called interactively."
(interactive (list 5)))
foo
(call-interactively 'foo)
6
If more than one advice have an interactive declaration, then the one of the advice with the smallest position will be used (before advices go before around and after advices), hence, the declaration below does not have any effect:
(defadvice foo (before fg-inter2 last act)
(interactive (list 6)))
foo
(call-interactively 'foo)
6
@@ Around advices:
==================
Now we'll try some around advices. An around advice is a wrapper around
the original definition. It can shadow or establish bindings for the
original definition, and it can look at and manipulate the value returned
by the original function. The position of the special keyword ad-do-it
specifies where the code of the original function will be executed. The
keyword can appear multiple times which will result in multiple calls of
the original function in the resulting advised code. Note, that if we don't
specify a position argument (i.e., first, last or a number), then
first (or 0) is the default):
(defadvice foo (around fg-times-2 act)
"First double X."
(let ((x (* x 2)))
ad-do-it))
foo
(foo 3)
7
Around advices are assembled like onion skins where the around advice
with position 0 is the outermost skin and the advice at the last position
is the innermost skin which is directly wrapped around the call of the
original definition of the function. Hence, after the next defadvice we
will first multiply X by 2 then add 1 and then call the original
definition (i.e., add 1 again):
(defadvice foo (around fg-add-1 last act)
"Add 1 to X."
(let ((x (1+ x)))
ad-do-it))
foo
(foo 3)
8
@@ Controlling advice activation:
=================================
In every defadvice so far we have used the flag activate to activate
the advice immediately after its definition, and that's what we want in
most cases. However, if we define multiple pieces of advice for a single
function then activating every advice immediately is inefficient. A
better way to do this is to only activate the last defined advice.
For example:
(defadvice foo (after fg-times-x)
"Multiply the result with X."
(setq ad-return-value (* ad-return-value x)))
foo
This still yields the same result as before:
(foo 3)
8
Now we define another advice and activate which will also activate the
previous advice fg-times-x. Note the use of the special variable
ad-return-value in the body of the advice which is set to the result of
the original function. If we change its value then the value returned by
the advised function will be changed accordingly:
(defadvice foo (after fg-times-x-again act)
"Again multiply the result with X."
(setq ad-return-value (* ad-return-value x)))
foo
Now the advices have an effect:
(foo 3)
72
@@ Protecting advice execution:
===============================
Once in a while we define an advice to perform some cleanup action,
for example:
(defadvice foo (after fg-cleanup last act)
"Do some cleanup."
(print "Let's clean up now!"))
foo
However, in case of an error the cleanup won't be performed:
(condition-case error
(foo t)
(error 'error-in-foo))
error-in-foo
To make sure a certain piece of advice gets executed even if some error or
non-local exit occurred in any preceding code, we can protect it by using
the protect keyword (if any of the around advices is protected then the
whole around advice onion will be protected):
(defadvice foo (after fg-cleanup prot act)
"Do some protected cleanup."
(print "Let's clean up now!"))
foo
Now the cleanup form will be executed even in case of an error:
(condition-case error
(foo t)
(error 'error-in-foo))
"Let's clean up now!"
error-in-foo
@@ Compilation of advised definitions:
======================================
Finally, we can specify the compile keyword in a defadvice to say
that we want the resulting advised function to be byte-compiled
(compile will be ignored unless we also specified activate):
(defadvice foo (after fg-cleanup prot act comp)
"Do some protected cleanup."
(print "Let's clean up now!"))
foo
Now foos advice is byte-compiled:
(byte-code-function-p 'ad-Advice-foo)
t
(foo 3)
"Let's clean up now!"
72
@@ Enabling and disabling pieces of advice:
===========================================
Once in a while it is desirable to temporarily disable a piece of advice
so that it won't be considered during activation, for example, if two
different packages advise the same function and one wants to temporarily
neutralize the effect of the advice of one of the packages.
The following disables the after advice fg-times-x in the function foo.
All that does is to change a flag for this particular advice. All the
other information defining it will be left unchanged (e.g., its relative
position in this advice class, etc.).
(ad-disable-advice 'foo 'after 'fg-times-x)
nil
For this to have an effect we have to activate foo:
(ad-activate 'foo)
foo
(foo 3)
"Let's clean up now!"
24
If we want to disable all multiplication advices in foo we can use a
regular expression that matches the names of such advices. Actually, any
advice name that contains a match for the regular expression will be
called a match. A special advice class any can be used to consider
all advice classes:
(ad-disable-advice 'foo 'any "^fg-.*times")
nil
(ad-activate 'foo)
foo
(foo 3)
"Let's clean up now!"
5
To enable the disabled advice we could use either ad-enable-advice
similar to ad-disable-advice, or as an alternative ad-enable-regexp
which will enable matching advices in ALL currently advised functions.
Hence, this can be used to dis/enable advices made by a particular
package to a set of functions as long as that package obeys standard
advice name conventions. We prefixed all advice names with fg-, hence
the following will do the trick (ad-enable-regexp returns the number
of matched advices):
(ad-enable-regexp "^fg-")
9
The following will activate all currently active advised functions that contain some advice matched by the regular expression. This is a save way to update the activation of advised functions whose advice changed in some way or other without accidentally also activating currently inactive functions:
(ad-update-regexp "^fg-")
nil
(foo 3)
"Let's clean up now!"
72
Another use for the dis/enablement mechanism is to define a piece of advice
and keep it "dormant" until a particular condition is satisfied, i.e., until
then the advice will not be used during activation. The disable flag lets
one do that with defadvice:
(defadvice foo (before fg-1-more dis)
"Add yet 1 more."
(setq x (1+ x)))
foo
(ad-activate 'foo)
foo
(foo 3)
"Let's clean up now!"
72
(ad-enable-advice 'foo 'before 'fg-1-more)
nil
(ad-activate 'foo)
foo
(foo 3)
"Let's clean up now!"
160
@@ Caching:
===========
Advised definitions get cached to allow efficient activation/deactivation
without having to reconstruct them if nothing in the advice-info of a
function has changed. The following idiom can be used to temporarily
deactivate functions that have a piece of advice defined by a certain
package (we save the old definition to check out caching):
(setq old-definition (symbol-function 'ad-Advice-foo))
(lambda (x) ....)
(ad-deactivate-regexp "^fg-")
nil
(foo 3)
4
(ad-activate-regexp "^fg-")
nil
(eq old-definition (symbol-function 'ad-Advice-foo))
t
(foo 3)
"Let's clean up now!"
160
@@ Forward advice:
==================
Let's define a piece of advice for an undefined function:
(defadvice bar (before fg-sub-1-more act)
"Subtract one more from X."
(setq x (1- x)))
bar
bar is not yet defined:
(fboundp 'bar)
nil
Now we define it and the forward advice will get activated:
(defun bar (x)
"Subtract 1 from X."
(1- x))
bar
(bar 4)
2
Redefinition will activate any available advice if the value of
ad-redefinition-action is either warn, accept or discard:
(defun bar (x)
"Subtract 2 from X."
(- x 2))
bar
(bar 4)
1
@@ Preactivation:
=================
Constructing advised definitions is moderately expensive, hence, it is
desirable to have a way to construct them at byte-compile time.
Preactivation is a mechanism that allows one to do that.
(defun fie (x)
"Multiply X by 2."
(* x 2))
fie
(defadvice fie (before fg-times-4 preact)
"Multiply X by 4."
(setq x (* x 2)))
fie
This advice did not affect fie...
(fie 2)
4
...but it constructed a cached definition that will be used once fie gets
activated as long as its current advice state is the same as it was during
preactivation:
(setq cached-definition (ad-get-cache-definition 'fie))
(lambda (x) ....)
(ad-activate 'fie)
fie
(eq cached-definition (symbol-function 'ad-Advice-fie))
t
(fie 2)
8
If you put a preactivating defadvice into a Lisp file that gets byte-
compiled then the constructed advised definition will get compiled by
the byte-compiler. For that to occur in a v18 Emacs you had to put the
defadvice inside a defun because the v18 compiler did not compile
top-level forms other than defun or defmacro, for example,
(defun fg-defadvice-fum ()
(defadvice fum (before fg-times-4 preact act)
"Multiply X by 4."
(setq x (* x 2))))
fg-defadvice-fum
So far, no defadvice for fum got executed, but when we compile
fg-defadvice-fum the defadvice will be expanded by the byte compiler.
In order for preactivation to be effective we have to have a proper
definition of fum around at preactivation time, hence, we define it now:
(defun fum (x)
"Multiply X by 2."
(* x 2))
fum
Now we compile the defining function which will construct an advised
definition during expansion of the defadvice, compile it and store it
as part of the compiled fg-defadvice-fum:
(ad-compile-function 'fg-defadvice-fum)
(lambda nil (byte-code ...))
fum is still completely unaffected:
(fum 2)
4
(ad-get-advice-info 'fum)
nil
(fg-defadvice-fum)
fum
Now the advised version of fum is compiled because the compiled definition
constructed during preactivation was used, even though we did not specify
the compile flag:
(byte-code-function-p 'ad-Advice-fum)
t
(fum 2)
8
A preactivated definition will only be used if it matches the current
function definition and advice information. If it does not match it
will simply be discarded and a new advised definition will be constructed
from scratch. For example, let's first remove all advice-info for fum:
(ad-unadvise 'fum)
(("fie") ("bar") ("foo") ...)
And now define a new piece of advice:
(defadvice fum (before fg-interactive act)
"Make fum interactive."
(interactive "nEnter x: "))
fum
When we now try to use a preactivation it will not be used because the current advice state is different from the one at preactivation time. This is no tragedy, everything will work as expected just not as efficient, because a new advised definition has to be constructed from scratch:
(fg-defadvice-fum)
fum
A new uncompiled advised definition got constructed:
(byte-code-function-p 'ad-Advice-fum)
nil
(fum 2)
8
MORAL: To get all the efficiency out of preactivation the function
definition and advice state at preactivation time must be the same as the
state at activation time. Preactivation does work with forward advice, all
that's necessary is that the definition of the forward advised function is
available when the defadvice with the preactivation gets compiled.
@@ Portable argument access:
============================
So far, we always used the actual argument variable names to access an
argument in a piece of advice. For many advice applications this is
perfectly ok and keeps advices simple. However, it decreases portability
of advices because it assumes specific argument variable names. For example,
if one advises a subr such as eval-region which then gets redefined by
some package (e.g., edebug) into a function with different argument names,
then a piece of advice written for eval-region that was written with
the subr arguments in mind will break.
Argument access text macros allow one to access arguments of an advised function in a portable way without having to worry about all these possibilities. These macros will be translated into the proper access forms at activation time, hence, argument access will be as efficient as if the arguments had been used directly in the definition of the advice.
(defun fuu (x y z)
"Add 3 numbers."
(+ x y z))
fuu
(fuu 1 1 1)
3
Argument access macros specify actual arguments at a certain position. Position 0 access the first actual argument, position 1 the second etc. For example, the following advice adds 1 to each of the 3 arguments:
(defadvice fuu (before fg-add-1-to-all act)
"Adds 1 to all arguments."
(ad-set-arg 0 (1+ (ad-get-arg 0)))
(ad-set-arg 1 (1+ (ad-get-arg 1)))
(ad-set-arg 2 (1+ (ad-get-arg 2))))
fuu
(fuu 1 1 1)
6
Now suppose somebody redefines fuu with a rest argument. Our advice
will still work because we used access macros (note, that automatic
advice activation is still in effect, hence, the redefinition of fuu
will automatically activate all its advice):
(defun fuu (&rest numbers)
"Add NUMBERS."
(apply '+ numbers))
fuu
(fuu 1 1 1)
6
(fuu 1 1 1 1 1 1)
9
What's important to notice is that argument access macros access actual arguments regardless of how they got distributed onto argument variables. In Emacs Lisp the semantics of an actual argument is determined purely by position, hence, as long as nobody changes the semantics of what a certain actual argument at a certain position means the access macros will do the right thing.
Because of &rest arguments we need a second kind of access macro that can access all actual arguments starting from a certain position:
(defadvice fuu (before fg-print-args act)
"Print all arguments."
(print (ad-get-args 0)))
fuu
(fuu 1 2 3 4 5)
(1 2 3 4 5)
18
(defadvice fuu (before fg-set-args act)
"Swaps 2nd and 3rd arg and discards all the rest."
(ad-set-args 1 (list (ad-get-arg 2) (ad-get-arg 1))))
fuu
(fuu 1 2 3 4 4 4 4 4 4)
(1 3 2)
9
(defun fuu (x y z)
"Add 3 numbers."
(+ x y z))
(fuu 1 2 3)
(1 3 2)
9
@@ Defining the argument list of an advised function:
=====================================================
Once in a while it might be desirable to advise a function and additionally
give it an extra argument that controls the advised code, for example, one
might want to make an interactive function sensitive to a prefix argument.
For such cases defadvice allows the specification of an argument list
for the advised function. Similar to the redefinition of interactive
behavior, the first argument list specification found in the list of before/
around/after advices will be used. Of course, the specified argument list
should be downward compatible with the original argument list, otherwise
functions that call the advised function with the original argument list
in mind will break.
(defun fii (x)
"Add 1 to X."
(1+ x))
fii
Now we advise fii to use an optional second argument that controls the
amount of incrementing. A list following the (optional) position
argument of the advice will be interpreted as an argument list
specification. This means you cannot specify an empty argument list, and
why would you want to anyway?
(defadvice fii (before fg-inc-x (x &optional incr) act)
"Increment X by INCR (default is 1)."
(setq x (+ x (1- (or incr 1)))))
fii
(fii 3)
4
(fii 3 2)
5
@@ Advising interactive subrs:
==============================
For the most part there is no difference between advising functions and
advising subrs. There is one situation though where one might have to write
slightly different advice code for subrs than for functions. This case
arises when one wants to access subr arguments in a before/around advice
when the arguments were determined by an interactive call to the subr.
Advice cannot determine what interactive form determines the interactive
behavior of the subr, hence, when it calls the original definition in an
interactive subr invocation it has to use call-interactively to generate
the proper interactive behavior. Thus up to that call the arguments of the
interactive subr will be nil. For example, the following advice for
kill-buffer will not work in an interactive invocation...
(defadvice kill-buffer (before fg-kill-buffer-hook first act preact comp)
(my-before-kill-buffer-hook (ad-get-arg 0)))
kill-buffer
...because the buffer argument will be nil in that case. The way out of
this dilemma is to provide an interactive specification that mirrors
the interactive behavior of the unadvised subr, for example, the following
will do the right thing even when kill-buffer is called interactively:
(defadvice kill-buffer (before fg-kill-buffer-hook first act preact comp)
(interactive "bKill buffer: ")
(my-before-kill-buffer-hook (ad-get-arg 0)))
kill-buffer
@@ Advising macros:
===================
Advising macros is slightly different because there are two significant
time points in the invocation of a macro: Expansion and evaluation time.
For an advised macro instead of evaluating the original definition we
use macroexpand, that is, changing argument values and binding
environments by pieces of advice has an affect during macro expansion
but not necessarily during evaluation. In particular, any side effects
of pieces of advice will occur during macro expansion. To also affect
the behavior during evaluation time one has to change the value of
ad-return-value in a piece of after advice. For example:
(defmacro foom (x)
(list ,x))
foom
(foom (a))
((a))
(defadvice foom (before fg-print-x act)
"Print the value of X."
(print x))
foom
The following works as expected because evaluation immediately follows macro expansion:
(foom '(a))
(quote (a))
((a))
However, the printing happens during expansion (or byte-compile) time:
(macroexpand '(foom '(a)))
(quote (a))
(list (quote (a)))
If we want it to happen during evaluation time we have to do the following (first remove the old advice):
(ad-remove-advice 'foom 'before 'fg-print-x)
nil
(defadvice foom (after fg-print-x act)
"Print the value of X."
(setq ad-return-value
(progn (print ,x)
,ad-return-value)))
foom
(macroexpand (foom '(a)))
(progn (print (quote (a))) (list (quote (a))))
(foom '(a))
(a)
((a))
While this method might seem somewhat cumbersome, it is very general because it allows one to influence macro expansion as well as evaluation. In general, advising macros should be a rather rare activity anyway, in particular, because compile-time macro expansion takes away a lot of the flexibility and effectiveness of the advice mechanism. Macros that were compile-time expanded before the advice was activated will of course never exhibit the advised behavior.
Defined variables (3)
ad-advice-classes | List of defined advice classes. |
ad-default-compilation-action | Defines whether to compile advised definitions during activation. |
ad-redefinition-action | Defines what to do with redefinitions during Advice de/activation. |