在Elisp中如何在被cl-letf覆盖的函数内调用原函数?
提问:Elisp中用
cl-letf覆盖函数后,如何在自定义实现内调用原函数 在Elisp中,cl-letf可用于覆盖函数实现。我现在需要在被覆盖的函数内部调用原函数,具体场景如下:
我想要禁用ediff的「Do you really want to quit?」退出确认提示,但保留ediff的其他询问弹窗,目前的实现代码如下:
(defun my-ediff-disable-quit-question (orig-fun &rest args) (cl-letf (((symbol-function 'y-or-n-p) (lambda (prompt) (if (string-prefix-p "Quit this Ediff session" prompt) t (<call-original-y-or-n-p> prompt))))) (apply orig-fun args))) (advice-add 'ediff-quit :around #'my-ediff-disable-quit-question)
以上代码中我覆盖了y-or-n-p函数,会先检查提示内容是否为退出会话的提示,如果是就直接返回t,否则需要调用原始的y-or-n-p执行原有逻辑。
回答
你只需要在执行cl-letf覆盖函数之前,先将y-or-n-p的原始实现存储到临时变量中,需要调用原逻辑时直接调用该临时变量即可,修改后的可用代码如下:
(defun my-ediff-disable-quit-question (orig-fun &rest args) ;; 提前保存原始的y-or-n-p函数实现 (let ((original-y-or-n-p (symbol-function 'y-or-n-p))) (cl-letf (((symbol-function 'y-or-n-p) (lambda (prompt) (if (string-prefix-p "Quit this Ediff session" prompt) ;; 匹配到退出提示直接返回确认 t ;; 其他场景调用原始y-or-n-p逻辑 (funcall original-y-or-n-p prompt))))) (apply orig-fun args)))) (advice-add 'ediff-quit :around #'my-ediff-disable-quit-question)
实现原理
symbol-function可以获取指定符号当前绑定的函数对象,我们在修改y-or-n-p的函数指向之前先把原始实现缓存到变量original-y-or-n-p中,后续调用时通过funcall执行该缓存的函数对象,不会触发我们新定义的覆盖逻辑,即可完美实现需求。
内容的提问来源于stack exchange,提问作者geza
相关产品推荐
相关产品推荐

