推荐一种emacs配置文件的组织方法

我平时经常在四台电脑上使用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的环境下,则只是打印一条信息,并不做设定。其他的情况也类似处理。

发布者

rix

如果连自己都不爱自己,哪还有谁来爱你