我想编写一个函数来调用 emacs 中的函数列表(特别是,kill-buffer-query-functions
),但是如果它们中的任何一个需要用户交互,我想让它们简单地返回nil
,这样整个事情就会以非交互方式运行。我正在考虑使用defadvice
来修改通常会提示用户 throw
使用值为nil
. 然后我将用catch
表格包装所有内容。唯一的麻烦是,我没有一份详尽的列表,列出所有可能提示用户输入某些内容的 emacs elisp 函数。
有没有人有这样的清单,或者有没有更简单的方法来解决这个问题?例如,函数yes-or-no-p
和y-or-n-p
肯定会在这个列表中,就像read-string
和一样completing-read
。
基本上,我想在这段代码中填写省略号:
(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
基本上,我将所有内容包装在一个 catch 块中,然后定义一个函数体,该函数体将简单地接受任何参数并引发适当的异常。我设置了一个要传递给的重定义列表flet
,它将临时重新定义这些函数以使用上述抛出异常的主体。form
最后,我使用这些临时函数重新定义进行评估。
现在,该代码中可能存在一些引用错误,但我认为如果我只有适当的列表来重新定义哪些函数,它会起作用。
请注意,如果需要任何用户交互,我希望整个表单返回,而不仅仅是表单中需要用户交互的特定函数调用。要了解我为什么需要这个,请考虑该表单可能想要询问以下任一问题:
- 您要删除这个非常重要的文件吗?是还是不是
- 你想保留这个非常重要的文件吗?是还是不是
显然,如果我只是修改yes-or-no-p
为始终返回nil
(这意味着“否”),仍然不能保证我的重要文件不会被删除。所以,由于我不知道可能会问什么问题,我想让整个表单简单地中止并返回一个特定的值,如果它想询问用户的任何事情。
本质上,我想说“评估这段代码,但如果你必须问我什么才能这样做,那就忘记它并返回nil
。”