7

I sometimes want to bypass the advice I have defined on some function. Something like:

(call-without-advice #'fn ...)
3
  • I don’t think it’s possible, but just for clarity what are the circumstances in which you want to call the original function only? Commented Jul 19, 2023 at 0:32
  • emacs.stackexchange.com/tags/elisp/info Commented Jul 19, 2023 at 14:29
  • 1
    Temporarily remove it, after saving it, then restore it. This page and the code it describes might help a bit. Commented Jul 19, 2023 at 14:31

3 Answers 3

7

I can't find a public interface for that. In Emacs 25.5 and Emacs 27.1 and presumably every version in between (I haven't checked older or more recent versions), for new-style advice (define-advice, advice-xxx from nadvice.el), you can use

(advice--cd*r (symbol-function #'fn))

For old-style advice (defadvice, ad-xxx from advice.el):

(ad-get-orig-definition #'fn)
8

I've thought about this before, and there's a less-than-perfect solution:
you need to store the original definition before any advice-adding.

(defun f ()
  (insert "233\n"))

(setq f.backup (symbol-function 'f))

(advice-add 'f :around
            (lambda (fobj &rest args)
              (insert (format "eq?: %s\n"
                              (eq f.backup fobj)))
              (apply fobj args)))

It is also convenient to store the definition in symbol-plist.


Update
(advice-add 'advice-add :before
            (lambda (symbol &rest _)
              (unless (get symbol :shynur/original-definition)
                (put symbol :shynur/original-definition
                     (symbol-function symbol)))))

(defun call-without-advice (symbol &rest arguments)
  (apply (or (get symbol :shynur/original-definition)
             symbol)
         arguments))

looks much better now.

1

Combining the suggestions from @Gilles:

(defun fn-sans-advice (sym)
  "Get original function defined at SYM, sans advices."
  (if (advice--p (symbol-function sym))
      (advice--cd*r (symbol-function sym))
    (if (fboundp 'ad-get-orig-definition)
        (ad-get-orig-definition sym)
      sym)))

I find this more general than a direct "call-without-advice", because you can e.g. let-bind it once before initiating a heavy loop, as in the following example.

(let ((real-delete-file (fn-sans-advice #'delete-file))
  (dolist (file (directory-files "."))
    (funcall real-delete-file file)))

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.