为什么 cl-letf 只有在我求值了函数体才生效呢?

我使用 https://github.com/andre-r/centered-cursor-mode.el 这个包来始终保持光标在正中间。

这个包提供了一个 ccm-mwheel-scroll 函数来处理滚轮操作,这个函数内部使用了 forward-line 函数,而我希望能用 next-line 这个函数来替代它,从而在开启 visual-line-mode 时有更好的体验。

我采用如下代码来实现这一点:

(define-advice ccm-mwheel-scroll
    (:around (orig &rest event) use-next-line)
  (cl-letf (((symbol-function 'forward-line) #'next-line))
    (apply orig event)))

目前遇到的问题是,这个代码运行后没有效果。但是如果我进入到 ccm-mwheel-scroll 的源代码中,重新求值C-x C-e)一下该函数的定义,那么就有效果了。

我的环境是: Mac Sonoma;Emacs Plus 29.1;Doom Emacs

希望得到大家的帮助!

因为太晚了,只是猜测一下,现在上下文是 lexical scope 否?如果是,cl-flet 或许不会动态绑定 'forward-line?只是猜测

因为 forward-line 被编译器内联了。直接自己重写一遍就行,别 advice 了。

(byte-compile (lambda (x) (forward-line x)))
#[(x) "^Hy\207" [x] 1]

(byte-compile (lambda (x) (next-line x)))
#[(x) "\301^H!\207" [x next-line] 2]

和 lexical scope 没关系。

试试 基于 pcase 的函数热补丁方法

(psearch-patch ccm-mwheel-scroll
  (psearch-replace '`(forward-line . ,args)
                   '`(next-line ,@args)))

原来如此,多谢指点!

好的,让我之后尝试一下,请问这个方法对于内联的情形(即本话题的情况)应该也没有效果的的吧?

对内联有效,因为会从原文件读取编译前的代码打补丁。

原来如此。

确实有效,舒服啦,感谢!!!