如何模块化emacsconfiguration?

我已经决定从头开始重写我的.emacs,并且我想要设置一些模块化的东西,以避免一个可怕的1k + LoC init.el文件…

我认为每个configuration都需要解决一些基本问题:

  • 全球选项
  • 编辑function
  • 导航(框架和缓冲区)
  • 键绑定
  • 模式自定义

虽然我仍然想要通过结构来思考,但我正在寻找一些关于如何实现这一目标的指导。
我在github上看过一些.emacs,似乎有些不同的方法,而且没有最好的方式去处理,这有点令人困惑。
我会有兴趣阅读关于如何构build这样一个设置,特别是一些相关的elisp代码的一些想法。


编辑:已经赶上了事情,并没有太多的时间玩这个呢。 将在几天内尝试提出的方法,看看什么是最好的,同时感谢所有的build议!


edit2:我一直在使用org-mode的literate init文件 ,这是非常棒的!
我还没有设置特定的加载机制,我一直在使用这个代码,recursion加载我的elisp目录,然后要求或任何安装说明说。

(if (fboundp 'normal-top-level-add-subdirs-to-load-path) (let* ((my-lisp-dir "~/.emacs.d/elisp/") (default-directory my-lisp-dir)) (setq load-path (cons my-lisp-dir load-path)) (normal-top-level-add-subdirs-to-load-path))) 

我仍然需要擦亮这个,也许使用自动加载,如果修改过的技巧,一些字节重新编译; 很想听听有关这方面的build议。

我的.emacs文件加载〜/ .emacs.d / init.el ,它定义了以下函数,首先为XEmacs编写,但是对于Emacs来说这些工作已经足够了:

 (defconst user-init-dir (cond ((boundp 'user-emacs-directory) user-emacs-directory) ((boundp 'user-init-directory) user-init-directory) (t "~/.emacs.d/"))) (defun load-user-file (file) (interactive "f") "Load a file in current user's configuration directory" (load-file (expand-file-name file user-init-dir))) 

然后,文件的其余部分将加载大量的单个文件,如下所示:

 (load-user-file "personal.el") 

我目前的一组文件如下:

  • personal.el
  • platform.el
  • cygwin.el
  • variables.el
  • paths.el
  • 邮件news.el
  • MISC-funcs.el
  • bbdb.el
  • calendar.el
  • angular马,funcs.el
  • C-和java.el
  • lisp.el
  • clojure.el
  • go.el
  • markdown.el
  • SGML的xml.el
  • tex.el
  • spelling.el
  • org.el
  • packages.el
  • fonts.el
  • 颜色theme.el
  • frame.el
  • server.el
  • keys.el
  • aquamacs.el

正如其名称所暗示的,其中一些比其他意图更具针对性。 文件越细化,重新安装包或库时越容易禁用表单集群。 当“移动”到一个新的系统,在那里你拖动你的configuration文件但是还没有安装所有的支持包的时候,这是特别有用的。

要将自定义分割为不同的文件,可以使用initsplit.el 。 此外,wiki上还有一个模块化的.emacs布局页面。

使用load-file什么问题?

你可能会发现一些额外的位有用

  • file-exists-p
  • file-expand-wildcards

使用Ch f <function>获得帮助,您可能会发现Emacs Lisp编程简介很有用(或者下载PDF )

看看这个非常好的emacs入门套件 ,还包括ELPA套件。 我用这个结构作为我自己更简单的设置的灵感。

如果你想分割你的custom-set-variables ,但想要比initsplit.el更轻的重量,那么试试这个:

 (defmacro custom-set-variable (var value) "Call `custom-set-variables' with a warning shown when customizing using the customize GUI. XXX: does not support setting the optional NOW and REQUEST (dependency) fields." (custom-set-variables ;; `load-file-name' is set by `load-file': ;; http://stackoverflow.com/a/1971376/470844 `(,var ,value nil nil ,(format "!!! CAREFUL: CUSTOM-SET IN %s !!!" load-file-name)))) 

现在,把你的configuration模块放在不同load-file中,像其他人所说的那样,把它们load-file到你的~/.emacs 。 在每个configuration模块中,使用

 (custom-set-variable var value) 

代替

 (custom-set-variables '(var value)) 

要么

 (setq-default var value) 

设置由自定义pipe理的variables时。 然后,如果您需要使用自定义界面来定制variables,则会看到一条警告,告诉您自定义应存储在哪个文件中:

 "!!! CAREFUL: CUSTOM-SET IN <path to module file> !!!" 

如果你的版本控制你的configuration文件,那么diff会告诉你的~/.emacs哪一行移动到自定义模块中。

讨论天真使用多个custom-set-variables调用的问题: http : //www.dotemacs.de/custbuffer.html

编辑:回应艾伦的问题

上面的custom-set-variablemacros的问题解决了

Emacs中的自定义界面会在您编辑任何自定义设置variables时将所有自定义设置variables保存在~/.emacs 。 如果您将自定义设置variables模块化,请将其分散在多个文件中,然后您需要了解emacs何时在.emacs中插入重复设置并将其删除。 上面的custom-set-variablemacros可以帮助你做到这一点。

一个来自我的configuration文件的真实例子

我在~/.emacs.d/extensions/whitespace.el文件中自定义设置与我的~/.emacs加载的~/.emacs.d/extensions/whitespace.el相关的variables。 例如,我设置了我的search-whitespace-regexpvariables,如下所示:

 (nc:custom-set-variable search-whitespace-regexp "[ \t\r\n]+") 

现在,有两件事情发生。 首先,当我在自定义界面中遇到这个variables时,我得到一个警告:

在Emacs的定制对话框中生成警告

其次,如果我使用自定义接口编辑任何variables,我的~/.emacs就会很明显地说明我已经隐藏了一些定义。 例如,在自定义界面中更改search-whitespace-regexpglobal-whitespace-mode后,我得到:

 $ svn di --diff-cmd "diff" -x "-U0" ~/v/conf Index: /home/collins/v/conf/dot.emacs =================================================================== --- /home/collins/v/conf/dot.emacs (revision 267) +++ /home/collins/v/conf/dot.emacs (working copy) @@ -55,0 +56 @@ + '(agda2-include-dirs (\` ("." (\, (file-truename "~/local/opt/agda-std-lib/src")))) nil nil "!!! CAREFUL: CUSTOM-SET IN /home/collins/.emacs.d/extensions/agda.el !!!") @@ -58,0 +60,3 @@ + '(global-whitespace-mode t) + '(indent-tabs-mode nil nil nil "!!! CAREFUL: CUSTOM-SET IN /home/collins/.emacs.d/extensions/whitespace.el !!!") + '(indicate-empty-lines t nil nil "!!! CAREFUL: CUSTOM-SET IN /home/collins/.emacs.d/extensions/whitespace.el !!!") @@ -72,0 +77 @@ + '(search-whitespace-regexp "" nil nil "!!! CAREFUL: CUSTOM-SET IN /home/collins/.emacs.d/extensions/whitespace.el !!!") @@ -74,0 +80 @@ + '(tab-width 2 nil nil "!!! CAREFUL: CUSTOM-SET IN /home/collins/.emacs.d/extensions/whitespace.el !!!") 

macros没有帮助我记得我改变了search-whitespace-regexp ,只是它已经设置在其他地方,但它确实帮助我知道我应该从我的~/.emacs (所有那些有警告的)中删除哪些variables设置,以及哪些我应该离开我的~/.emacs ,或移动到其他单独的文件(所有那些没有警告)。

结论

macros可能是矫枉过正的,但是一旦存在,就很容易使用,并且更容易避免在自定义设置variables的阴影下拍摄自己。

你可以这样做(require 'foo) require'foo (require 'foo) ,并且会在你的加载path中加载第一个“foo.el”elisp查找,或者(require 'foo "/home/user/experimental/foo.el")加载/加载/ 。 如果“foo.el”不包含expression式(provide 'foo)它会报错。 在一个不正常的情况下,你可以做(require 'foo "bar.el") ,只要“bar.el”有一个(provide 'foo)子句就可以工作。

这里是一个库,它允许你简单地通过将它们保存在指定的目录中来安装新的模块。 它可以从http://github.com/tripleee/my-site-start/下载和安装;

  ;;; my-site-start.el --- set up personal .emacs.d/site-start.d/ ;; ;; Copyright (C) era eriksson <http://www.iki.fi/~era/> 2008-2009 ;; License: GPL v2 ;; Version: see `my-site-start-version' below ;; ;;; Commentary: ;; ;; The purpose of my-site-start is to simplify maintenance of user libraries. ;; Instead of indefinitely tweaking your .emacs, just create a site-start.d ;; directory and add symlinks to the libraries you want to load into Emacs. 

这个架构确实强加了一些您可能会或可能不会喜欢的约定。 请参阅文件顶部附近的注释部分的其余部分以获得全面的信息。

我是这个代码的作者,并感谢任何反馈(虽然不直接通过这个公共论坛)。

我所做的每件事情都是X,我可能要使用,创build一个名为configure-X的文件,并在.emacs中放入相应的require 。 这个function可以通过注释掉一行来删除。

例如,要select最简单的(如果最不好的名字),我有configure-picture-and-artist-mode.el。 这个文件很简单:

 (global-set-key (kbd "CMP") 'picture-mode) (provide 'configure-picture-and-artist-mode) 

在.emacs中:

 (require 'configure-picture-and-artist-mode) 

sorting完成后,我的.emacs中没有任何内容,除了一个大的require s列表和对load-path的一些更改外,可以很容易地移除给定的包,并且每个包的所有configuration都在一个地点。

(我也有一个全面的.el文件,我用它来存储没有任何明显的家(我的全局键绑定,帮助函数等)的东西,但仍然理想地想要远离.emacs。位并不是非常模块化的,并且可能会引入隐式依赖关系的包,我的scheme应该很容易卸载,但实际上这似乎不是什么大问题。)

你可以尝试一下init-loader.el ,它是一个configuration文件的加载器。 init-loader.el从指定的目录加载configuration文件。 它使您能够对您的configuration进行分类并将其分成多个文件。

有关更多信息,请访问init-loader GitHub Repo

感谢@JoeCasadonte提到EmacsWiki页面 。 正如我使用Debian和Ubuntu,这个特定的代码片段工作得很好(放在.emacs.d / init.el中):

 (setq dotfiles-dir (file-name-directory (or load-file-name (buffer-file-name)))) (let ((user-site-start-dir (concat dotfiles-dir "/site-start.d"))) (debian-run-directories user-site-start-dir)) 

然后,我只需要将我的.el文件放在〜/ .emacs.d / site-start.d(例如~/.emacs.d/site-start.d/50cedet.el )中,它们都会自动加载。