2008年01月17日

http://pluskid.lifegoo.com 用了很久了,以后会一直用那个。

2006年07月22日

Scsh 简介

与其说 Scsh 是一个 shell ,还不如说他是一个完整的 scheme 的实现。事实上,他是在 Scheme 481 的基础上做出来的,任何现有的 scheme 代码都可以不加修改地在他里面运行2,另外,他还提供了完整的 Posix 接口、完整的网络支持、强大的字符串操、AWK 式的宏、基于 s-expression 表示的正则表达式以及线程支持。相比之下,scsh 和 Emacs 的 elisp 是不同的,elisp 是模拟一个 sh 类似的 shell 语法,再经过转换成为 lisp 代码再执行,而 scsh 则完全使用 lisp 语法,下面是一个例子:

gunzip < paper.tex.gz | detex | spell | lpr -Ppulp & 

在 scsh 里面会被写为:

(& (| (gunzip) (detex) (spell) (lpr -Ppulp)) ; background a pipeline (< paper.tex.gz)) ; with this redirection 

Scsh 作为脚本语言

目前 scsh 并不是专门设计来作为交互使用的,而是主要作为脚本编程之用,目前的版本甚至连最简单的命令行编辑功能都没有,我试验过,确实非常难用,你甚至无法用 Backspace 来删除同一行上刚刚键入的字符。文档里面提供的解决办法是使用 Commander S 作为 scsh 的上层交互界面3,Scsh 文档里面提供的 commander-s 的下载页面已经不能访问了,但是可以在sourceforge 里 scsh 的 cvs 仓库里面找到 commander-s 的源代码下载,目前我可以使用匿名登录的方式通过 cvs 下载到:

cvs -d:pserver:anonymous@scsh.cvs.sourceforge.net:/cvsroot/scsh login cvs -z3 -d:pserver:anonymous@scsh.cvs.sourceforge.net:/cvsroot/scsh \ co -P commander-s 

注意如果提示输入密码,只需直接回车就可以了。在 这里可以找到 commander-s 的一份很不错的文档。要安装 commander-s 的话,还需要其他的东西:

把上面几个包分别装上之后,只要运行 commander-s 目录下的 install.scm 就可以安装上了。

当然还有其他的方法:

  • 使用 Emacs 里面的 cmuscheme 包:键入 C-u M-x runscheme 并在请求程序中键入 scsh 即可。
  • 使用行编辑器 rlwrap ,安装之后可以这样来启动交互:
    rlwrap -c -b '(){}[].,=&^%$#@\;|' scsh 
  • 使用一些有输入输出功能的终端模拟器,例如为 Plan 94 设计的 9term 就是一个例子,他的主页在 http://www.cs.su.oz.au/~matty/9term/index.html – 或者,任何其他可以在里面运行一个子进程的文本编辑器,例如 wily 。

Scsh 作为系统编程语言

Scsh 提供了很多操作系统的底层操作接口,除了信号控制之外,目前的版本完全支持 Posix 并且还有许多非 Posix 扩展,如 sockets 支持等。换句话说,在 Scsh 里面可以使用进程操作、文件读写、目录访问、tty & pty 支持,文件锁定、管道、日期以及环境变量等等所有的操作。这样,就可以使用 scheme 而不是 C 语言来进行系统编程了。

Scsh 作为一个可移植的编程环境

Scsh 是为可移植性而设计的,他在 Scheme 48 的基础上实现。Scheme 48 作为 scheme 的一个字节解释器实现,可以在任何拥有 C 编译器的平台上得到编译。 Scsh 的 OS 接口也是非常具有可移植性的。目前 Scsh 代码可以不加修改地运行在 DEC Ultrix, GNU Hurd, HP-UX, IBM AIX, Linux, NetBSD/i386, NeXTSTEP, SGI IRIX, Solaris 和 SunOS 上,并且移植到其他系统上也并非难事。


1. Jonathan Rees 和 Richard Kelsey 说作的一个 scheme 实现。

