24

我已经重写并独立测试了由与 Emacs 24 捆绑的 Emacs 函数之一调用的内部函数的行为。合并 - 例如在我的init.el- 我的函数的行为覆盖捆绑函数的首选方法是什么?

advice我已经关注了vsfset等 的各种线程并且很困惑。

4

4 回答 4

30

@iainH 通过描述您要实现的目标以及到目前为止的目标,您往往会更快地获得有用的答案。我要求提供代码以尝试帮助您做您想做的事情,而无需覆盖任何内容。

我还是不明白为什么你不只是使用defun呢?我怀疑可能发生的情况是您defun在 init 文件中使用,但尚未加载原始函数(请参阅autoload)。一段时间后,您做了一些事情来加载具有原始定义的文件,并且您的自定义函数被原始定义覆盖。

如果这是问题所在,您有三个选项(假设您telnet-initial-filter要从“telnet.el”覆盖):

  1. 在定义自己的版本之前自己加载文件。

    (require 'telnet)
    (defun telnet-initial-filter (proc string)
      ...)
    
  2. 仅在使用eval-after-load机制加载文件后,才指示 Emacs 加载您的函数 。

    (eval-after-load "telnet"
      '(defun telnet-initial-filter (proc string)
         ...))
    
  3. 使用建议。

其中,2个是最好的。1 也可以,但是您必须加载一个您可能永远不会在会话中使用的文件。3是最差的。任何涉及的事情defadvice 都应该作为最后的选择。

于 2013-03-31T01:34:14.983 回答
6

只是为了让这个问题自成一体,这里是如何根据建议来做的。

(defadvice telnet-initial-filter (around my-telnet-initial-filter-stuff act)
  "Things to do when running `telnet-initial-filter'."
  (message "Before")
  ad-do-it
  (message "After") )

如果您想包装而不是替换现有函数(在这种情况下只需重新定义它),这显然很有用。

有关使用建议的更多信息,请参阅手册

于 2014-08-11T16:27:20.337 回答
2

有一种“新”的建议方法,甚至可以在加载原始建议之前设置函数替换。

(defun something-fixed ()
  ...
  )
(advice-add 'original-function :override #'something-fixed)

This even works in combination with eval-buffer of e.g. your init file.

于 2021-02-15T15:39:17.933 回答
1

我发现很难推理eval-after-load+ defun。而且defadvice宏具有复杂的语义和文档。相反,我使用建议原语,例如advice-add

(defun my-vc-git-print-log (files buffer &optional shortlog start-revision limit)
   ...)

(defun my-vc-git-print-log-advice (fn &rest args)
  "Uses `my-vc-git-print-log' that adds extra `--all' to `git log'."
  (apply #'my-vc-git-print-log args))

(advice-remove 'vc-git-print-log #'my-vc-git-print-log-advice)
(advice-add 'vc-git-print-log :around #'my-vc-git-print-log-advice)
于 2020-03-30T10:43:22.980 回答