在Emacs Lisp中覆盖一个函数

12
我想临时覆盖 kill-new 函数。我有一种方法来重新实现 kill-new 函数,只在某些情况下起作用,但我不想在此基础上重新实现一个特殊版本的 kill-region(kill-new 从 kill-region 调用)。
由于 Emacs Lisp 使用动态作用域,这应该是可能的,对吗?(另一方面,支持这个功能似乎是不安全的,知道它是可能的可能会让我有点紧张......)
我已经尝试过使用 let 和 fset,但到目前为止还没有找到使其按预期工作的方法。因此,希望有人能填写以下伪代码中的空白部分:
(defun my-kill-new (string &optional replace yank-handler) 
   (message "in my-kill-new!"))

(defun foo ()
   (some-form-that-binds-a-function (kill-new my-kill-new)
   (kill-region (point) (mark))))

一些绑定函数的表单应该是什么样子?还是说我方向错了?

3个回答

17

您的绑定函数的某个表单被称为flet,所以您已经接近了。


11

这里是一个解决方案:

(defadvice kill-new (around my-kill-new (string &optional replace yank-handler)) 
   (message "my-kill-new!"))


(defun foo ()
  (progn (ad-enable-advice 'kill-new 'around 'my-kill-new)
     (ad-activate 'kill-new)
     (kill-region (point) (mark))
     (ad-disable-advice 'kill-new 'around 'my-kill-new)
     (ad-activate 'kill-new)))

我认为我更喜欢这种方法,而不是使用flet。虽然使用advice会有更多的仪式感,但它让我可以轻松地访问kill-new的现有实现。 - kes
6
你可能想要使用 unwind-protect 来移除建议,以便非本地退出也可以移除建议。只需使用 flet 即可。 - jrockway
如果您想要访问“kill-new”的原始定义,只需将其“flet”到“old-kill-new”。 - Radon Rosborough

3

看一下 advice 包,它非常擅长完成所有这些操作。


FYI:现在advice已被nadvice取代。 - Radon Rosborough
1
我正在运行最新的emacs,nadvice似乎不在了,但是advice仍然很强大。 - Randal Schwartz
这很令人惊讶。除非你所说的“不存在”是指nadvice没有advice的所有功能?https://github.com/emacs-mirror/emacs/blob/master/lisp/emacs-lisp/nadvice.el - Radon Rosborough
啊,仍然被称为“advice”,并且仍然被记录为这样。所以它在那里,但是“较新”。不错。 - Randal Schwartz
确实。新系统完成了与旧系统相同的事情,但“少了一些花哨的东西”。也就是说,它更直观,适用于更多情况,更一致,更简单。总有一天advice.el会被弃用,但很可能不会很快。 - Radon Rosborough

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接