If you want to run something after the stack clears, run it on a 0 second timer.
(run-with-timer 0 nil 'your-function)
You could wrap this is a macro like this:
(defmacro after-stack-clears (&rest body)
"Do BODY after the call stack is clear"
`(run-with-timer 0 nil (lambda () ,@body)))
Here's an example usage mimicking your described scenario.
In this example, annoying-func
is calling another provided function. In the provided function you'd like to call annoying-func
again but annoying-func
will error if called more than once on the call stack. So to counter this, the provided macro to ensure that annoying-func
is called a second time, but only after the call stack has cleared and annoying-func
has done its cleanup
(defun your-func-simple ()
"try to directly call `annoying-func'."
(annoying-func (lambda () (message "hi"))))
(defun your-func-smart ()
"ensure `annoying-func' is called after the stack clears."
(after-stack-clears
(annoying-func (lambda () (message "hi")))))
(setq annoying-var nil)
(defun annoying-func (func)
"This function will apply FUNC, if `annoying-function' is called
somewhere down the line by FUNC, the second call will error, because this
is the annoying function after all."
(if annoying-var
(error "Can't call recursively!")
(condition-case err
(progn (setq annoying-var t)
(apply func nil)
(setq annoying-var nil))
(error (progn (message "errored! %s" err) (setq annoying-var nil))))))
(defun erroring-example ()
(annoying-func 'your-func-simple))
(defun working-example ()
(annoying-func 'your-func-smart))
;; will error due to annoying-func being called twice on the stack
(erroring-example)
;; will NOT error since annoying-func is called again only after the stack has cleared
(working-example)
post-command-hook
-- there is at least one other hook that runs later in time, but not always -- the former always runs exactly one time. However, this is before control returns to the user. The hook that runs before the current function is called thepre-command-hook
. Here is a link to the documentation regarding the standard hooks: gnu.org/software/emacs/manual/html_node/elisp/…