LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 3901|回复: 33

加速你的Emacs!

[复制链接]
发表于 2006-5-10 23:08:08 | 显示全部楼层 |阅读模式
排版好累的,排好版的版本请看我的 blog 吧 :p :
http://blog.donews.com/pluskid/archive/2006/05/10/863831.aspx

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

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

用 emacsclient 来连接 emacs server
这个方法首先要有一个启动好了的 Emacs ,并且要已经启动了 server 模式, 你可以用 M-x start-server 来启动 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 那里 去,比较麻烦。
1. 有关 emacs 的 server 模式的更多内容,请参见 http://www.gnu.org/software/emac ... e/Emacs-Server.html

使用 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 。所以如 果用了这个补丁,使用 emacsclient 的时候会自动打开新的窗口而不是在 emacs 的 server 里面打开,然后再手工切换到 server 那里。
要使用这个补丁版本的 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

不过我这儿下载速度实在是慢得可以,作者还提供了一个仓库,说是用 bazzar 软件来获取仓库的文件的,不过我连那个仓库好像根本没有下载下来任何东西, 我同时用 baz 连那个仓库,并到 Emacs 的仓库用 cvs 去 check out 出来一个 完整的源码树,结果 Emacs 都 check out 完了,这边还没有任何反应。不过作 者还提供了针对 emacs cvs 仓库的源码树的补丁文件,可以在 http://lorentey.hu/downloads/emacs/multi-tty 找到补丁文件,然后把他们 打到 check out 出来的 emacs 的源码树上面去。我看到补丁文件里面好像是针 对 emacs 22.0.5* 的,也就是直接用命令:

  1. cvs -z3 -d:pserver:anonymous@cvs.savannah.gnu.org:/cvsroot/emacs co emacs
复制代码

check out 出来的版本,至于那个 unicode 的 branch ,也就是传说中的 emacs 23 我并没有试过。然后下载你 check out 出来的日期对应的补丁,如果 没有对应的,那么相近的日期的补丁应该问题也不大的了,尽量相近就可以了。 然后到 emacs 的目录里面去,打上补丁:
cd emacs
patch -p 1 < ../emacs--multi-tty--0--patch-555.2006-05-05.patch

现在补丁打上了,我们还需要再稍微 hack 一下才编译,要不然会有一点错误的, 打开 src/pursize.h 把定义的 PURESIZE 改大一点,否则编译好之后启动 emacs 会产生 warning 说 ``Building Emacs overflow pure space'' 2 。 我是把 #define PURESIZE_RATIO 1 改成了 #define PURESIZE_RATIO 4 之后就 没有错误了,如果你想自己看看到底是什么错误,你可以先不修改,然后直接编 译,运行一下,看看如果出错了再修改,因为只修改一处小的地方对于重新 make 来说只会影响到一小部分,速度很快的。事实上,因为 emacs 启动的时候 有一部分只读的不可扩展的内存,因为这儿用了 multi-tty 补丁,导致预先定 义的那些内存无法容纳下所有的预加载库,于是只有动态分配,所以会在启动的 时候产生 warning ,所以说也不能说是一个错误,但是我是个完美主义者,所 以想要去掉那个 warning 。OK!hack 之后就可以编译安装了: 3

  1. ./configure --without-gtk
  2. make bootstrap
  3. make
  4. make install
复制代码