2. 只有一个不兼容的地方,就是 symbol 在 scsh 里面是区分大小写的,就是说: (eq? 'symbol 'Symbol) 在 scsh 里面求值会得到 #f ,而在符合 R5RS 的解释器(包含本来的 Scheme 48)上会得到 #t 。

3. 事实上,我觉得任何 shell 都应该这样设计,然后可以做一个通用的交互前端,这样,既减轻了 shell 实现的负担,又让用户从一个 shell 迁移到另外一个 shell 的时候减轻了许多习惯上的痛苦。

4. 引用 Plan 9 wiki 上的一句话:Developed by the people who devised Unix, i.e. Bell Labs, Plan 9 takes OS development back into the realm of research. Plan 9 is an attempt to work on the concept of operating system from the ground up, reworking the whole idea using modern concepts and technology. 关于 Plan 9 的更多东西请参见 http://cm.bell-labs.com/plan9/ 或者也可以自己 google 出更多东西来。

使用简介

template.el 可以让你在创建文件的时候为不同类型的文件指定初始化模板,模板可以包含普通文本以及动态扩展的域。例如,你可以在 ~/.templates/ 目录下包含一个 TEMPLATE.h.tpl 文件:

/* author: (>>>USER_NAME<<<) * date:   (>>>ISO_DATE<<<) */

#ifndef _(>>>FILE_UPCASE<<<)_H#define _(>>>FILE_UPCASE<<<)_H 1

(>>>POINT<<<)

#endif /* _(>>>FILE_UPCASE<<<)_H */

那些 (>>>USER_NAME<<<) 一类的域会动态得到扩展,更多的域可以参见template.el 的文档,也可以通过添加到 template-expansion-alist 来定义自己的域。

template.el 查找模板的方式非常智能,让用户可以为不同的工程、不同类型的文件甚至是某一个特殊的文件指定不同的模板,文档里面有一个例子:

  • 你有一个工程目录 ~/proj/ 以及子目录 foo/bar/ ,他们都包含 .java类型的文件。
  • 你想为工程里面的 .java 文件定义一个一般的模板,同时,为子目录 foo/里面的 .java 文件定义另外一个模板。你还想为工程里面的所有文件名为proj.java 的文件定义一个单独的模板。
  • 为了避免让模板文件把你的工程目录搞得一团糟,你首先创建一个< code>~/proj/Templates/ 目录,并把一般模板的 TEMPLATE.java.tplproj.java.tpl 放到这里面。同时,在 ~/proj/foo/ 目录里面创建用于这个子目录的模板文件 TEMPLATE.java.tpl

     

template.el 还有其他功能,详细可以参见他的文档。

和 ido 一类的包协同工作

