缩写词功能

Emacs 有非常方便的缩写词功能,例如,经常要输入“the National Institute of Standards and Technology”让你非常厌烦,你可以定义一个缩写词“nist”, 这样,每当你输入“nist”然后接着输入空格或者标点符号等的时候就会被 Emacs 自动扩展为“the National Institute of Standards and Technology”。

尝试 Emacs 自带的缩写词功能

打开 minor-mode abbrev-mode 之后,就可以使用缩写词功能了。可以定义全局 的缩写词,也可以定义只针对某一个 mode 的缩写词,这会覆盖掉同名的全局缩 写词。

定义缩写词

可以分别使用 C-x a gC-x a l 来定义全局和针对某个 mode 的缩写词,他 们会从 minibuffer 读取缩写形式,并把当前光标以前的一个或者几个词作为缩 写词的扩展形式,可以通过 C-u 来传递一个数值参数告诉他需要使用几个词。例 如,要定义“find outer otter”的缩写为“foo”,先输入“find outer otter”,然 后键入 C-u 3 C-x a g f o o <RET> 即可。当用 C-u 传入参数零的时候表示使 用选中的区域作为要扩展的形式。反过来,你可以先输入“foo”,然后再键入 C-x a i g 或者 C-x a i l ,通过在 minibuffer 输入扩展后的形式的方法来定 义缩写词,这样的方法不用费心用 C-u 去传递参数,相比之下要方便一些。

要删除一个缩写词,只需要给 C-x a g 或者 C-x a l 传递一个负参数即可,它 会让你输入要删除的缩写词。另外,还可以通过 M-x kill-all-abbrevs 来删除 所有的(包括全局和局部的)缩写词。

使用缩写词

缩写词会在你键入一个不能作为单词的内容的字符的时候得到扩展,换句话说, 任何可以作为单词内容的字符都可以作为缩写词的内容。

缩写词扩展的时候会保留大小写状态,例如:“foo”会扩展为“find outer otter”,“Foo”会扩展为“Find outer otter”,而根据 abbrev-all-caps 变量的 设定,“FOO”会扩展为“FIND OUTER OTTER”或者“Find Outer Otter”。

在没有打开 abbrev-mode 的时候,也可以通过 C-x a e 来手动扩展光标所在出 的缩写词。另外,还可以用 M-x expand-region-abbrevs 来在一个区域进行手工 扩展。

假如你定义了一个缩写词“cnst”扩展为“construction”,现在你希望输入 “recnst”并让他扩展为“reconstruction”。直接输入“recnst”是不行的,这个时 候 M-'(abbrev-prefix-mark) 就起作用了。输入“re”,然后键入 M-' (这个时候 会出现一个连字符)接着再输入“cnst”,之后再输入空格之类的,就可以成功扩展 为“reconstruction”了。

有时候不希望缩写词被扩展,这个时候只需要使用 C-q 来输入缩写词后面的那 个空格或者标点符号即可。

保存缩写词定义

可以分别用 M-x write-abbrev-fileM-x read-abbrev-file 来保存和加载 缩写词定义。如果没有提供文件名,他们会使用变量 abbrev-file-name 所提供 的文件名,默认是 ~/.abbrev_defs 。另外,如果 save-abbrevs 不为 nil 的 话,Emacs 在保存所有文件的时候(例如 C-x s 或者 C-x C-c 的时候)也会把缩 写词保存到 abbrev-file-name 所指定的文件中去。

msf-abbrev.el

简介

msf-abbrev 最初是设计来管理 mode 相关的缩写词的,现在功能已经相当完善, 可以说远远超过了缩写词的功能,在它的主页上有一个动画的 demo ,生动地展 示了他的强大功能。

msf-abbrev 使用目录结构来管理各个 mode 特定的缩写词。例如,把缩写词定 义在 ~/emacs/mode-abbrevs 目录下:

~/emacs/mode-abbrevs
 |
 +---- muse-mode
 |      |
 |      +---- emacs
 |      |
 |      `---- debian
 `---- c-mode
        |
        +---- ifndefx
        |
        `---- fopenx

其中每一个文件就是一个单独的缩写词定义。这样的布局让缩写词管理变得非常 方便。并且缩写词的定义也是使用了一种简单的语法,而不需要指定 Elisp 的 相关细节。

定义缩写词的语法

文件的内容就是缩写词扩展后的内容,不过,下面一些特殊形式会被解释:

<cursor>
表示扩展结束后光标所在的位置。
<varlookup "user-mail-address">
插入 Elisp 变量 user-mail-address 的 值。
<elisp "(insert (current-time-string))">
在当前位置执行引号内的 Elisp 表达式。
<query "what color? ">
在 minibuffer 里面显示引号内的内容,并把用户的 输入作为替换内容。如果有几个相同的 query ,那么只会提问一次,并在后面 的 query 中使用前一次获得的值。
<field "foo">
生成一个叫做 foo 的域,可以使用 TAB 或者 Shift+Tab 在各 个域之间切换。
<choose><choice "foo"><choice "bar"></choose>
生成一个可以选择内容的 域,按 Enter 键并使用方向键即可选择某个选项。
<endpoint>
标记一系列域的结束位置,即 TAB 键最后会到达的位置。
<comment "blah blah">
作为注释,最后会被空内容替换掉。

例如,我定义的 c-mode 的 ifndefx 内容为:

foo.h 中输入 ifndefx 并按下空格键就会扩展为:

安装和配置

可以从主页下载,也可以在这里得到 msf-abbrev.el 的 1.0beta1 版。把他放 到自己的 load-path 所包含的路径里面。并根据自己的需要在 ~/.emacs 里面 加入下面类似的初始化语句:

之后可以手工在相应的目录下面添加缩写词,或者使用 C-c a 动态地给某个 mode 添加缩写词了。另外,在主页上还可以找到通过解析 glibc 的 info 文档 而得到的针对 c-mode 的缩写词包,这也算是一个非常不错的自动完成以及在线 文档功能了。