I want to write a function that will call a list of functions in emacs (specifically, kill-buffer-query-functions
), but if any of them require user interaction, I want to have them simply return nil
instead, so that the whole thing will run non-interactively. I am thinking of using defadvice
to modify every function that would normally prompts the user to instead throw
an exception with a value of nil
. Then I will wrap everything with a catch
form. The only trouble is, I don't have an exhaustive list of all emacs elisp functions that might prompt the user for something.
Does anyone have such a list, or is there an easier way to go about this? As examples, the functions yes-or-no-p
and y-or-n-p
would certainly be on this list, as would read-string
and completing-read
.
Basically, I want to fill in the ellipsis in this code:
(defun eval-but-return-if-requires-user (form &optional interactive-return)
"Evaluate FORM, but immediately stop and return INTERACTIVE-RETURN if any part of FORM would require user interaction."
;; Set up the safety net
(catch 'ui-required
(let ((ui-requiring-functions '( ... )) ; What goes in this list?
(ui-required-callback
;; A function that takes any number of args and throws an exception
'(lambda (&rest args)
(throw 'ui-required interactive-return)))
(flet-redefinitions
;; Use the above callback to create a list of redefinitions for `flet'
(mapcar (lambda (func)
(cons func (cdr ui-required-callback)))
ui-requiring-functions)))
`(flet
,flet-redefinitions ; Perform the function redefinitions,
,form)))) ; Then evaluate FORM
Basically, I wrap everything in a catch block, then I define a function body that will simply take any arguments and throw an appropriate exception. I set up a list of redefinitions to be passed to flet
, which will temporarily redefine those functions to use the aforementioned exception-throwing body. Finally, I evaluate form
with those temporary function redefinitions in place.
Now, there's probably some quoting errors in that code, but I think that it would work if I just had the appropriate list of which functions to redefine.
Note that I want the entire form to return if any user interaction is required, not just the particular function call within the form that required user interaction. To see why I need this, consider that the form could possibly want to ask either of the following questions:
- Do you want to delete this very important file? yes or no
- Do you want to keep this very important file? yes or no
Obviously, if I just modified yes-or-no-p
to always return nil
(which means "no"), that still isn't guaranteed to save my important file from deletion. So, since I don't know what questions might be asked, I want to cause the entire form to simply abort and return a specific value if it wants to ask anything of the user.
Essentially, I want to say "Evaluate this code, but if you have to ask me anything in order to do so, just forget about it and return nil
."