9

I had a look over the weekend, and I cannot see an easy way to check whether a function is advised.

I must be missing something.

HELP! :)

3
  • 6
    M-x describe-function aka C-h f
    – lawlist
    Commented Jan 8, 2018 at 17:47
  • 4
    advice-add/advice-remove updates function's documentation accordingly, thus C-h f works. From Lisp, take a look at advice-mapc and advice-member-p.
    – xuchunyang
    Commented Jan 8, 2018 at 18:15
  • 1
    I edited your question. 1. If you are not asking about one of the two aspects (interactive, from Lisp) then please delete that part. 2. It's not clear which advice system you are asking about, new (e.g. advice-add) or the old (e.g., defadvice).
    – Drew
    Commented Jan 8, 2018 at 19:16

2 Answers 2

12

As lawlist correctly points out in a comment, the Emacs Help system, invoked via C-hfNAMERET (M-xdescribe-functionRETNAMERET) in this case, is a quick way to interactively check whether there is any advice currently active on the function named NAME. This is doubly convenient because the name of the advising function is hyperlinked as a button, allowing you to jump to and back from its definition.

To programmatically determine whether the function definition of a particular symbol (e.g. fn) contains any advice[1], you can write:

(advice--p (advice--symbol-function 'fn))

Note, however, that the double hyphens indicate this is an internal API and thus subject to breaking change.

[1]: This assumes the new nadvice.el system in Emacs 24; see (elisp) Porting old advice.

5
  • I'm perpetually surprised by how many Emacs things seem to only have an interactive human-level solution and how even more common it is for answers to only mention those solutions - "here's how you as a human user can check/do this" - as if a human wanting to know/do a doesn't inherently imply that a human will eventually want to have their Elisp do it for them with an actually stable/public/guaranteed API. +1 anyway of course, I just see this pattern more with Emacs/Elisp than with other programming languages/frameworks.
    – mtraceur
    Commented May 18, 2023 at 2:23
  • @mtraceur Patches for improvements are always welcome upstream ;).
    – Basil
    Commented May 18, 2023 at 7:07
  • Saying what a community could do better is a patch for the cultural upstream. If we can get more developers to think "I'm doing something that's useful for a human -> it's probably useful as an API too" that leads to the far more efficient solution of the people who already know all the relevant knowledge making the patch instead of someone new having to first learn it all.
    – mtraceur
    Commented May 19, 2023 at 2:38
  • @mtraceur Agreed, but comments on a 3rd-party Q&A forum post are arguably also less efficient than having this discussion upstream: in the form of a concrete report / feature request, or ideally even patch :).
    – Basil
    Commented May 19, 2023 at 12:43
  • Good news everyone! I figured out how to get specific advice information, such as the where. See my answer. That'll have to be the extent of my contribution for quite some time - I'm not sure when I'll get around to actually proposing that as a patch, but at least now we know more of what that patch might look like.
    – mtraceur
    Commented Dec 29, 2023 at 4:31
2

If you want to do it from Elisp:

  1. advice-mapc will loop through all the advice functions on a function, and call a callback for each one.

  2. advice-member-p has the undocumented feature that when it returns non-nil, the return value is advice information!

So:

  1. If you're just interested in a boolean "does this function have *any" advice on it?":

    (defun has-advice-p (symbol)
        (let ((has-advice nil))
            (advice-mapc (lambda (&rest _) (setq has-advice t)) symbol)
            has-advice))
    
  2. If you want to check how a function was advised (:before, :around, :filter-return, [...]?) by a specific piece of advice:

    (defun advice-how (function symbol)
        (when-let (advice (advice-member-p function symbol))
            (aref (aref advice 2) 2)))
    

    (In earlier versions of Emacs this was known as "where" instead of "how".)

  3. If you want to know all of the advice for a function, combine advice-mapc with the above advice-how:

    (defun advice-list (symbol)
        (let ((advice-list ()))
            (advice-mapc
                (apply-partially
                    (lambda (symbol function properties)
                        (let ((how (advice-how function symbol))
                              (advice ()))
                            (when properties
                                (push properties advice))
                            (push function advice)
                            (push how advice)
                            (push advice advice-list)))
                    symbol)
                symbol)
            advice-list))
    

(Amusingly, the help text shown by describe-function (C-h f) doesn't actually query advice information, it's just added into the docstring by advice--make-single-doc.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.