加速你的 Emacs

Emacs 会随着你定制的内容增多而启动速度越来越慢,当然,在很多服务器上是 启动之后就一直不会关闭的,但是自己的电脑不做服务器,会经常关机,而且有 些时候会临时启动一下编辑器,比如说环境变量里面的 EDITOR 就是很多程序经 常会调用的。那么,如何来加速自己的 Emacs 呢?下面给出了几个解决办法:

不加载任何配置文件进行启动

emacs -q 命令启动可以跳过加载自己的 ~/.emacs 而进行启动,如果版本比 较新的 Emacs ,还支持 -Q 选项,表示快速启动,其实这个选项是等价于这样 启动: emacs -q --no-site-file --no-splash 。这样一般就能够达到比较快 的速度了,不足的地方就是跳过了所有定制的部分,自己熟悉的定制的功能都没 有了,见到的只是一个陌生的朋友而已。

用 emacsclient 来连接 emacs server

这个方法首先要有一个启动好了的 Emacs ,并且要已经启动了 server 模式, 你可以用 M-x server-start 来启动 server 模式,或者在自己的 ~/.emacs 里 面加入 (server-start) 来自动启动 server 。

然后,你就可以通过 emacsclient filename 来快速使用 Emacs 打开文件了! 事实上,文件是在作为 server 的那个 Emacs 里面打开的,而 emacsclient 将 等待 server 编辑文件。这个时候你可以转到 server 那里去编辑文件,编辑好 之后用 C-x # 来关闭文件并通知 emacsclient 文件已经编辑完成。现在,你就 可以把自己的 EDITOR 变量设置成 emacsclient 而不用怕启动速度慢了:

EDITOR="emacsclient +%d %s"

不过如果没有事先启动了一个 emacs server 的话,这个命令就会失败,他提供 的一个解决办法就是 --alternate-editor 参数,表示连接失败的时候调用的命 令,你可以把他设置成 vi 或者是其他小巧的编辑器,或者,你也可以在这儿直 接设置成 emacs ,不过这也许并不如想象中的那么美妙,也许你认为如果没有 启动 emacs ,那么在这儿就启动它,然后后面就可以顺利地调用 emacsclient 了!但是如果这儿是其他程序比如 mutt 或者 svn 之类的使用 EDITOR 环境变 量来调用的编辑器,他会等待编辑器退出来表示编辑完成,这个时候看着刚刚启 动的 emacs 马上又要关闭了,实在是不忍心呀!:) 1 不过这个也有个不爽的 地方就是打开文件都是在 server 里面打开的,还不能自动跳转到 server 那里 去,比较麻烦。

使用 multi-tty 补丁

简介

引用作者的一句话: 2

My goal is to allow opening multiple, different tty devices and simultaneous X (graphical) and tty frames from a single Emacs session.

这里是扩展了 emacs server 的这种方法。使用 emacsclient 的时候可以另外 打开一个 X 窗口或者是 tty 窗口进行编辑,而不是简单地把编辑任务发送到 emacs server 那里。

获取和安装

使用 Debian 的 apt-get 直接安装

要使用这个补丁版本的 Emacs ,如果是 Debian 系统的话,可以直接使用他提 供的源下载安装或者下载源代码包自己编译:

# Multi-tty Emacs
deb http://aszt.inf.elte.hu/~lorentey/mirror/apt unstable multi-tty
deb-src http://aszt.inf.elte.hu/~lorentey/mirror/apt unstable multi-tty

获取 emacs—multi-tty 的源代码

其他系统可以直接下载源代码进行编译。作者提供了一个仓库,可以用 bazzar 软件来获取仓库中的源代码,他有好几个镜像,具体可以参见他的 README 文件 ,我使用其中一个仓库:

baz register-archive -f http://lorentey.hu/arch/2004/
baz get lorentey@elte.hu--2004/emacs--multi-tty emacs-multi-tty

在我这里速度很慢,不知道是为什么,连接上去以后接近半个小时才开始真正下 载文件,几分钟之后就下载完毕了,我开始还一直以为是根本无法下载呢。

获取 emacs 22 的代码和 multi-tty 的补丁文件

另外,也可以用 cvs 来获取的 Emacs 22 的源码,并打上最新的multi-tty 给的 补丁,可以在 这里 找到补丁文件,然后把他们打到 check out 出来的 emacs 的源码树上面去。这样也许速度会快一些,但是需要注意的是,最好是先下载补 丁文件,看是哪个日期的,再去获取对应那天的 Emacs 的源代码,不过,即使是 同一天的源代码,也可能会有巨大变动的,所以还是直接获取 emacs—multi-tty 的源代码安全一点。

cvs -z3 -d:pserver:anonymous@cvs.savannah.gnu.org:/cvsroot/emacs co emacs

然后到 emacs 的目录里面去,打上补丁:

