Joe*_*nte 4 emacs elisp defadvice advising-functions
当我遇到一些非常奇怪的行为时,我试图回答另一个SO问题。这是我的小测试用例:
(make-variable-buffer-local
(defvar my-override-mode-on-save nil
"Can be set to automatically ignore read-only mode of a file when saving."))
(defadvice file-writable-p (around my-overide-file-writeable-p act)
"override file-writable-p if `my-override-mode-on-save' is set."
(or
my-override-mode-on-save
ad-do-it))
(defun my-override-toggle-read-only ()
"Toggle buffer's read-only status, keeping `my-override-mode-on-save' in sync."
(interactive)
(setq my-override-mode-on-save (not my-override-mode-on-save))
(toggle-read-only))
(defun tester-fn ()
(interactive)
(let ((xxx (file-writable-p "/tmp/foofoo"))
(yyy (file-writable-p "/tmp/fooxxfoo")))
(message (concat "XXX: " (if xxx "yes" "no") " - YYY: " (if yyy "yes" "no")))))
Run Code Online (Sandbox Code Playgroud)
哪里:
/tmp/foofoo是我访问并运行过的只读文件my-override-toggle-read-only。/tmp/fooxxfoo 不存在。/tmp 由我登录的用户可写。如果我tester-fn在my-override-mode-on-save设置为的缓冲区中运行,t则会得到意外结果:XXX: no - YYY: no。如果我tester-fn在其他缓冲区(例如,scratch)中运行,我会在minibuffer中得到预期的响应:XXX: no - YYY: yes。通过调试器跟踪建议可以表明它确实在执行我认为应该做的事情,执行了我期望的部分,跳过了我期望的部分,返回了我期望的值。但是,tester-fn通过调试器进行跟踪显示返回的值非常不同(nil&t如果变量的值为nil,nil&nil如果变量的值为非nil,则&。在nil与nil回报是真的是我觉得怪异。
我不知道这里发生了什么。有人知道为什么我没有得到我期望的结果吗?
您的代码看起来不错,但缺少一个键。您需要适当地设置返回值:
(defadvice file-writable-p (around my-overide-file-writeable-p act)
"override file-writable-p if `my-override-mode-on-save' is set."
(setq ad-return-value
(or
my-override-mode-on-save
ad-do-it)))
Run Code Online (Sandbox Code Playgroud)
建议手册中对此进行了记录。