eval-after-load和mode hook的区别

81
使用eval-after-load和使用模式钩子设置模式有什么区别吗?
我看到一些代码在主模式钩子中使用define-key,而其他一些代码在eval-after-load表单中使用define-key
更新:
为了更好的理解,这里是一个使用eval-after-load和模式钩子与org-mode一起使用的例子。该代码可以在(load "org")(require 'org)(package-initialize)之前运行。
;; The following two lines of code set some org-mode options.
;; Usually, these can be outside (eval-after-load ...) and work.
;; In cases that doesn't work, try using setq-default or set-variable
;; and putting them in (eval-after-load ...), if the
;; doc for the variables don't say what to do.
;; Or use Customize interface.
(setq org-hide-leading-stars t)
(setq org-return-follows-link t)

;; "org" because C-h f org-mode RET says that org-mode is defined in org.el
(eval-after-load "org"
  '(progn
     ;; Establishing your own keybindings for org-mode.
     ;; Variable org-mode-map is available only after org.el or org.elc is loaded.
     (define-key org-mode-map (kbd "<C-M-return>") 'org-insert-heading-respect-content)
     (define-key org-mode-map (kbd "<M-right>") nil) ; erasing a keybinding.
     (define-key org-mode-map (kbd "<M-left>") nil) ; erasing a keybinding.

     (defun my-org-mode-hook ()
       ;; The following two lines of code is run from the mode hook.
       ;; These are for buffer-specific things.
       ;; In this setup, you want to enable flyspell-mode
       ;; and run org-reveal for every org buffer.
       (flyspell-mode 1)
       (org-reveal))
     (add-hook 'org-mode-hook 'my-org-mode-hook)))

7
因为C-h f org-mode RET显示org-mode是在org.el中定义的,所以我给"+1 for org"。我一直在努力让eval-after-loadnxml-mode中实际执行,而这个提示很有用! - Zach Young
1个回答

113

eval-after-load包裹的代码将只会被执行一次,通常用于执行一次性的设置,例如设置默认的全局值和行为。一个例子是为特定模式设置默认按键映射。在eval-after-load代码中,不存在"当前缓冲区"的概念。

模式钩子(Mode hooks)会针对每个启用该模式的缓冲区执行一次,因此它们用于针对每个缓冲区进行配置。模式钩子比eval-after-load代码后运行;这样可以根据诸如当前缓冲区是否启用其他模式等信息采取相应的操作。


1
顺便提一下(如果我错了请纠正):似乎在自定义的eval-after-load脚本得到执行之前,emacs-lisp-mode和lisp-mode就已经被加载了。因此,在这种情况下,确实需要使用模式钩子。 - balu
1
是的:eval-after-load 块总是在相关库被 load 后才会被 eval。但请注意,该代码将始终在相关库中的任何函数被调用之前执行。因此,如果您 (eval-after-load 'lisp-mode ...),那么该块中的 ... 代码将在 lisp-mode.el 中的 lisp-mode 函数被调用之前运行。 - sanityinc
1
after-load 究竟是用来做什么的?和 eval-after-load 有什么区别? - balu
6
这只是一个本地的宏包装器,用于避免引用传递给 eval-after-load 的形式需要加引号。例如,我可以写 (after-load 'foo (foo) (bar)) 来代替 (eval-after-load 'foo '(progn (foo) (bar)))。注意,翻译时不能改变原意。 - sanityinc
2
@balu:emacs-lisp-modelisp-mode已经随着Emacs一起安装,但从未被加载。 - sds
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接