我抄了一个函数来添加company-backend:
purcell/emacs.d/lisp/init-company.el :
(defun sanityinc/local-push-company-backend (backend)
"Add BACKEND to a buffer-local version of `company-backends'."
(make-local-variable 'company-backends)
(push backend company-backends))
这个函数在用的时候需不需要放在with-eval-after-load 'company
里?
e.g.:
(with-eval-after-load 'company
(add-hook 'c-mode-common-hook
(lambda () (sanityinc/local-push-company-backend 'company-c-headers))))
以及我该怎么确定,在什么情况下 必须 用with-eval-after-load
, 什么情况下 最好 用with-eval-after-load
, 而什么情况下 不要 用with-eval-after-load
?我看了半天EmacsWiki和官方文档,结果完全理解不到点上……
谢谢!
eval-after-load
/ with-eval-after-load
的作用非常明确,(elisp) Hooks for Loading 中提到:
If you want code to be executed when a particular library is loaded, use the macro `with-eval-after-load’:
所以问问你自己有没有这个需要?这应该很容易判断,从结果往前推挺别扭,也没听说过什么 best practice 可以总结的。
如果为保安全使用(因为我的菜鸡水平,有时候真判断不出来),开销大不大?
;;; init-foo.el
(require 'foo)
;; 使用 foo 自身的成员,无需 eval-after-load,因为已经 require 在前了
(setq foo/var-a t)
;; 这里的 eval-after-load 多余,foo/func-a 立即被调用
(eval-after-load 'foo
(foo/func-a))
;; 用到了 bar 的成员,这个包在本文中没有 require,并且:
;; - 不知道它什么时候/哪个文件 require(抄来的配置太复杂😄)
;; - 知道它什么时候/哪个文件 require,但是不想为加载顺序所累
;; - 不/不想关心它什么时候 require
;; 通过 eval-after-load 推迟这段代码的执行,直到 bar 被 require
(eval-after-load 'bar
;; 如果 bar 一直没有 require,就永远也执行不到。有时候可能也会带来些问题
;; 比如:你特别需要某个功能,但是这里就静悄悄的跳过去了
(bar/func-a))
;;; init-foo.el ends here
eval-after-load
开销当然是有一点,但是它里面的代码只在初始化的时候执行一次,如果运用得当,还能节省不少启动时间。你倒是需要注意哪些反复激活的 mode-hook
里的代码开销。
@LdBeth 说少用/不用,那是建立在对初始化流程相当了解的情况下。通常如果配置文件一复杂,难免出现交叉依赖,就像 spacemacs
,用了一堆 pre-init/post-init
来解决这个问题。
2 个赞
也就是说,如果我明确的知道这些代码的加载顺序,其实不用也没事?
LdBeth
2017 年11 月 19 日 03:02
9
如果你用 use-package
管理配置的话,你其实是可以完全不需要显式调用 with-eval-after-load
的。