Emacs配置系统
作者: shell909090

emacs是个超级复杂的程序,尤其在配置问题上。贝壳的emacs要跨越三个环境。环境一,WindowsXP+Emacs23。环境二,Debian Testing + Xfce4。环境三,CentOS + Ssh。而整个的操作方式,个性设定需要保持一致。因此,引出一个问题。配置如何设置,跨平台,同步。
首先解决配置的同步问题,贝壳建立了一个svn仓库,用于存储该配置系统。然后在各个系统中co出这个仓库,当有需要调整时ci就可以保持同步了。 Linux下可以使用ln连接文件,Windows下比较麻烦点,NTFS格式(大多都是NTFS格式了吧)可以去sysinternals下一个叫做 junction的工具,以建立目录的工具链接,当然,.emacs文件只能手工拷贝了。
然后是配置的切分问题,如果只有一个文件,即使使用了版本控制,意义也不大。同时,将配置切割成不同的部分,控制载入过程,也可以跨平台和加速。以下是贝壳的.emacs文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | ;; .emacs profile, written by shell.xu ;; load other set (add-to-list 'load-path "~/.emacs.d/") (add-to-list 'load-path "~/.emacs.d/auto-complete/") (add-to-list 'load-path "~/.emacs.d/plugins/") (load "emacs-setup") (load "emacs-redef") (load "emacs-plugin") (cond ((not (boundp 'initial-window-system)) (load "emacs-console")) ((memq initial-window-system '(x w32)) (cond ((memq system-type '(windows-nt cygwin)) (load "emacs-win")) ((memq system-type '(gnu/linux)) (load "emacs-linux")) ) ) ) (load "emacs-keymap") |
从上可以看出,我们先设定了.emacs.d作为默认加载路径——大多数文件都是放在这里。plugins是各种第三方程序的安装路径,这样这些程序就无需在各个平台上各自安装一次。而auto-complete单独拆出来纯粹是因为文件太多了。而后,我们加载了setup,这个文件内定义了emacs的基本配置,redef文件内定义了各种自定义函数和变量,plugin内控制了需要加载的各个插件和配置。
下面就有点复杂,简单来说,设定无Windows系统的时候加载emacs-console文件,有Windows的情况下,在windows下加载emacs-win,在linux下加载emacs-linux。这是实现跨平台设置的核心。
最后是keymap,经过上面复杂的设定,按键设置是统一的。
setup文件就不细说了,大家按照自己的习惯设定就好。下面我说几个redef中定义的函数。
1 2 3 4 5 6 7 8 | (defun switch-windows-buffer () (interactive) (let ((this-buffer (window-buffer))) (switch-to-buffer (window-buffer (next-window (selected-window)))) (switch-to-buffer-other-window this-buffer) (other-window 1) ) ) |
这个函数的目标是用热键交换两个窗口的位置。如果你经常用C-x 3分栏,并且在两者间跳来跳去的话,有的时候往往希望两者的位置换一下。通常都是C-x b切换当前的窗口,然后C-x o切到隔壁去再换。这个太繁琐了。
1 2 3 4 | (defun popup-term () (interactive) (apply 'start-process "terminal" nil popup-terminal-command) ) |
这个函数是用于在当前文件所在路径弹出一个term的。也许有人说了,emacs有term啊。问题是,那个term只能开一个,而且有些东西操作不了。例如你如果想在这个term里面跑aptitude…
注意这个函数里面的popup-terminal-command,这个需要跨平台的,因此在windows和linux下设定各自不同。以下是两个典型设定,至于哪个是哪个我想都看得懂。注意console下面没必要搞这个。
1 2 | (setq popup-terminal-command '("xfce4-terminal")) (setq popup-terminal-command '("cmd" "/c" "start")) |
然后我们说plugin,这个文件其实很简单,加载插件,然后设定就好。下面是一部分范例。
1 2 3 4 5 6 | ;; load template (require 'template) ;;here set the templates directory (setq template-subdirectories '("./" "Templates/" "~/.emacs.d/templates/")) (template-initialize) (setq template-auto-insert t) |
这部分范例说明了如何载入template,并且进行设定。
下面是一点细节问题,tool-bar-mode这个设定相信多数人都有做。问题是,针对某些console系统,如果你设定了(tool-bar-mode -1),立刻会报错。具体的条件是,编译的时候没有加入X的支持。因此,为了兼容性起见,针对console下就忽略这个设定。
最后,这些设定,推荐进行编译加速,包括所有第三方插件。不编译也是可以载入的,然而记得删除el文件对应的elc。否则emacs默认载入elc,从而导致你对el文件的修改无效——emacs是不认文件时间的。而显然,每个平台编译一遍是个脑残的事情。因此,我们需要写一个Makefile。
1 2 3 4 5 6 7 8 9 10 11 | DEPENDS=auto-complete plugins SOURCES=emacs-console.el emacs-keymap.el emacs-linux.el emacs-redef.el emacs-setup.el emacs-win.el build: $(SOURCES) emacs-plugin.el for i in $(DEPENDS); do $(MAKE) -C $$i build || exit 1; done emacs --batch -f batch-byte-compile $(SOURCES) emacs --batch -l ~/.emacs -f batch-byte-compile emacs-plugin.el clean: rm -rf *.elc for i in $(DEPENDS); do $(MAKE) -C $$i clean || exit 1; done |
注意,在每个目录中也要分别写Makefile,不过内容简单多了,基本就是emacs –batch -f batch-byte-compile *.el而已。而plugin这个文件比较特殊——他必须依赖于所有插件才能工作,所以最后才进行编译。
以上工作,基本完成了一个跨平台的emacs配置系统的组建。当然,如果你高兴向其中加入更多的内容,可以遵循以上规范进行。

loading...
多人共笔博客?
[回复]
ahei 回复:
三月 4th, 2010 at 10:21 上午
@happybabe, 对阿,邀请到了共17位emacser,不知道你有兴趣没?我加你gtalk了,有空聊下
[回复]
happybabe 回复:
三月 4th, 2010 at 2:50 下午
@ahei, 17位~好多啊…可不可以拜托你们一件事,长文章都给它插个 more 标签吧,首页会简洁许多。
文章技术含量太高了,我真的看不懂。没必要写得这么复杂…
[回复]
ahei 回复:
三月 4th, 2010 at 3:13 下午
@happybabe, 呵呵,还好吧,如果真看不懂,再多看点其他的资料,熟悉了就容易看的懂了
[回复]
1. 自己的emacs的配置也是用在多个平台,代码配置是用git,原先也用过svn,但是经常会没有网络,也只能选择了分布式的git,hg试过一会就彻底的git了。
2. 不得不说在windows上用时比较折腾的,还创建了单独的HOME目录,平台相关的代码倒是在具体的配置文件中在进行判断的,vim和makefile也是要单独判断windows,很是费劲。
3. 自己是吧emacs的配置文件拆分的很细,.emacs文件成了载入配置文件的master,也是为了控制方便。
[回复]
Dropbox不好用么?
[回复]
@bood
那个,Dropbox不是不好用,只是经常被墙。
[回复]
你的select-buffer,Alt-tab不起作用,切换的是ubuntu的窗口。
select-buffer-forward(M-N)下一个窗口
select-buffer-backward(M-P)上一个窗口,是正常的。
我的环境(vmware下ubuntu9.10+emacs23)
[回复]
ahei 回复:
三月 26th, 2010 at 7:33 上午
;; 可以像linux下Alt-tab那样切换窗口
;; select-buffer-forward(M-N)下一个窗口
;; select-buffer-backward(M-P)上一个窗口
“可以像”并不是说,按键绑定也是Alt Tab,我默认绑定的就是M-N和M-P
[回复]
匿名 回复:
三月 26th, 2010 at 8:09 上午
@ahei, 额,不好意思,误会了……
[回复]
发现新的CVS版里已经有cedet,w3m了,有些跟你的DEA里的不一样,但似乎先找到的是安装目录下的,这样就有问题了,你能否处理一下
[回复]
ahei 回复:
三月 30th, 2010 at 7:38 上午
@, 没关系的,我的会覆盖系统的。
[回复]
我在windows下测试了一下,好像不能覆盖吧,还有一个错误:
Warning (initialization): An error occurred while loading `e:/ntemacs23/.emacs’:
File error: Searching for program, no such file or directory, ~/dea-read-only/lisps/snarl_command.exe
[回复]
ahei 回复:
三月 30th, 2010 at 8:49 上午
@, 那最简单的方法,你可以把内置的cedet移走就可以了。关于那个snarl,我忘记提交了,晚上提交上去告诉你。
[回复]
我没有用cvs版的没有覆盖怎么竟然也没有错误?
[回复]
ahei 回复:
三月 30th, 2010 at 2:25 下午
啥意思?那你用什么cedet的?我的还是1.0pre6?
[回复]
tmpistemp 回复:
三月 30th, 2010 at 6:53 下午
@ahei, 我晕,多说了一个”没有”
原意是想说”我用cvs版的没有覆盖怎么竟然也没有错误”.
我用的是pre7.
[回复]
ahei 回复:
三月 31st, 2010 at 12:59 上午
@tmpistemp, 这个就不清楚了,得实际调查一下了。
[回复]
请问为什么在 KDE 下使用 (setq popup-terminal-command ‘(“konsole”)) 不能启动 konsole?
而且如果一直按着 F7 就会启动很多个 konsole,按一次就啥都没有。。
试过 (setq popup-terminal-command ‘(“terminal”)) 是可以启动 terminal 的。
[回复]
ahei 回复:
四月 3rd, 2010 at 4:59 上午
@, 应该是(setq popup-terminal-command ‘(“konsole”))吧, 而且作者所说的:
其实可以用multi-term解决.
[回复]
匿名 回复:
四月 4th, 2010 at 3:53 上午
@ahei,
其实就是 (setq popup-terminal-command ‘(“konsole”)) 不管用。。
但是 (setq popup-terminal-command ‘(“terminal”)) 可以启动 Xfce 的 Terminal 。。
比较困惑
[回复]
ahei 回复:
四月 4th, 2010 at 3:56 上午
@, 我的意思是不是你把标点弄成全角的了, 如果没有的话, 是不是你的konsole不在PATH里面?还有, 有报什么错误吗?
[回复]
匿名 回复:
四月 4th, 2010 at 7:04 上午
@ahei,
字符都是半角的。konsole 也是在 PATH 里的。
我换用同步的 call-process 倒是可以启动 konsole 了,
似乎 konsole 启动时会自动 fork 一次然后不作为当前进程的子进程。
感觉上像是 start-process 启动 konsole 时还没 fork 就退出去了。
用 call-process 的问题是工作目录又不在 pwd 了。。。
[回复]
ahei 回复:
四月 4th, 2010 at 7:20 上午
@, 同步的话, 你操作konsole的时候就不能操作Emacs啦, “用 call-process 的问题是工作目录又不在 pwd 了”是指打开konsole后, 当前目录不是刚才在Emacs中的当前目录吗?你用start-process的时候, 什么错误都没有嘛?
[回复]
匿名 回复:
四月 4th, 2010 at 7:44 上午
@ahei,
“用 call-process 的问题是工作目录又不在 pwd 了” 就是您说的意思。比如我在编辑 ~/temp/temp.cc,
konsole 打开还是在 ~/ 下。
进一步我尝试 call-process-shell-command,用 (format “konsole –workdir %s” (pwd)) 做 shell command 来运行,还是有一些问题:只有第一个term是在启动在 pwd 下,第一个窗口不关,之后 F7 出来的term的working dir都是一样的。。只有关了之前的term窗口后,再 F7 才用当前的 pwd。不过 Emacs minibuffer 里提示的 Directory 又总是当前的 pwd。。
call-process 有个参数 destination,为 0 的时候就像异步一样立刻返回了
http://www.gnu.org/software/emacs/elisp/html_node/Synchronous-Processes.html#Synchronous-Processes
start-process 的时候 Emacs 真没有任何错误信息出来。。。
但是终端里运行 konsole 会有如下提示:
konsole(19740)/kdeui (kdelibs): Attempt to use QAction “change-profile” with KXMLGUIFactory!
Undecodable sequence: 01b(hex)[?1034h
[回复]
ahei 回复:
四月 4th, 2010 at 8:04 上午
@, 呵呵, 不知道你为什么要用konsole呢, 在emacs下用multi-term不是很好吗, 非常方便, 和真实的shell基本一样的.
[回复]
匿名 回复:
四月 4th, 2010 at 8:16 上午
@ahei,
呃,因为现在 DE 是 KDE,而且 Xfce Terminal 有过一些奇怪的问题。。所以打算换一下,
本来以为 .emacs 里改个字符串就行了,没想到还挺麻烦。。
Emacs 里用 term 我大概还不习惯吧,感觉term还是一个黑黑的窗口比较爽呵呵。multi-term 我去试试。。谢谢
[回复]
ahei 回复:
四月 4th, 2010 at 2:28 下午
想要黑黑的窗口的话, 你把Emacs底色设为黑色不就行了吗? 我的就是黑色的, 你可以看我的Emacs截图
[回复]
兄弟 你写的教程 我有点看不懂 能否详细说下Emacs在windows xp下如何配置
中文菜单的显示 和 .emacs这个文件
谢谢
[回复]
shell 回复:
四月 22nd, 2010 at 1:59 上午
@fhefh, 中文菜单的话,我没啥主意。因为我的配置是去掉菜单而不是将他翻译成中文。emacs的特长是定义很多函数,然后将这些函数绑定到快捷键上。从而在一个键下执行很多神奇的事情,从最简单的光标向前一个位到最复杂的格式化文本。要是用菜单一级级点出来,还不如给我个vim。
[回复]
ahei 回复:
四月 22nd, 2010 at 2:06 上午
@fhefh, 而且emacs没有中文版,想要中文菜单的话,得自己汉化了
[回复]