我应该在哪里包含惰性初始化?


13

我想向乳胶模式添加特定的键绑定:

(define-key latex-mode-map (kbd "<f6>") 'my-latex-defun)

同时,我只想在加载特定模式时进行设置。因此,我想知道在使用适当的hook(latex-mode-hook)完成此操作或使用子句(with-eval-after-load "tex-mode" ...包装键绑定定义之间是否存在偏好(最佳实践)。我对它们都进行了测试,但是它们都可以正常工作,但是我想知道哪种方法是正确的。


2
with-eval-after-load加载一次,因此keymap-change在那里。每次运行模式时都会挂载钩子,例如,在加载与该模式相关联的新文件时,或者定义了钩子。您将加载例如flyspell-modehl-line-mode钩。在我中,init.el我使用with-eval-after-load大约160次和add-hook110次。惰性初始化是一个好的初始化(IMO)。
拉斯莫斯2014年

如果有时间的话,@ rasmus听起来像是一个答案:)我认为要区分代码运行多少次是主要的考虑因素。(这也是我能想到的唯一一个……)
肖恩·阿雷德

为什么这是一个坏主意,改变模式钩键绑定看到emacs.stackexchange.com/questions/990/...
眼镜猴

Answers:


18

惰性初始化是一个好的初始化。

(IMO)

何时使用 with-eval-after-load

with-eval-after-load被加载一次当某一功能文件首先加载,所以键映射变清楚地进入内部的其中之一。至少因为在启动时可能不知道键映射[尝试类似(define-key message-mode-map (kbd "C-c f") 'Footnote-add-footnote)in中的操作emacs -q]。钩子不是一个很好的解决方案,因为它在每次启动钩子时都会将函数绑定到键。正如tarsius所指出的,您可以阅读有关为什么加入local-set-key钩子的更多信息。

最后,请注意,with-eval-after-loadGNU Emacs 24.4是2行包装器,eval-after-loadbody不需要引用的地方。

何时使用挂钩

挂钩是每次满足标准(例如,启动某种模式)时加载的功能列表。挂钩的常见用法是加载次要模式,例如flyspell-modehl-line-mode。例如(add-hook 'org-agenda-mode-hook 'hl-line-mode)。正如Rémi指出的那样,add-hooks即使钩子变量尚未加载,它也很聪明并且会做正确的事情。尽管如此,我还是有很多类似以下的子句,这些子句对于速度提升来说可以忽略不计,但是确实提供了组织和依赖关系的感觉:

(with-eval-after-load 'org-agenda
  (add-hook 'org-agenda-mode-hook 'hl-line-mode))

为什么要添加到钩子之后org-agenda?一如既往地C-h v org-agenda-mode-hook C-j交付。挂钩的定义org-agenda.el如中所示*help*

加载额外的功能 with-eval-after-load

with-eval-after-load对于加载其他功能也很重要。您可能想要(with-eval-after-load 'org (require 'org-inlinetask))加载org inlinetasks之类的东西。看看为什么(find-library "org-inlinetask")。从org-inlinetasks.el直接开始(require 'org)autoload您友好的Emacs维护人员会非常注意地提供的所有好处都将被“忽略”,并且org.el(c)将全部加载。

但是,如果您的(个人)defun需要多个地方怎么办?如果您确实很挑剔,则可以将defuns 放入您的另一个文件中load-path并添加autoloadcookie,或者可以告诉Emacs使用该autoload函数在哪里找到该函数。然后这样的事情会起作用:

(autoload 'org-cdlatex-mode "org" "cdlatex mode from org.")
(with-eval-after-load "latex"
  (add-hook 'TeX-mode-hook 'org-cdlatex-mode))

或者您也可以require org反过来拉cdlatex

而且,老实说,在大多数情况下,个人辩护对于启动时间没有多大影响。我的1150行个人defun(84 defun)init.el比原始的Emacs增加0.02s。

测量初始化时间

估算初始化时间的一种简单方法是

time emacs --eval "(kill-emacs)"

(针对的基准emacs -q

但是,要获得有关初始化瓶颈的详细信息,请查看Joe Schafer的esup

最后,加载时间不会神奇地消失。您只是将其向前推进(扩展到您在每个会话中使用所有功能)。


1
您不需要将add-hook放在with-eval-after-load中,因为add-hook将绑定变量(如果尚不存在)。
雷米

你是对的!还能从中获得速度提升吗?[我稍后将尝试更新答案以反映这一点]
rasmus

那么以后我想绑定到钩子或键绑定的defuns呢?我应该在with-eval-after-load不失去懒惰的初始化优点的情况下在外部定义defun 吗?
jrbalderrama 2014年

5

除了您对eval-after-load钩子的建议和使用外,让我建议use-package.el。你可以做你需要做的

(use-package latex
  :ensure auctex
  :bind ("<f6>" . my-latex-defun))

您请求之前不会加载LaTeX 。

顺便提一句:的谨慎使用use-package将我的启动时间缩短到了不到一秒钟。(过去大约需要四秒钟。)


谢谢你的建议。我也曾考虑使用use-package,但我真的很想弄清楚如何在不使用其他软件包的情况下使用它。
jrbalderrama

1
该@jrbalderrama音符use-package设置使用Emacs 25船
肖恩·奥尔雷德
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.