现在,启动你安装好的 emacs ,在启动 server 模式: M-x server-start 。 然后到另外一个地方去用 emacsclient:
emacsclient file
在新的 X frame 中打开文件进行编辑,编辑完成后用 C-x # 完成编辑并关闭 frame
emacsclient -t file
在当前终端下打开文件进行编辑(类似于 emacs -nw 的效果),编辑完之后用 C-x # 完成编辑并关闭
emacsclient
打开一个空的 X frame ,使用 C-x 5 0 关闭
emacsclient -t
不用解释了吧?
注意这下所有的打开的 frame 或者是终端界面的 emacs 其实都是同一个 session 的,你在任意一个里面用 C-x C-c 都会导致所有的 frame 关闭退出哟! 另外,如果你真的打算几个月开着 Emacs ,而又不想让自己的 Emacs 被一大堆 乱七八糟的 buffer 给填满,也许你可以试一下 Midnight mode ,详细请看 Emacs 的手册: C-h i m Emacs RET m Kill Buffers RET 。
2. 关于此的详细内容请参见 elisp 的手册:C-h i m elisp RET m Pure Storage RET
3. emacs multi-tty 的扩展主页在 http://lorentey.hu/project/emacs.html.en
4. 注意这儿要选择 --without-gtk ,因为作者说了,目前对于编译为 gtk 的 模式还有问题,不过 x-toolkit 用什么都无所谓吧,因为平时使用的时候 用到 x-toolkit 的东西并不多嘛。
感谢 galilette 向我推荐 multi-tty 的补丁。
感谢 herberteuler 向我推荐 Midnight mode 。
发表于 2006-5-11 02:42:09 | 显示全部楼层
u're welcome, pluskid

I bet you haven't read the README from the multi-tty patch. The author actually provided two very useful shell script: preload-emacs and connect-emacs (see below) to keep an emacs-server running in a detached GNU Screen session ( http://www.gnu.org/software/screen/ ). This way you have your emacs server running through different X sessions or even after logging off. This is what I meant `one startup per boot' in the other post.

As to c-x c-c. I think it is now bound to save-buffer-kill-terminal by default, instead of save-buffer-kill-emacs for the unpatched branch. so there is no risk invoking it -- only killing the last terminal will you kill the whole emacs, and if u use screen, as is described above, there is hardly a chance.

