【已解决】如何实现在Emacs启动时询问我加载哪些包

随着需要编写不同的代码,比如C、Python、Lisp、Org-mode,我喜欢为每一个不同的任务开一个不同的Emacs Frame。这样的话我就希望实现一个配置加载的可选择性:需要开启一个专门编写Python代码的Frame时,就不要加载org-mode的配置(有些配置比较费时)。

能否在.emacs初始化文件中通过lisp代码实现呢?希望各位给点提示,多谢!

不觉得启动时手工选择会比自动加载快。

每个major mode一般都默认关联了文件后缀来加载固定的主模式,例如你提到的打开py文件时是不会加载org的。具体是采用auto-mode-alist来关联的。 也可以自己定义文件后缀和主模式的关联。例如:

(add-to-list 'auto-mode-alist '("\\.iss$"  . iss-mode))

如果不是主模式,想避免其他的包加载,可以参考这篇文章。 用eval-after-load避免不必要的elisp包的加载

配置 X 并不要求加载 X,Emacs 在加载配置本身上的时间常常可以忽略不计。比如你可以在 Org-mode 没有加载时就配置它,Emacs 已经尽量这么做了:

;; Emacs autoload 了 org-store-link,即使 org 没有加载,你也能使用它
(global-set-key (kbd "C-c l") #'org-store-link)

;; setq 有特效,无论 org 什么时候加载,下面设置均有效
(setq org-agenda-files '("~/Sync/org/"))

;; add-hook 有特效,org-mode-hook 没定义也可以用;
;; org-bullets-mode 已经被 package.el 自动 autoload
(add-hook 'org-mode-hook #'org-bullets-mode)

但是你试图调用 Org-mode 中的某些函数的话,比如

(org-babel-do-load-languages
 'org-babel-load-languages
 '((emacs-lisp . t)
   (shell      . t)
   (ruby       . t)))

它会迫使 Emacs 启动时就加载 Org-mode,这会严重拖累 Emacs 启动速度,而且也没必要,你完全可以等到你打开 .org 文件时,再执行这段配置

(with-eval-after-load 'org
  (org-babel-do-load-languages
   'org-babel-load-languages
   '((emacs-lisp . t)
     (shell      . t)
     (ruby       . t))))

同样你也可以把上面的 setqadd-hook 放到 with-eval-after-load 里面来。


(emacs) Lisp Libraries 中关于 Autoload 的一点说明:

Some commands are “autoloaded”; when you run them, Emacs
automatically loads the associated library first.  For instance, the
‘M-x compile’ command (*note Compilation::) is autoloaded; if you call
it, Emacs automatically loads the ‘compile’ library first.  In contrast,
the command ‘M-x recompile’ is not autoloaded, so it is unavailable
until you load the ‘compile’ library.
3 个赞

感谢xuchunyang,感谢各位!

我想我需要的应该就是这个with-eval-after-load。