I want to run some function f after adding a hook to a mode and after running f remove the hook that I added, returning the result of f if there is one.

Here is a non-working version that I hope makes the intent clear:

(defun run-function-with-hook (mode-hook hook-fn fn)
  (add-hook mode-hook hook-fn)
  (message (concat "mode hooks before running: " (prin1-to-string (symbol-value mode-to-slowdown))))
  (funcall fn)
  (remove-hook mode-hook hook-fn))

  (run-function-with-hook 'org-mode-hook (message "opening org file") (message "opened org file"))

Is this a better fit for a macro? If so, perhaps the right answer to this is an answer using a macro instead.

  • That's the usual way to do it, AFAIK: add-hook followed by remove-hook.
    – Drew
    Commented Sep 9, 2019 at 13:51

2 Answers 2


It looks like I had things mostly correct besides a variable I forgot to rename. The issue was that I needed to wrap the functions in lambda calls:

(defun run-function-with-hook (mode-hook hook-fn fn)
  (add-hook mode-hook hook-fn)
  (message (concat "mode hooks before running: " (prin1-to-string (symbol-value mode-hook))))
  (funcall fn)
  (remove-hook mode-hook hook-fn))

(run-function-with-hook 'org-mode-hook (lambda () (message "opening org file")) (lambda () (message "opened org file")))

  • 3
    You might want to use unwind-protect in your run-function-with-hook to ensure that remove-hook happens.
    – phils
    Commented Feb 6, 2020 at 23:56

I do this all the time with let-binding. For example, here I temporarily define the value of an org-mode hook. It automatically reverts outside the let definition.

#+BEGIN_SRC emacs-lisp
(let ((org-export-before-parsing-hook '(org-ref-cite-natmove)))
    (org-open-file (org-latex-export-to-pdf)))

or in this example, I temporarily remove the org-mode hook while opening a file:

(let* ((filename (pop org-db-queue))
       (org-mode-hook '())
       (enable-local-variables nil)
       (already-open (find-buffer-visiting filename))
       (buf (find-file-noselect filename)))
  (org-db-log "Updating %s" filename)
  (with-current-buffer buf
    (org-db-update-buffer force))
  (unless already-open (kill-buffer buf)))

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.