如果使用 ido 的话,会发现用 ido 的 ido-find-file 来打开文件并不会触发模板扩展,查看文档可以看出,应该修改一下 template-find-file-commands 。可是把 ido-find-file 加到里面并不管用,查看了一下 template 的源代码可以发现,template.el 工作的方式大概是这样的,他通过加入 hook 到find-file-not-found-hooks (事实上,这个变量已经在版本 22.1 里面不鼓励使用了,取而代之的是 find-file-not-found-functions) ,在新建一个文件的时候他提供的 hook 将会被调用,这个时候他判断 this-command ,看他是否在变量 template-find-file-commands 里面,如果在里面,那么就会执行 template的相应工作了。而我跟踪发现 `ido-find-file’ 执行之后 this-command 的值事实上是 ido-exit-minibuffer ,因此这儿必须这样设置才会生效:

(add-to-list 'template-find-file-commands         'ido-exit-minibuffer)
2006年05月10日

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

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

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/emacs/manual/html_node/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* 的,也就是直接用命令:

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

./configure --without-gtk
make bootstrap
make
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年05月07日

你可以显式地为当前的 buffer 选择一个 mode ,但是其实大多数情况 Emacs 会
根据文件名以及出现在文件里面的特殊字符自动选择对应的 mode 。

要显式地选择一种 mode ,可以使用 “M-x” 命令,mode 的名字加上 “-mode” 就
是设置这个 mode 的命令。例如 “M-x lisp-mode” 可以打开 Lisp mode 。

当你访问一个文件的时候,Emacs 一般会根据文件名自动选择正确的 mode ,例
如:当你打开一个文件名以 “.c” 结尾的文件时,会自动进入 C mode 。文件名
和 mode 之间的对应关系是由变量 "auto-mode-alist" 来控制的。它是一个表,
表里面的每一个元素有这样的形式:

(REGEXP . MODE-FUNCTION)

或者是这种形式

(REGEXP MODE-FUNCTION FLAG)

例如,表里面有一个元素为 ("\\.c\\’" . c-mode) 所以文件名以 “.c” 结尾的
文件会使用 C mode 。如果是第二种形式,并且 FLAG 不是 nil ,那么在调用
了 MODE-FUNCTION 之后,匹配到 REGEXP 的后缀将会被丢弃,并继续寻找下一
个匹配。

你也可以在文件的第一个非空白行添加一些特殊的文本告诉 Emacs 对这个文件
使用某个特定的 mode 。这一行应该包括 ``-*-MODENAME-*-'' 的形式,也允许
其他字符出现在这一行,例如:

;-*-Lisp-*-

告诉 Emacs 在这儿使用 Lisp mode 。这种显式地指定将覆盖通过文件名来选择
的 mode 。另外一种形式是:

-*- mode: MODENAME;-*-

这样你可以像这样指定一些局部变量:

-*- mode: MODENAME; VAR: VALUE; ... -*-

当一个文件的内容以 “#!” 开始,他将被当作 Shell Script 。当你访问这样的
文件而他的文件名有没有对应的 major mode 的时候,Emacs 使用第一行的解释
器的名字来选择 mode ,例如 “perl” 、“tcl” 、“bash” 等。Emacs 会选择合
适那个解释器的 mode 。这样的选择是由变量 “interpreter-mode-alist” 来控
制的。

当一个文件的内容以 “#!” 开始的时候,你无法在第一行以 ``-*-'' 的形式来指
定 mode ,因为这样会使 “#!” 的功能失效。这个时候 Emacs 会查看第二行是
否有 ``-*-'' 的指定 mode 的指令。

当你访问一个没有指定 mode 的文件,或者使用 “C-x b” 来创建一个新的
buffer 的时候,变量 “default-major-mode” 将指定使用哪个 mode 。他的值
一般是 “fundamental-mode” 。如果这个变量的值是 nil ,major mode 将会根
据前一个 current buffer 来选取。

当你改变了一个 buffer 的 mode 的时候,你可以用 "M-x normal-mode" 来让
Emacs 自动选择 mode 。这也正是 “find-file” 调用来设置 mode 的方法,它
还会处理文件相关的局部变量 (如果有的话) 。

调用命令 “C-x C-w” 和 “set-visited-file-name” 之后如果新的文件名对应一
个 mode ,那么 Emacs 将进入这个 mode 。但是如果 buffer 的内容指定了一个
mode ,这种情况不会出现。而且,有些 major mode 不允许改变 mode 。你可
以把变量 “change-major-mode-with-file-name” 设定为 nil 来关闭这个特性。


by Sydney J. Harris

I walked with my friend to the newsstand the other night, and he
bought a paper, thanking the newspaper politely. The vendor didn’t
even acknowledge it.

“A sullen fellow, isn’t he?” I commented.

“Oh, he’s that way every night,” shrugged my friend.

“Then why do you continue to be so polite to him?” I asked.

“Why not?” inquired my friend. “Why should I let him decide how I’m
going to act?”

As I thought about this incident later, it occurred to me that the
important word was “act”. My friends acts toward people; most of us
react toward them.

He has sense of inner balance which is lacking in most of us; he knows
who he is, what he stands for, how he should behave. He refuse to
return incivility from incivility, because then he would no longer be
in command of his own conduct.

When we are enjoined in the Bible to return good for evil, we look
upon this as a moral injunction — which it is. But it is also a
psychological prescription for our emotional health.

Nobody is unhappier than the perpetual reactor. His center of
emotional gravity is not rooted within himself, where it belongs, but
in the world outside him. His spiritual temperature is always being
raised or lowered by the social climate around him, and he is a mere
creature at the mercy of there elements.

Praise gives him a feeling of euphoria, which is false, because it
does not last and it does not come from self approval. Criticism
depresses him more than it should, because it confirms his own
secretly shaky opinion of himself. Snubs hurt him, and the merest
suspicion of unpopularity in any quarter rouses him to bitterness.

A serenity of spirit cannot be archieved until we become the masters
of our own actions and attitudes. To let another determine whether we
shall be rude or gracious, elated or depressed, is to relinquish
control over our own personalities, which is ultimately all wo
possess. The only true possession is self-possession.

2006年05月06日

Emacs 里面的 shell 和 eshell 默认都没有过滤掉颜色控制字符,如果使用 /bin/ls –color 的话显示会乱七八糟。有个解决办法就是使用 ansi-color.el 。在自己的 ~/.emacs 里面写上:

;; shell 和 eshell 相关设置

;; 让 shell mode 可以正常显示颜色
(autoload 'ansi-color-for-comint-mode-on "ansi-color" nil t)
(add-hook 'shell-mode-hook 'ansi-color-for-comint-mode-on)

(require 'ansi-color)
;; eshell 的颜色
;; 这样可以显示颜色,但是当在文件很多的目录里面显示的时候
;; 会很慢
;(add-hook 'eshell-preoutput-filter-functions
;         'ansi-color-apply)
;; 这样直接把颜色滤掉
(add-hook 'eshell-preoutput-filter-functions
          'ansi-color-filter-apply)

就可以正确过滤颜色控制字符了。

早上起来看到 Linuxsir 上面有个贴说 stardict 的网站上有新的辞典了,赶紧去下了一些下来,感觉不错。突发奇想想在 Emacs 里面弄个查辞典的功能,记得王垠的网站上有介绍的,看了下,好像是用什么 dictd 来查的,那个东西我不会用,而且好像没有英汉辞典的样子,想想反正系统里面装了 stardict ,为何不直接用它来查呢?于是就查了一下关于 tooltip 以及 shell-command 相关的资料,写了这个小东西:

;; author: pluskid
;; 调用 stardict 的命令行接口来查辞典
;; 如果选中了 region 就查询 region 的内容,
;; 否则就查询当前光标所在的词
(global-set-key [mouse-3] 'kid-star-dict)
(defun kid-star-dict ()
(interactive)
(let ((begin (point-min))
(end (point-max)))
(if mark-active
(setq begin (region-beginning)
end (region-end))
(save-excursion
(backward-word)
(mark-word)
(setq begin (region-beginning)
end (region-end))))
;; 有时候 stardict 会很慢,所以在回显区显示一点东西
;; 以免觉得 Emacs 在干什么其他奇怪的事情。
(message "searching for %s ..." (buffer-substring begin end))
(tooltip-show
(shell-command-to-string
(concat "sdcv -n "
(buffer-substring begin end))))))

呵呵!效果还不错的,不过只是自己玩玩,因为 stardict 本身就带有屏幕取词的功能的。但是如果在 Emacs 里面查询的话,就不用另外开一个 stardict 了,而且可以绑定到自己喜欢的快捷键。呵呵!效果如图,还不错吧?


是否 kill-ring 里面有太多的东西?每次 C-y 之后都 M-y M-y M-y … N 次才找到想要的东西呢?很不爽是吧?那试试 browse-kill-ring.el 吧!这是一个让你能够浏览你的 kill-ring 的东西,他还有一个增强插件 browse-kill-ring+.el ,让我们来试用一下吧:
把两个文件下载到你的 load-path 里面,然后在 ~/.emacs 里加上:

;; browse-kill-ring 功能
(require 'browse-kill-ring)
(require 'browse-kill-ring+)
(global-set-key (kbd "C-c k") 'browse-kill-ring)

重新打开 Emacs 就可以用 browse-kill-ring 的功能了。现在先 kill 一些东西填填自己的 kill-ring 吧。然后,调出 browse-kill-ring ,我们把他绑定到了 C-c k 上面。看到新打开了一个窗口,在这里就可以随意浏览你 kill-ring 里面的内容了。下面列出了一些常用的功能:

1. RET 插入当前 kill-ring 的内容并关闭 browse-kill-ring 的窗口
2. U 在原来那个窗口里面执行 Undo 命令
3. e 编辑当前 kill-ring 项,编辑完之后按 C-c C-c 提交修改
4. d 输出当前 kill-ring 项
5. n 往前移动
6. p 往后移动
7. s 往前搜索
8. r 往后搜索
9. i 插入当前 kill-ring 项
10. y 插入当前 kill-ring 项
11. a 在末尾添加当前 kill-ring 项
12. b 在开头插入当前 kill-ring 项
13. o 插入当前 kill-ring 项,并把它提升到 kill-ring 的首部
14. u 同上,但是插入之后关闭 browse-kill-ring 窗口
15. x 插入当前 kill-ring 项,并把它从 kill-ring 中删除
16. <mouse-2>  插入鼠标选中的内容

最后,你可以用 ? 或者 h 来获取当前 mode 的描述,当然也就可以获得各命令的说明。而 browse-kill-ring+.el 为我们提供的功能是 toggle-browse-kill-ring-display-style ,绑定到 t 上,他可以让你选择在显示 kill-ring 的内容的时候是按原来的格式显示还是每个 kill-ring 项显示一行。值得注意的一点是,调用 browse-kill-ring 的时候他会记住你调用他的时候所在的那个窗口,如果你在这之后改变了窗口布局,然后在到 browse-kill-ring 的窗口里面去执行插入操作之类的,会把他搞迷糊,通常,他会显示一条错误信息。
怎么样?方便吗?Just Enjoy! :)

浏览邮件列表的时候经常看到有人发表这样的小框,很漂亮:

,----[ foo bar ]
| text in the box
| looks beautiful
`----

