我的 GNU Emacs 配置“程序”
呃……一般来说大家都叫“配置文件”,是吧。当然我也是这么叫的。那就让我们还是继续延续这个名字,就叫 Emacs配置文件。
那么配置文件是我们定制和扩展Emacs最重要的地方,一般来说,最常用的配置文件是 =.emacs= 。当然也可以是别的文件,具体可以查阅 GNU Emacs Manual。
然而随着使用的日久,日积月累,定制的设置越来越多, =.emacs= 变得越来越庞大,渐渐的就会增大到难以维护的地步。直到某日在 emacser.cn 看到王纯业的 组织 .emacs 的文件内容的技巧 ,将配置信息分成多个文件,维护的困难才稍稍得以缓解。但是即使是拆分以后,文件仍然会变得很大,而且还在不断增大,维护起来仍然压力很大。有没有好的解决办法呢? ahei 的DEA我还没有去仔细看过,毕竟他那个太大了,我的配置还没有大到那个地步。我希望的是简洁高效的解决办法。能够在我的配置文件里面只有我最关心的内容,不带一点多余的东西呢?
直到最近开始着手探索 Lisp,体会到 Lisp语言强大的描述能力和抽象能力,随即萌发了将众多的配置细节直接用写成简洁清晰的 =list= ,然后用 Lisp Code进行处理,这样就可以去掉配置文件里面那些无穷无尽的方法调用了。 走了这个路子之后,原来的“配置文件”就摇身一变,变成“配置程序”了。
.emacs
闲话不说了,开始捞干的吧。让我们先从最基本的 =.emacs= 开始。在这种方式下 =.emacs= 文件就非常简单了。它的核心部分一共只有两行。
(add-to-list 'load-path "~/Shell/config/emacs.el" "~/Shell/config/emacs.init")
(mapc 'load (directory-files "~/Shell/config/emacs.init" t "^[a-zA-Z0-9].*.el$"))
第一行通过 =load-path= 注册扩展文件的所在位置。第二行通过 =mapcar= 函数逐个装载 "=~/Shell/config/emacs.init=" 目录下的所有配置文件。就是这么简单。其余的内容多数都是 Emacs Customization 添加的代码。或者换句话说,现在的 =.emacs= 文件完全留给 Emacs用了。
其实在采用这种方式之前,我是不用什么 Customization 的。当然,不用的代价是显而易见的。问题在于在原来那种配置方式之下, =.emacs= 本身就已经够烦够乱了,如果 Emacs的 Customization 再往里面添乱,就更难维护和控制了。不过现在没事了。我自己使用的一共只有两行,剩下的所有地方随便它写吧。所以呢,我现在至少还用 Customization修改了一下 ansi-color,默认颜色里面的深蓝色的目录实在是太刺眼了。
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(ansi-color-faces-vector [default default default italic underline bold bold-italic modeline])
'(ansi-color-names-vector ["black" "red" "PaleGreen" "yellow" "DodgerBlue1" "magenta" "cyan" "white"]))
另外,还有一个地方需要提到一下, 在 =.emacs= 里面我还保留了一段中文字体的设置。以前 emacser.com 里面有人发过字体设置的东西。但是由于 GNU Emacs 23以后基本都在 daemon方式下工作,如果直接使用原来那种方式设置中文字体的话,在 emacsclient中是无效的,所以要把它加到 =make-frame= 的hook里面。这样每次 =emacsclient -c= 生成的 frame就都是指定的中文字体了。 当然这下面这个函数还有一个缺陷,就是如果不是使用 daemon 方式的话…… 你懂得,鱼和熊掌,不可兼得。
(add-hook 'after-make-frame-functions
(lambda(arg)
(if (>= (length (frame-list)) 1)
(set-fontset-font "fontset-startup" 'chinese-gbk (font-spec :family "文泉驿微米黑") nil 'prepend)
)
) t
)
color-theme.el
那么我自己的配置信息写在哪些地方呢?让我们看看 "=~/Shell/config/emacs.init="目录下的都有哪些文件
2 : 2023 : 13:03:26 : ~/Shell/config/emacs.init
dove@bash-4.1$ du -sh *.el
8.0K calendar-setup.el
28K color-theme.el
28K dove-ext.el
4.0K keybindings.el
8.0K org-mode.el
8.0K plugins.el
4.0K settings.el
2 : 2024 : 13:03:35 : ~/Shell/config/emacs.init
dove@bash-4.1$ du -sh .emacs
4.0K .emacs
2 : 2025 : 13:04:07 : ~/Shell/config/emacs.init
dove@bash-4.1$
就是这些地方了。每个文件的作用从文件名上就能清晰的看出来。只有这个"=dove-ext.el="文件需要解释一下,这里存放的是我自己编写的所有扩展函数。
下面让我们逐个看一看这些文件的内容。"=calendar-setup.el=" 就不说了,这个文件基本上就是从网上搜来的,我自己也就是定义几个节日而已。
"=color-theme.el=" 是主题设置文件。基本上就是 =color-theme-gnome2= 的翻版,我自己做了一些简单的修改。之所以把他存在一个单独的文件里面主要是因为 =color-theme= 实在是太长了,放在哪个文件里都会影响其他的内容。
(eval-when-compile (require 'color-theme))
(defun my-color-theme ()
"Color theme created 2010-04-09."
; (interactive)
(color-theme-install
'(my-color-theme
; ((background-color . "#102C29")
((background-color . "darkslategrey")
; (( background-color . "black")
(background-mode . dark)
(border-color . "black")
(cursor-color . "LightGray")
; ... ... ... ... theme 太长,中间省略了
(woman-bold-face ((t (:bold t :weight bold))))
(woman-italic-face ((t (:foreground "beige"))))
(woman-unknown-face ((t (:foreground "LightSalmon"))))
(zmacs-region ((t (:background "dark cyan" :foreground "cyan")))))))
(eval-when-compile (require 'color-theme))
(color-theme-initialize)
(add-hook 'after-make-frame-functions
(lambda (arg)
""
(my-color-theme)) t)
另外我在加载 color-theme 的时候做了一个处理,把 =my-color-theme= 加到 =after-make-frame-functions= 这个 hook里面去,这样只有创建 frame的时候才会执行 =my-color-theme= 。 如果不是 =X= 环境,例如用 =emacs -nw= 的时候,就不要加载 =my-color-theme= 了。因为这个主题到了终端模式下,那个背景颜色根本没法看(汗一个)。虽然偶自己从来都是工作在 =X= 里面的。
这个问题在网上找到的有些解决办法是判断一下是不是 =window-system= ,这种办法到了 daemon模式下是会出错的。看来 Emacs 23 以后的 daemon 模式下的配置方法还是需要进一步深入研究的。什么东西都放到 =after-make-frame-functions= 这个地方毕竟也不是个事儿。
settings.el
下一个来看的是 settings.el。 settings 的任务其实很简单,就是设置全局变量。全局变量的设置就是 =setq= 嘛。这个事情简单的不能再简单了。但是无数的 =setq= 无论是写起来还是读起来都会让人很郁闷。还好,我们记得 =setq= 不但可以设置一个变量,它实际上可以处理一个 =list= 。嗨,既然说它可以,为什么还要让他闲着呢? 让我们动手吧,把所有的变量和值写在一个 =list= 里面,多余的 =setq= 通通都删掉吧。
(menu-bar-mode -1)
(tool-bar-mode -1)
(icomplete-mode 1)
(scroll-bar-mode -1)
;(ruler-mode -1)
(setq save-abbrevs t
x-select-enable-clipboard t
ispell-dictionary "english"
frame-title-format "%b %n %I"
inhibit-startup-message t
column-number-mode t
; ... ... ... ... 内容太多,中间省略
ido-toggle-regexp t
dim:switch-window-relative nil
shell-file-name "/usr/bin/bash"
default-major-mode 'text-mode
)
;; Misc
(setq-default abbrev-mode t
line-spacing 4
)
(setenv "EMACSSHELL" shell-file-name)
未完待续 …… ……
posted on 2010-11-03 21:13 David Young 杨博华 阅读(2386) 评论(5) 编辑 收藏 举报