我的配置充满了建议,而且我不断听到有关新的闪亮简约nadvice.el
包的信息。
我已经搜索了手册,并且阅读了源代码,但我会公开承认:我仍然不知道如何实际使用它。
在座的任何人都可以向我指出指南,或告诉我如何开始移植旧式建议吗?
我的配置充满了建议,而且我不断听到有关新的闪亮简约nadvice.el
包的信息。
我已经搜索了手册,并且阅读了源代码,但我会公开承认:我仍然不知道如何实际使用它。
在座的任何人都可以向我指出指南,或告诉我如何开始移植旧式建议吗?
Answers:
C-h f add-function
其中包含您需要的所有信息,其中描述了的基本机制advice-add
。
新的建议系统基本上就像用下表中描述的函数替换函数的当前定义一样
C-h f add-function
,这取决于您对WHERE
参数的选择,只是为了跟踪已在哪个源文件中定义了什么行为而更干净。
:around
选项的示例最一般的情况是该:around
选项,因此我举一个例子。(在可能的情况下,最好使用专用WHERE
参数,但您可以用等效的:around
函数相互替换
)。
举个例子,假设您想调试每次调用它的参数列表find-file
并使用print
它。你可以写
(defun my-find-file-advice-print-arguments (old-function &rest arguments)
"Print the argument list every time the advised function is called."
(print arguments)
(apply old-function arguments))
(advice-add #'find-file :around #'my-find-file-advice-print-arguments)
通过此新实现,建议所需的所有内容均作为参数传递。ad-get-args
因为参数作为普通函数参数(对于WHERE
有意义的参数)传递给通知函数,因此变得不必要
。ad-do-it
由于:around
建议将函数和参数作为参数而变得不必要,因此(ad-do-it)
它被替换为形式
(apply old-function arguments)
或在您命名参数时
(funcall old-function first-arg second-arg)
因为不涉及任何魔术形式,所以它更清洁。修改参数只需将修改后的值传递给即可OLD-FUNCTION
。
WHERE
值的docstring add-function
包含所有建议场所(或“组合器”)及其等效表,并lambda
以与建议功能等效的方式解释功能:
`:before' (lambda (&rest r) (apply FUNCTION r) (apply OLDFUN r))
`:after' (lambda (&rest r) (prog1 (apply OLDFUN r) (apply FUNCTION r)))
`:around' (lambda (&rest r) (apply FUNCTION OLDFUN r))
`:override' (lambda (&rest r) (apply FUNCTION r))
`:before-while' (lambda (&rest r) (and (apply FUNCTION r) (apply OLDFUN r)))
`:before-until' (lambda (&rest r) (or (apply FUNCTION r) (apply OLDFUN r)))
`:after-while' (lambda (&rest r) (and (apply OLDFUN r) (apply FUNCTION r)))
`:after-until' (lambda (&rest r) (or (apply OLDFUN r) (apply FUNCTION r)))
`:filter-args' (lambda (&rest r) (apply OLDFUN (funcall FUNCTION r)))
`:filter-return'(lambda (&rest r) (funcall FUNCTION (apply OLDFUN r)))
(cited from `C-h f add-function')
其中FUNCTION是建议功能,而OLDFUN是添加建议的功能。不要试图一次理解所有这些,只需选择一个WHERE
听起来合适的符号并尝试理解该符号即可。
或只是使用:around
。据我所知,WHERE
在:around
所有内容上使用Specialized s 的唯一优势是,C-h f ADVISED-FUNCTION
在阅读建议的文档字符串之前,通过查找可以获得更多信息。除非您计划发布包含建议的代码,否则可能没有关系。
我建议使用命名函数作为建议,因为它具有许多优点(其中一些优点也适用于对挂钩使用命名函数):
它显示C-h f find-file
为
:around advice: `my-find-file-advice-print-arguments'
链接到建议功能的定义,该功能通常包含指向定义它的文件的链接。如果建议已lambda
直接以advice-add
表单的形式定义为表单,则该文档字符串将内联显示(长文档字符串是否乱七八糟?),并且没有任何内容指示该文档的定义位置。
您可以通过以下方式删除建议
(advice-remove #'find-file #'my-find-file-advice-print-arguments)
您可以更新建议的定义,而无需重新运行
advice-add
或冒使旧版本保持活动状态的风险(因为在运行
advice-add
更改lambda
后将被识别为新建议,而不是对旧建议的更新)。
旁注该#'function
符号基本上与等效
'function
,除了它有助于字节编译器将符号标识为函数名称,从而标识缺失的函数(例如,由于拼写错误)。
(advice-add 'find-file :around #'my-find-file-advice-print-arguments)
和类似(advice-remove 'find-file #'my-find-file-advice-print-arguments)
。
advice-add
是一个边境案件。我个人认为该' ↔ #'
区别主要是帮助识别函数名称中的拼写错误,因此在这里它可能取决于是否希望在添加建议时定义该函数。
add-function
)。我希望文档能更清楚地说明这一点。我可能希望为此做一个补丁。
C-h f find-file
,而不是C-x
?
M-x report-emacs-bug
。有些开发人员有时更喜欢开发而不是文档。;-) Emacs文档本身很重要。