Doom Emacs延迟加载场景下,如何程序化使用未加载包的变量?
Doom Emacs延迟加载包的按键绑定问题解决
问题场景
尝试在Doom Emacs的延迟加载机制下,为未加载的包绑定自定义按键映射,原代码如下:
(pcase-dolist (`(,package ,keymap) '((eww eww-mode-map) (info Info-mode-map) (man Man-mode-map) (nov nov-mode-map) (devdocs devdeocs-mode-map))) (eval-after-load package (evil-define-key* 'normal keymap "j" #'my/pixel-scroll-down)))
存在的问题:eval-after-load内部的变量会被立即求值,而非等到包加载时才使用对应变量,导致按键绑定无法正确生效。
解决方案
修正后的代码
(pcase-dolist (`(,package ,keymap) '((eww eww-mode-map) (info Info-mode-map) (man Man-mode-map) (nov nov-mode-map) (devdocs devdocs-mode-map))) (let ((pkg package) (km keymap)) (eval-after-load pkg (lambda () (evil-define-key* 'normal km "j" #'my/pixel-scroll-down)))))
关键说明
- 局部变量绑定:用
let将循环中的package和keymap绑定到局部变量pkg和km,避免循环变量被后续迭代覆盖,确保每个eval-after-load回调能获取到对应包的正确参数。 - 延迟执行逻辑:将
evil-define-key*的调用包裹在lambda函数中,eval-after-load会在包加载完成后执行这个lambda,此时才会对km(对应包的按键映射变量)求值,保证绑定操作在包完全加载后执行。 - 拼写修正:原代码中
devdeocs-mode-map为拼写错误,修正为devdocs-mode-map。
原代码失效原因
evil-define-key*是宏,会在pcase-dolist循环时立即展开,此时keymap变量对应的包按键映射可能尚未初始化,导致绑定无效。- 未使用局部变量保存循环参数时,所有
eval-after-load的回调会共享同一个循环变量,最终只会使用最后一次迭代的参数值。
内容的提问来源于stack exchange,提问作者Maor
相关产品推荐
相关产品推荐

