覆盖emacs lisp函数的首选方法?

时间:2013-03-30 09:42:40

标签: emacs override

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

我已经关注了advice vs fset等的各种主题并感到困惑。

4 个答案:

答案 0 :(得分:20)

@iainH您倾向于通过描述目标来更快地获得有用的答案 你想要完成,然后到目前为止你所拥有的。我问代码 尽量帮助你做你想做的事,而不必覆盖任何东西。

我仍然不明白为什么你不只是使用defun?我猜测 可能会发生的事情是你在init文件中使用defun,但是原始版本 函数尚未加载(参见autoload)。一段时间后,你做到了 导致带有原始定义的文件被加载的东西和你的 自定义功能被原始功能覆盖。

如果这是问题,你有三个选择(假设你想要 从“telnet.el”覆盖telnet-initial-filter

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

    (require 'telnet)
    (defun telnet-initial-filter (proc string)
      ...)
    
  2. 直接Emacs仅在文件加载后加载您的函数 eval-after-load机制。

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

  4. 其中,2是最好的。 1也没关系,但你必须加载一个文件 从不在会话中使用。 3是最糟糕的。涉及defadvice的任何事情 应该留作最后的选择。

答案 1 :(得分:5)

为了让这个问题保持独立,以下是如何通过建议来实现的。

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

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

有关使用建议的更多信息,请参阅the manual

答案 2 :(得分:1)

有一个 "new" advice method 可以在原始函数加载之前设置函数替换。

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

这甚至可以与 eval-buffer 结合使用,例如您的初始化文件。

答案 3 :(得分:0)

我很难为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)