如何在Emacs中建议原语

如何在Emacs中建议原语,emacs,elisp,advising-functions,defadvice,Emacs,Elisp,Advising Functions,Defadvice,我正试图回答,突然发现了一些非常奇怪的行为。下面是我的小测试用例: (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)

我正试图回答,突然发现了一些非常奇怪的行为。下面是我的小测试用例:

(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)中运行测试仪fn,我会在小缓冲区中得到预期的响应:
XXX:no-YYY:yes
。通过调试器跟踪建议显示它正在做我认为它应该做的事情,执行我期望它做的部分,跳过我期望它做的部分,返回我期望它做的值。但是,通过调试器跟踪
测试仪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)))

这记录在。

中,我一直认为
ad return value
用于覆盖返回值,而不是设置返回值(手册也这么说)。但这确实是丢失的一块——谢谢!(对我来说)不同之处在于,假设返回值是正常的(即最后计算的表达式),而
ad返回值将用于更改该值。@JoeCasadonte啊,我总是将建议解释为给你改变行为的钩子,但(引用)“After advice和around advice可以通过设置ad返回值来覆盖返回值。”但我可以看到您的POV。