我平时经常在四台电脑上使用emacs,家里有两台,公司有两台,xp,ubuntu,osx,fedora,都是我经常使用的系统,为了在各个不同的平台上使用相同的习惯,需要将emacs做相同的配置,相同的功能。最简单的办法是复制,但有些内容在不同的平台上是不一样的,比如cygwin,我只有在windows上才使用,有些时候仅仅是想将某个插件临时禁用了(包括它的相关配置),这样很容易就造成了平台之间的不一致,每次使用造成不少麻烦。当然,我使用git来不断的更新我的配置,但有些内容则没有想象的那么简单。
前段时间在网上找关于编译错误解析(这个问题目前还没有解决)的时候,看到了别人的一篇关于emacs配置文件的组织方式:http://ann77.emacser.com/Emacs/EmacsOrginzeDotEmacs.html,具体内容可以看那篇文章,这里简单的说一下。
将配置文件按照ASCII顺序放到指定的文件夹中,然后在.emacs中写入下面的内容:
(mapc 'load (directory-files "~/work/emacs_config" t ".el$"))
我的配置文件放在~/work/emacs_config的目录中,你可以根据实际情况指定。然后将原来的配置文件按照你自己乐意的顺序来放置,我基本上是按照A.XXX.MODE.el的方式来排列的,A代表[a-zA-Z]的单个字母,XXX代表0-999的数字,MODE是模式的名字,比如shell-mode,现在正在写blog的weblogger模式,总共可以弄26*1000的顺序排列,我想这足够使用了(目前大约排到a.08X),我将快捷键的配置放到了z.001.keyshort.el中,这样保证配置快捷键的是否,所有的都已经准备妥当。
我自己下载的插件并没有放在emacs安装目录中,而是放在emcas_config中,在很多时候,需要指定load-path才行,于是,我在刚才的那个.emacs的刚开始添加了一行:
(setq emacs-config-dir "~/work/emacs_config/")
(mapc 'load (directory-files "~/work/emacs_config" t ".el$"))
然后,在模式配置的el,写上下面的语句,比如a.011.color-theme.el的:
(add-to-list 'load-path (concat emacs-config-dir "plugin/color-theme-6.6.0"))
(require 'color-theme)
(color-theme-initialize)
;(setq color-theme-is-global t)
(eval-after-load "color-theme" '(color-theme-classic))
由于文件的拆分,这样必然加载很慢,编译成.elc无疑是个好办法,但有些内容的话,直接使用下面的命令是没办法编译的:
emacs -batch -f batch-byte-compile *.el
上面的color-theme就不可以,原因在于那个命令并不执行自己的emacs配置文件,这样变量emacs-config-dir就没有定义,然后就无法找到color-theme,这样就无法编译成功了。不过,可以使用下面的方法进行编译:
emacs -l .emacs -batch -f batch-byte-compile *.el
上面的命令最好在~目录下执行,然后*.el改成具体目录下的*.el。两条命令不一样的就是emacs首先加载自定义的.emacs配置文件,然后再进行编译。
如果你像我一样,下面还扔了很多的插件的话(我都扔在emacs_config/plugin下),而这些插件没有编译的话,加载速度是很慢的,可以使用下面的命令来编译所有的.el到.elc
find work/emacs_config/plugin -name *.el -type f | xargs emacs -l .emacs -batch -f batch-byte-compile
一般的插件似乎都没有什么问题,但cedet似乎没办法这么干的,因此我其实使用的是下面的语句:
find work/emacs_config/plugin -path work/emacs_config/plugin/cedet2 -prune -o -name *.el -type f | xargs emacs -l .emacs -batch -f batch-byte-compile
cedet根据cedet的情况手动编译下就可以了。你会发现启动速度快了非常的多。
我将这些配置都放到git的仓库中,但现在有太多的内容了,很多都已经由el编译成elc了,elc我并不想放到仓库中,因此我用下面的命令来剔除所有的.elc,并忽略.git目录:
find . -path ./.git -prune -o -type f ! -name *.elc | xargs git add
在我将windows上的导出到linux上的时候,有一个问题,我在windows上用的是cygwin-mode,但linux上并不需要,一个方法就是将文件改名,但改来改去总不是办法,于是,我使用下面的方式来解决:
;; cygwin shell 配置
(cond
((memq initial-window-system '(x w32))
(cond
((memq system-type '(windows-nt cygwin)) (
(setq exec-path (cons "D:/proj/cygwin/bin" exec-path))
(setq shell-file-name "bash")
(setenv "SHELL" shell-file-name)
(setq explicit-shell-file-name shell-file-name)
;使用方法,把光标移动到要粘贴的地方,然后用按住 Alt + 拖拉鼠标, 选择要拷贝的部分, 抬起鼠标,选择的部分就粘贴到了光标所在位置. 也就是说,一个动作完成 copy & paste 的工作,而且不改变 kill ring 的内容, 用 windows 的术语是剪切板. 和上面的方法类似, 如果按住 Alt + Shift + 拖动鼠标,那么就会完成 cut & paste 的功能.
(defun cygwin-shell()
(interactive)
(shell "*cygwin-shell*")
; (set-buffer-process-coding-system 'chinese-gbk-unix 'chinese-gbk-unix)
(delete-other-windows)
)
;; enable cygwin clear, default set it does not work
(add-hook 'shell-mode-hook 'n-shell-mode-hook)
(defun n-shell-mode-hook ()
"12Jan2002 - sailor, shell mode customizations."
(local-set-key '[up] 'comint-previous-input)
(local-set-key '[down] 'comint-next-input)
(local-set-key '[(shift tab)] 'comint-next-matching-input-from-input)
(setq comint-input-sender 'n-shell-simple-send)
)
(defun n-shell-simple-send (proc command)
"17Jan02 - sailor. Various commands pre-processing before sending to shell."
(cond
;; Checking for clear command and execute it.
((string-match "^[ \t]*clear[ \t]*$" command)
(comint-send-string proc "\n")
(erase-buffer)
)
;; Checking for man command and execute it.
((string-match "^[ \t]*man[ \t]*" command)
(comint-send-string proc "\n")
(setq command (replace-regexp-in-string "^[ \t]*man[ \t]*" "" command))
(setq command (replace-regexp-in-string "[ \t]+$" "" command))
;;(message (format "command %s command" command))
(funcall 'man command)
)
;; Send other commands to the default handler.
(t (comint-simple-send proc command))
)
)
(require 'cygwin-mount)
(cygwin-mount-activate)
))
((memq system-type '(gnu/linux)) (message "for linux"))
)))
system-type来指示系统是windows-nt/cygwin的时候才执行那个cygwin的设定,如果是在gnu/linux的环境下,则只是打印一条信息,并不做设定。其他的情况也类似处理。