如何在Emacs中建议原语

时间:2010-06-19 14:44:24

标签: emacs elisp advising-functions defadvice

当我遇到一些非常奇怪的行为时,我试图回答another SO question。这是我的小测试案例:

(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")))))

其中:

  • /tmp/foofoo是我访问过并在my-override-toggle-read-only中运行的只读文件。
  • /tmp/fooxxfoo不存在。
  • /tmp可由我登录的用户写入。

如果我在tester-fn设置为my-override-mode-on-save的缓冲区中运行t,则会收到意外结果:XXX: no - YYY: no。如果我在其他缓冲区(例如 scratch )中运行tester-fn,我会在迷你缓冲区中获得预期的响应:XXX: no - YYY: yes。通过调试器跟踪建议表明它正在做我认为应该做的事情,执行我期望的部分,跳过我期望的部分,返回我期望的值。但是,通过调试器跟踪tester-fn会显示返回的值非常不同(nil& t如果变量的评估结果为nil,nil& nil变量的计算结果为非零)。 nil& nil回归真是我发现奇怪的事情。

我不知道这里发生了什么。任何人都知道为什么我没有得到我期望的结果?

1 个答案:

答案 0 :(得分:4)

您的代码看起来不错,但缺少一个密钥。您需要适当地设置返回值:

(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)))

advice manual中记录了这一点。