btw, I myself use dtach ( http://dtach.sourceforge.net/ ) instead. screen is great, but it's an overkill for maintaining a server frame in background that i'll never visit.

below are the mentioned scripts.
preload-emacs (adapted for dtach):
#!/bin/bash
# Usage: preload-emacs <name> [<waitp>]
#
# Preloads the Emacs instance called NAME in a detached screen
# session.  Does nothing if the instance is already running.  If WAITP
# is non-empty, the function waits until the server starts up and
# creates its socket; otherwise it returns immediately.

name="$1"
waitp="$2"
dtachdir=~/.dtach_socks #pick up your own
screendir="/var/run/screen/S-$USER"
serverdir="/tmp/emacs$UID"
emacs="/usr/local/bin/emacs" # Or wherever you installed your multi-tty Emacs

if [ -z "$name" ]; then
    echo "Usage: preload_emacs <name> [<waitp>]" >&2
    exit 1
fi

#if [ ! -e "$screendir"/*."$name" ]; then
if [ ! -e "$dtachdir"/"$name" ]; then
    if [ -e "$serverdir/$name" ]; then
        # Delete leftover socket (for the wait option)
        rm "$serverdir/$name"
    fi
#    screen -dmS "$name" "$emacs" -nw --no-splash --eval "(setq server-name \"$name\")" -f server-start
    dtach -n "$dtachdir"/"$name" "$emacs" -nw --no-splash --eval "(setq server-name \"$name\")" -f server-start
fi
if [ ! -z "$waitp" ]; then
    while [ ! -e "$serverdir/$name" ]; do sleep 0.1; done
fi

and connect-emacs (intact)
#!/bin/bash
# Usage: connect-emacs <name> <args>...
#
# Connects to the Emacs instance called NAME.  Starts up the instance
# if it is not already running.  The rest of the arguments are passed
# to emacsclient.

name="$1"
shift
   
if [ -z "$name" ]; then
    echo "Usage: connect_emacs <name> <args>..." >&2
    exit 1
fi
preload-emacs "$name" wait
/usr/local/bin/emacsclient -s "$name" "$@"

and I also have 'e' for x display client and 'et' for terminal client at hand, haha both shorter than 'vim'
~/bin/e:
#!/bin/bash
connect-emacs editor $@
~/bin/et:
#!/bin/bash
connect-emacs editor -t $@
回复 支持 反对

使用道具 举报

发表于 2006-5-11 10:17:01 | 显示全部楼层
顺便说明一下,如果是为了编辑配置文件而单独打开新的 Emacs 进程,并且用户并未(在 .emacs 中)改变移动光标命令的快捷键,可以用这个命令来快速地打开 Emacs(受 pluskid 所说 -Q 的启发):
  1. emacs -nw -Q --eval="(progn (global-font-lock-mode 1) (require 'generic-x) (require 'conf-mode))"
复制代码

但如果想编辑邮件,可能就不合适了。

不过,使用 Tramp 来编辑配置文件,然后用 sudo 在 Emacs 的 Shell 中应用修改似乎更快。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-5-11 13:16:32 | 显示全部楼层
to galilette:
:p 呵呵!我确实没有仔细看作者的说明文档,恩,看来好好看看会更好用。呵呵!我也有“e”和 "et" 的alias的,呵呵!

to herberteuler:
恩,TRAMP确实是非常不错的功能,不过目前还没有完全在 eshell 里面工作,其实在 eshell 里面可以有这样的绑定:

  1. alias v view-file $1
  2. alias e find-file $1
复制代码

也是很方便的,不过我现在用一个很方便的终端:yakuake ,暂时还不能完全用 eshell 的,嘿嘿!
回复 支持 反对

使用道具 举报

发表于 2006-5-11 13:49:58 | 显示全部楼层
我也用不惯 EShell,我用的是 M-x term 和 M-x shell 得到的 Shell。M-x term 得到的 Shell 甚至可以在其中运行 vim,呵呵。最绝的是,还可以再运行 Emacs,再执行 M-x term,再运行 Emacs,……无穷无尽。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-5-11 15:39:37 | 显示全部楼层
Post by herberteuler
我也用不惯 EShell,我用的是 M-x term 和 M-x shell 得到的 Shell。M-x term 得到的 Shell 甚至可以在其中运行 vim,呵呵。最绝的是,还可以再运行 Emacs,再执行 M-x term,再运行 Emacs,……无穷无尽。

哈哈!嵌套之后快捷键都乱啦!都退不出来了!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-5-11 16:39:16 | 显示全部楼层
Post by galilette
u're welcome, pluskid

I bet you haven't read the README from the multi-tty patch. The author actually provided two very useful shell script: preload-emacs and connect-emacs (see below) to keep an emacs-server running in a detached GNU Screen session ( http://www.gnu.org/software/screen/ ). This way you have your emacs server running through different X sessions or even after logging off. This is what I meant `one startup per boot' in the other post.

As to c-x c-c. I think it is now bound to save-buffer-kill-terminal by default, instead of save-buffer-kill-emacs for the unpatched branch. so there is no risk invoking it -- only killing the last terminal will you kill the whole emacs, and if u use screen, as is described above, there is hardly a chance.

btw, I myself use dtach ( http://dtach.sourceforge.net/ ) instead. screen is great, but it's an overkill for maintaining a server frame in background that i'll never visit.

below are the mentioned scripts.
preload-emacs (adapted for dtach):


and connect-emacs (intact)


and I also have 'e' for x display client and 'et' for terminal client at hand, haha both shorter than 'vim'
~/bin/e:

~/bin/et:

不是很明白作用是什么, 难道就是在后台启动一个 -nw 的 Emacs ,之后一直在前台通过 emacsclient 打开?可是我前台打开一个窗口,然后退出,不管是用C-x C-c 退出还是用C-x 5 0 关闭窗口,然后再启动 e ,他还会在启动一次 server ,按理说,后台应该还有一个最初启动的 -nw 的 emacs 在运行呀,怎么会就退出了呢?如果是这样的话,似乎没有达到想要的效果呀?还有一个奇怪的地方就是我明明在 .emacs 里面写了 (tool-bar-mode -1) 可是用这样的方法启动之后 tool-bar 居然出来了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-5-11 16:54:15 | 显示全部楼层
Post by pluskid
不是很明白作用是什么, 难道就是在后台启动一个 -nw 的 Emacs ,之后一直在前台通过 emacsclient 打开?可是我前台打开一个窗口,然后退出,不管是用C-x C-c 退出还是用C-x 5 0 关闭窗口,然后再启动 e ,他还会在启动一次 server ,按理说,后台应该还有一个最初启动的 -nw 的 emacs 在运行呀,怎么会就退出了呢?如果是这样的话,似乎没有达到想要的效果呀?还有一个奇怪的地方就是我明明在 .emacs 里面写了 (tool-bar-mode -1) 可是用这样的方法启动之后 tool-bar 居然出来了。

恩,工具栏的问题是因为 server 以 -nw 启动,但是具体为什么这样会导致工具栏出现我还不知道是怎么回事。

还有就是我手工看了一下,用
  1. emacs -f server-start
复制代码

启动server一切正常。
不过如果以 -nw 方式启动,这儿还没有用到 dtach 的地方,启动 server 之后,用 emacsclient 去连接,然后在 emacsclient 里面退出,再过去看启动 server 的那个终端,已经退出了,显示:

  1. Fatal error (11)Segmentation fault (core dumped)
复制代码

产生的 core 文件用什么看呀? gdb 好像不行的。他说:

  1. $ gdb --core=core
  2. ...
  3. "/home/kid/core" is not a core dump: File format not recognized
复制代码
回复 支持 反对

使用道具 举报

发表于 2006-5-11 17:32:04 | 显示全部楼层
Post by pluskid
不是很明白作用是什么, 难道就是在后台启动一个 -nw 的 Emacs ,之后一直在前台通过 emacsclient 打开?可是我前台打开一个窗口,然后退出,不管是用C-x C-c 退出还是用C-x 5 0 关闭窗口,然后再启动 e ,他还会在启动一次 server ,按理说,后台应该还有一个最初启动的 -nw 的 emacs 在运行呀,怎么会就退出了呢?如果是这样的话,似乎没有达到想要的效果呀?还有一个奇怪的地方就是我明明在 .emacs 里面写了 (tool-bar-mode -1) 可是用这样的方法启动之后 tool-bar 居然出来了。


First, about the toolbar thing. I'm not sure why this won't work, maybe it is bypass if called from a tty frame, which the server frame is.

One way to do customization based on tty type (i.e., x display or tty) is by setting the window-system-default-frame-alist variable. e.g., mine is something like
(setq window-system-default-frame-alist
      '(
        ;; if frame created on x display
        (x
         ;; mouse
         (mouse-wheel-mode . 1)
         (mouse-wheel-follow-mouse . t)
         (mouse-avoidance-mode . 'exile)
         ;; face
         (font . "-*-terminus-medium-*-*-*-14-*-*-*-*-*-*-*")
         (foreground-color . "snow")
         (background-color . "dark slate gray")
         (cursor-color . "orange")
         )
        ;; if on term
        (nil
         (background-color . "black")
         (foreground-color . "white")
         )))

you can add a line like
(tool-bar-lines . 0)

in the x section to suppress your toolbar explicitly in x frames

second about the c-x c-c thing. do your tty server frame segfault when it quit? what if you start more than 1 x frame clients? Is the server frame quitting when you close any of them or only the last of them ?
回复 支持 反对

使用道具 举报

发表于 2006-5-11 17:39:59 | 显示全部楼层
ok I see

then you are having the same problem as I had.

In short this seems to be caused by refering to an XIM object of the server frame, which doesn't exist.

If you can stand with the chinese input methods built into the leim pack, then you can simply add a line in your ~/.Xresource
emacs*UseXIM: false

otherwise, open emacs/src/xterm.c, and comment out the following lines
/*      if (dpyinfo->display)
        XCloseIM (dpyinfo->xim);*/
I know it is quite dirty never to release the XIM mem back to the OS. but at least for me, restarting X once a while is no big deal.

Hope this can be of some help
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表