]> code.delx.au - gnu-emacs/blobdiff - lisp/emacs-lisp/advice.el
Merge from trunk.
[gnu-emacs] / lisp / emacs-lisp / advice.el
index 5934975e36a7349c7e4b89e22948fa92b3d2bc56..09dde2c1c17585a0c16d08fbe0652560ff13c739 100644 (file)
@@ -1,6 +1,6 @@
 ;;; advice.el --- an overloading mechanism for Emacs Lisp functions
 
-;; Copyright (C) 1993-1994, 2000-2011 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2000-2012 Free Software Foundation, Inc.
 
 ;; Author: Hans Chalupsky <hans@cs.buffalo.edu>
 ;; Maintainer: FSF
 ;; 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).  For
-;; subrs/special-forms for which neither explicit argument list definitions
-;; are available, nor their documentation strings contain such definitions
-;; (as they do v19s), `(&rest ad-subr-args)' will be used.
+;; 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'.
 
 ;; @@@ 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. For example, somebody might specify
-;; `(sym newdef)' as the argument list of `fset', while advice might use
-;; `(&rest ad-subr-args)' as the argument list of the original function
-;; (depending on what Emacs version is used). 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.
+;; 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:
 ;; ===============================
 ;;
 ;;    (ad-activate-regexp "^ange-ftp-")
 ;;
-;; A saver way would have been to use
+;; 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 deactivated. All these
+;; 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
 
 ;; @@@ Enabling automatic advice activation:
 ;; =========================================
-;; Automatic advice activation is enabled by default. It can be disabled by
-;; doint `M-x ad-stop-advice' and enabled again with `M-x ad-start-advice'.
+;; Automatic advice activation is enabled by default. It can be disabled with
+;; `M-x ad-stop-advice' and enabled again with `M-x ad-start-advice'.
 
 ;; @@ Caching of advised definitions:
 ;; ==================================
 ;;     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 deactivated functions.
+;;     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.
 ;; - 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 deactivated.
+;;               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
 ;; @@ Summary of forms with special meanings when used within an advice:
 ;; =====================================================================
 ;;   ad-return-value   name of the return value variable (get/settable)
-;;   ad-subr-args      name of &rest argument variable used for advised
-;;                     subrs whose actual argument list cannot be
-;;                     determined (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
 ;; 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
-;; deactivated functions:
+;; inactive functions:
 ;;
 ;; (ad-update-regexp "^fg-")
 ;; nil
 ;; fii
 ;;
 ;; Now we advise `fii' to use an optional second argument that controls the
-;; amount of incrementation. A list following the (optional) position
+;; 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?
@@ -2135,16 +2127,27 @@ Redefining advices affect the construction of an advised definition."
 ;; @@ Interactive input functions:
 ;; ===============================
 
+(declare-function 'function-called-at-point "help")
+
 (defun ad-read-advised-function (&optional prompt predicate default)
   "Read name of advised function with completion from the minibuffer.
 An optional PROMPT will be used to prompt for the function.  PREDICATE
 plays the same role as for `try-completion' (which see).  DEFAULT will
-be returned on empty input (defaults to the first advised function for
-which PREDICATE returns non-nil)."
+be returned on empty input (defaults to the first advised function or
+function at point for which PREDICATE returns non-nil)."
   (if (null ad-advised-functions)
       (error "ad-read-advised-function: There are no advised functions"))
   (setq default
        (or default
+           ;; Prefer func name at point, if it's in ad-advised-functions etc.
+           (let ((function (progn
+                             (require 'help)
+                             (function-called-at-point))))
+             (and function
+                  (assoc (symbol-name function) ad-advised-functions)
+                  (or (null predicate)
+                      (funcall predicate function))
+                  function))
            (ad-do-advised-functions (function)
              (if (or (null predicate)
                      (funcall predicate function))
@@ -2583,36 +2586,6 @@ For that it has to be fbound with a non-autoload definition."
         (byte-compile symbol)
         (fset function (symbol-function symbol))))))
 
-
-;; @@ Constructing advised definitions:
-;; ====================================
-;;
-;; Main design decisions about the form of advised definitions:
-;;
-;; A) How will original definitions be called?
-;; B) What will argument lists of advised functions look like?
-;;
-;; Ad A)
-;;    I chose to use function indirection for all four types of original
-;;    definitions (functions, macros, subrs and special forms), i.e., create
-;;    a unique symbol `ad-Orig-<name>' which is fbound to the original
-;;    definition and call it according to type and arguments.  Functions and
-;;    subrs that don't have any &rest arguments can be called directly in a
-;;    `(ad-Orig-<name> ....)' form.  If they have a &rest argument we have to
-;;    use `apply'.  Macros will be called with
-;;    `(macroexpand '(ad-Orig-<name> ....))', and special forms also need a
-;;    form like that with `eval' instead of `macroexpand'.
-;;
-;; Ad B)
-;;    Use original arguments where possible and `(&rest ad-subr-args)'
-;;    otherwise, even though this seems to be more complicated and less
-;;    uniform than a general `(&rest args)' approach.  My reason to still
-;;    do it that way is that in most cases my approach leads to the more
-;;    efficient form for the advised function, and portability (e.g., to
-;;    make the same advice work regardless of whether something is a
-;;    function or a subr) can still be achieved with argument access macros.
-
-
 (defun ad-prognify (forms)
   (cond ((<= (length forms) 1)
         (car forms))