cd emacs
patch -p 1 < ../emacs--multi-tty--0--patch-555.2006-05-05.patch

修改与编译

PURESIZE

编译之后尝试运行一下,有可能会出现 warning 说 ``Building Emacs overflow pure space'' 3 。事实上,因为 emacs 启动的时候有一部分只读的 不可扩展的内存,因为这儿用了 multi-tty 补丁,导致预先定义的那些内存无法 容纳下所有的预加载库,于是只有动态分配,所以会在启动的时候产生 warning 。

要解决这个问题,需要修改一下 src/pursize.h 文件,找到里面定义 PURESIZE_RATION 的地方,把值改大一点就可以了。我是把

改成了

输入法问题导致的段错误

这样可以重现这个问题:

  1. 以非 X 方式启动 Emacsemacs -nw
  2. Emacs 里面启动 server : M-x server-start
  3. 以 X 方式启动一个 emacsclient 连接到 server : emacsclient
  4. 退出这个 emacsclient : C-x 5 0

这个时候可以看到 server 已经 Segment fault 退出了。galilette@Linuxsir 指出这是由于对 server 的不存在的 XIM 对象进行释放而造成的。如果不使用 X 下的输入法作为 Emacs 的输入的话,这个问题很好解决,在 ~/.Xresources 里面加入

emacs*UseXIM: false

就可以了。但是通常 Emacs 内置的输入法不如 X 下的输入法好用,这个问题已 经发送到 emacs—multi-tty 的邮件列表,可是至今还没有得到很好的解决。 galilette@Linuxsir 提供了一个解决办法,有些 dirty ,而且可能会导致资源 泄漏,但还是可以忍受的。除了心里面觉得不舒服以外,我还没有真正因为这个 碰到任何问题,即使一直开着 X 几个月后也许会发现可用资源越来越少,系统会 越来越慢,重新起动一下 X 也应该并不是件很难办的事情吧。

galilette@Linuxsir 的方法是这样的,打开 src/xterm.c ,定位到这里

并把这两行注释掉。

编译

接下来就可以编译了4

$ ./configure --without-gtk
$ make bootstrap
$ make
# make install

配置与使用

试用

启动 Emacs (可以以 X 或者非 X 方式启动),并启动 server : M-x server-start 。现在可以去另外一个地方使用 emacsclient 了。扩展后的 emacsclient 支持更多选项,例如, -t 选项告诉 emacsclient 直接在终端里 面打开,而不是建立一个 X 窗口。启动之后会有提示,如果是有文件名作为参 数,编辑完成之后可以使用 C-x # 退出,否则可以使用 C-x 5 0 退出。

一次启动随处运行

在 emacs—multi-tty 的 README 文件中提供了一个很 cool 的脚本,使用 ScreenEmacs 服务器隐藏起来,事实上,只需要在计算机启动的时候启动 Emacs 的 server ,之后就可以一直使用 emacsclient 进行连接,甚至在不同 的 X 会话中,甚至在重新登陆以后。非常舒服。

galilette@Linuxsir 提议说仅仅为了一个从来不会切换到前台进行使用的 Emacs 的 server 而启动一个 Screen 会话对其进行维护太浪费了。使用更轻量 级的 dtach 更舒服一些5。下面就是相关脚本。

首先是 preload-emacs ,用于检查是否有指定的 server 在运行,如果没有, 则启动它。

首先是 emacs—multi-tty README 里面提到的脚本,使用 Screen

这是 galilette@Linuxsir 提议使用 dtach 的脚本。

然后是 connect-emacs

然后分别是 eet

在把 EDITOR 环境变量设置成 et 就可以了。

配合窗口管理器

有很多可定制性很高的窗口管理器,比如 fvwm 、Sawfish 之类的,可以写一个 脚本,调用 emacsclient 的同时叫窗口管理器切换到 Emacs 窗口处,就非常方 便了,使用 Sawfish 的一个例子可以在这里找到。

Footnote

1. 有关 emacs 的 server 模式的更多内容,请参见 Emacs 的手册

2. emacs multi-tty 的扩展主页在这里

3. 关于此的详细内容请参见 elisp 的手册: C-h i m elisp RET m Pure Storage RET

4. 注意这儿要选择 --without-gtk ,因为作者说了,目前对于编译为 gtk 的 模式还有问题,不过 x-toolkit 用什么都无所谓吧,因为平时使用的时候 用到 x-toolkit 的东西并不多嘛。

5. 当我在 Sawfish 里面直接调用(例如使用 run-shell-command) dtach 的时 候,dtach 会报错,说“tcgetattr: inappropriate ioctl for device” , 应该是没有通过一个真正的终端来运行而造成的原因吧。因为我总是使用 Sawfishjump-or-exec 来调用我常用的程序,而且我平时也一直在使用 Screen ,所以我还是使用Screen 的那个脚本而不是 dtach 的那个。