向“org-forward-element”添加额外的操作recenter?

问题描述

在组织模式下,调用 M-} 的敲击 org-forward-element 非常方便跳转

然而,匹配的行总是停留在底部。所以我必须手动执行(recenter)。

如何将动作(recenter)添加org-forward-element

我尝试了装饰器解决方案,但不起作用。

(defun add-recenter(func)
  (lambda ()
    (func)
    (recenter)))
(setq org-element-forward (add-recenter org-element-forward))

解决方法

这似乎有效:

(advice-add 'org-forward-element :after (lambda () (recenter)))

我第一次尝试了 (advice-add 'org-forward-element :after 'recenter),但没有奏效,因为如果添加的建议函数(在本例中为 recenter)是交互式的,它的 interactive 规范会覆盖旧函数 (org-forward-element),这会导致错误,因为 recenter 生成一个参数而 org-forward-element 使用零个参数。


你的代码不工作的原因是在 Emacs Lisp 中变量和函数在不同的命名空间中,就像 Common Lisp 而不像 Scheme。这有时被描述为“Lisp-2”,而不是“Lisp-1”。见例如这篇文章:http://ergoemacs.org/emacs/lisp1_vs_lisp2.html

基本上每个符号都有一个“值单元格”和一个“功能单元格”。 setq 更改符号的值单元格,调用符号(如 (foo))会访问其函数单元格。相应的 Emacs Lisp 代码类似于:

(defun add-recenter(func)
  (lambda ()
    (funcall func)
    (recenter)))
(fset 'org-element-forward (add-recenter (symbol-function 'org-element-forward)))

这基本上就是上面的 advice-add 调用所做的。