elisp: Advising Functions

 
 12.11 Advising Emacs Lisp Functions
 ===================================
 
 When you need to modify a function defined in another library, or when
 you need to modify a hook like ‘FOO-function’, a process filter, or
 basically any variable or object field which holds a function value, you
 can use the appropriate setter function, such as ‘fset’ or ‘defun’ for
 named functions, ‘setq’ for hook variables, or ‘set-process-filter’ for
 process filters, but those are often too blunt, completely throwing away
 the previous value.
 
    The “advice” feature lets you add to the existing definition of a
 function, by “advising the function”.  This is a cleaner method than
 redefining the whole function.
 
    Emacs’s advice system provides two sets of primitives for that: the
 core set, for function values held in variables and object fields (with
 the corresponding primitives being ‘add-function’ and ‘remove-function’)
 and another set layered on top of it for named functions (with the main
 primitives being ‘advice-add’ and ‘advice-remove’).
 
    For example, in order to trace the calls to the process filter of a
 process PROC, you could use:
 
      (defun my-tracing-function (proc string)
        (message "Proc %S received %S" proc string))
 
      (add-function :before (process-filter PROC) #'my-tracing-function)
 
    This will cause the process’s output to be passed to
 ‘my-tracing-function’ before being passed to the original process
 filter.  ‘my-tracing-function’ receives the same arguments as the
 original function.  When you’re done with it, you can revert to the
 untraced behavior with:
 
      (remove-function (process-filter PROC) #'my-tracing-function)
 
    Similarly, if you want to trace the execution of the function named
 ‘display-buffer’, you could use:
 
      (defun his-tracing-function (orig-fun &rest args)
        (message "display-buffer called with args %S" args)
        (let ((res (apply orig-fun args)))
          (message "display-buffer returned %S" res)
          res))
 
      (advice-add 'display-buffer :around #'his-tracing-function)
 
    Here, ‘his-tracing-function’ is called instead of the original
 function and receives the original function (additionally to that
 function’s arguments) as argument, so it can call it if and when it
 needs to.  When you’re tired of seeing this output, you can revert to
 the untraced behavior with:
 
      (advice-remove 'display-buffer #'his-tracing-function)
 
    The arguments ‘:before’ and ‘:around’ used in the above examples
 specify how the two functions are composed, since there are many
 different ways to do it.  The added function is also called a piece of
 _advice_.
 

Menu