也想自己弄一个,于是写了段 elisp 小代码,用来在 Emacs 里面把选中的区域加上边框,elisp 代码如下:

(defun kid-box-region (begin end title)
  (interactive "r\nsBox Title: ")
  (let ((old-buffer (current-buffer)))
    (switch-to-buffer (get-buffer-create "*kid-box-region-output*"))
    ;; 删除以前的内容,为防止误删东西,把他放在 kill-ring 里面
    (kill-region (point-min) (point-max))
    (insert-buffer-substring old-buffer begin end)
    (goto-char (point-min))
    (insert ",----------[ " title " ]\n")
    (replace-regexp "^" "| ")
    (goto-char (point-max))
    ;; 检查最后是否有换行
    (if (search-backward-regexp "^| $" (point-min) t)
         (delete-char 2)
       (insert "\n"))
    (insert "`----------\n")))

处理之后会变成这样,因为 lisp 缩进很多,为了变漂亮一点,我决定多加几个“-”:

,----------[ kid-box-region ]
| (defun kid-box-region (begin end title)
|   (interactive "r\nsBox Title: ")
|   (let ((old-buffer (current-buffer)))
|     (switch-to-buffer (get-buffer-create "*kid-box-region-output*"))
|     ;; 删除以前的内容,为防止误删东西,把他放在 kill-ring 里面
|     (kill-region (point-min) (point-max))
|     (insert-buffer-substring old-buffer begin end)
|     (goto-char (point-min))
|     (insert ",----------[ " title " ]\n")
|     (replace-regexp "^" "| ")
|     (goto-char (point-max))
|     ;; 检查最后是否有换行
|     (if (search-backward-regexp "^| $" (point-min) t)
|          (delete-char 2)
|        (insert "\n"))
|     (insert "`----------\n")))
`----------

这下我也可以有漂亮的 box 了! :)