Vim 宏,用于编辑 DocBook 文档
最近,在帮助 Linux Journal 将其编辑流程转换为使用 DocBook/XML 处理文章的过程中,我有机会转换一些旧的 Vim 宏,以便在新流程中使用。最初的宏是用于插入 Quark 标签和特殊字符的快捷键或缩写。新的编辑流程包括在 DocBook/XML 中标记文档。然后,应用样式表将文档转换为 Quark,以便在印刷杂志中发布,或转换为 HTML,以便在网站上发布。
DocBook 存在两种基本形式:SGML 版本和较新的 XML 版本。DocBook 是一种类似于 HTML 的标记语言。它使用带有属性的标签和 & 符号序列来指定特殊字符和符号。清单 1 包含一篇简短的 DocBook/XML 文章。
清单 1. DocBook/XML 文章示例
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?> <!DOCTYPE article SYSTEM "docbookx.dtd"> <article> <!-- Article information. --> <articleinfo> <!-- Article title and abstract. --> <title>This is an Uninteresting Sample article</title> <abstract> <para>This article isn't about anything interesting.</para> </abstract> <!-- Author name and bio. --> <author> <firstname>John</firstname> <surname>Doe</surname> <authorblurb> <para>The author is not a very interesting person.</para> </authorblurb> </author> </articleinfo> <!-- Body of article. --> <simplesect> <title>This is the first of thankfully only one uninteresting section.</title> <para>True to form this is not very interesting either.</para> </simplesect> </article>
如您所见,文章结构与 HTML 类似,只是标签名称不同。DOCTYPE 行引用了用于验证文件的 DTD(文档类型定义)。要编写有用的 DocBook,您需要 DTD 和一个程序来验证您的文档,以便确定它是否包含任何 DocBook 或 XML 错误。请参阅本文末尾的“资源”部分,了解可以获取 DTD 和文档验证程序的网站。
Vim 主要是一个与原始 vi 编辑器兼容的替代品,vi 编辑器随许多 UNIX 系统一起提供。Vim 还包含许多增强功能,包括功能强大的宏/脚本语言和 GUI 版本。大多数 Linux 发行版都应该包含 Vim。Vim 是一种模式文本编辑器;也就是说,按键的含义取决于您是输入文本还是操作文本。
用于我们项目的 Vim 宏集包含在以下文件中
tagtmps.vim:包含标签模板。标签模板是开始和结束标签以及一些可以插入到您正在编辑的文件中的预定义内容。
tfuncs.vim:包含用于操作标签的函数。函数可用于插入、删除、移动和更改标签。
mfuncs.vim:包含辅助设置 Vim 快捷键映射的函数。
maps.vim:使用上面定义的映射函数来定义用于访问上面定义的标签函数的快捷键映射。
要使用这些文件,请启动 vi 并输入
:so tagtmps.vim :so tfuncs.vim :so mfuncs.vim :so maps.vim
但是,通常情况下,您会将这些命令放在一个文件中,并在进入 vim 时仅 source 它。例如,将上述文件放在您主目录中名为 vim 的子目录中。然后,在名为 editdb.vim 的文件中放入以下几行
so ~/vim/tagtmps.vim " Tag templates. so ~/vim/tfuncs.vim " Tag functions. so ~/vim/mfuncs.vim " Map functions. so ~/vim/maps.vim " Key mappings.
现在,启动 vi 并输入以下命令以使用一个命令加载所有文件:so ~/editdb.vim. 另一种选择是在您的 .vimrc 文件中 source 这些文件,以便在您每次启动 vim 时都加载它们。您的 .vimrc 文件位于您的主目录中。
一旦这些文件被 vim 读取和处理,宏就会绑定到键盘。宏提供以下功能
插入标签模板。
插入开始标签。
插入结束标签。
通过将单词放在开始标签和结束标签之间来标记单词。
使用开始标签和结束标签标记一系列行。
更改标签。
插入特殊符号,例如版权符号。
插入特殊字符,例如带重音符号的字符。
删除光标下的标签。
将光标移动到前一个(后一个)标签的左侧(右侧)。
将标签移动到前一个(后一个)单词的左侧(右侧)。
删除标签左侧或右侧的空格。
在标签的左侧或右侧插入空格。
宏绑定到功能键(F 键),后跟零个、一个或两个修饰符字符。功能键指定为 <FN>,其中 N 是功能键编号。Shift 功能键指定为 <S-FN>。快捷键映射在表 1-4 中详细说明如下。
表 1. 快捷键映射
快捷键序列 | 映射 |
---|---|
<F2>标签键 | 插入标签模板。插入与文档中指定的标签键对应的标签模板。有关已定义的标签键列表,请参阅表 2。 |
<F3>符号键 | 插入符号字符。插入与文档中指定的符号键对应的符号字符。最常见的情况是,这会插入符号的 DocBook/XML 实体引用。有关已定义的符号键列表,请参阅表 3。 |
<F4>外文字符键 | 插入外文字符。将与指定的外文字符键对应的外文字符插入到文档中。有关已定义的外文字符键列表,请参阅表 4。 |
<F5>标签键 | 插入开始标签。插入与指定的标签键对应的开始标签。 |
<F6>标签键 | 插入结束标签。插入与指定的标签键对应的结束标签。 |
<F7>标签键 | 标记单词。如果光标位于单词上,则将与指定的标签键对应的标签放在单词周围。 |
<F7>标签键 | 标记范围(命令模式)。当指定一系列行时,这会将与指定的标签键对应的标签放在这些行周围。注意:这在命令模式下完成;输入冒号,后跟快捷键序列。 |
<F8>标签键 | 更改标签。如果光标位于标签上,则将标签更改为与指定的标签键对应的标签。 |
<F9> | 向左按标签移动光标。如果光标位于标签上,则移动到标签的开头(到 <)。如果光标不在标签上,则移动到光标左侧的下一个标签的开头。 |
<F10> | 将标签移动到前一个单词的左侧。如果光标位于标签上,则将标签移动到前一个单词的左侧。换句话说,如果光标位于开始标签上,则扩展标记内容量以包括标签左侧的单词。如果光标位于结束标签上,则从标记内容中删除标签左侧的单词。 |
<F11> | 将标签移动到后一个单词的右侧。如果光标位于标签上,则将标签移动到后一个单词的右侧。换句话说,如果光标位于开始标签上,则从标记内容中删除标签右侧的单词。如果光标位于结束标签上,则扩展标记内容量以包括标签右侧的单词。 |
<F12> | 向右按标签移动光标。如果光标位于标签上,则移动到标签的末尾(到 >)。如果光标不在标签上,则移动到光标右侧的下一个标签的末尾。 |
<S-F8> | 删除标签。如果光标位于标签上,则删除该标签。 |
<S-F9> | 删除标签左侧的空格。如果光标位于标签上,则删除标签左侧的任何空格。 |
<S-F10> | 在标签左侧插入一个空格。如果光标位于标签上,则在标签左侧插入一个空格。 |
<S-F11> | 在标签右侧插入一个空格。如果光标位于标签上,则在标签右侧插入一个空格。 |
<S-F12> | 删除标签右侧的空格。如果光标位于标签上,则删除标签右侧的任何空格。 |
以下键与功能键 <F2>、<F5>、<F6>、<F7> 和 <F8> 组合使用。功能键确定操作;后面的键确定标签。
表 2. 标签键
键 | 对应的标签 |
---|---|
a | <article> |
b | <emphasis role="bold"> |
c | <command> |
d | <entry> |
e | <email> |
f | <function> |
h | <title> |
i | <emphasis> |
jd | <remark role="web-pub-date"> |
ji | <remark role="author-image"> |
jl | <remark role="layout-info"> |
jn | <remark role="article-number"> |
jo | <remark role="output-file"> |
jp | <remark role="pull-quote"> |
js | <remark role="article-section"> |
jt | <remark role="teaser"> |
jw | <remark role="article-series"> |
k | <command role="what-to-type"> |
l | <listitem> |
m | <mediaobject> |
n | <itemizedlist> |
o | <orderedlist> |
p | <para> |
q | <quote> |
r | <row> |
s | <sidebar> |
t | <table> |
u | <ulink> |
xa | <author> |
xb | <blockquote> |
xc | <![CDATA[ |
xf | <firstname> |
xi | <articleinfo> |
xl | <surname> |
xm | <othername role="middle"> |
xn | <!-- |
xo | <screen> |
xp | <programlisting> |
xq | <question> |
xr | <answer> |
xs | <simplesect> |
例如,<F2> 插入一个标签模板,因此 <F2>p 插入<para></para>,并将光标放在两个标签之间并进入插入模式。许多模板不仅仅包含开始和结束标签。例如,表格的模板会插入空的标题行和正文行。
以下键与功能键 <F3> 组合使用。
表 3. 符号键
键 | 插入值 | 描述 |
---|---|---|
3 | ¾ | 四分之三 |
5 | ‘ | 左单引号 |
6 | ’ | 右单引号 |
7 | “ | 左双引号 |
8 | ” | 右双引号 |
, | < | < |
. | > | > |
< | < | < |
> | > | > |
a | æ | ae 合字 |
c | © | 版权符号 |
d | ° | 度数符号 |
f | ¼ | 四分之一 |
h | ½ | 二分之一 |
n | – | 短破折号 |
m | — | 长破折号。 |
r | ® | 注册符号 |
t | × | 乘号 |
_(下划线) | -date- | 当前日期 |
例如,<F3>3 将 ¾ 插入到文本中。
以下键与功能键 <F4> 组合使用。
表 4. 外文字符键
键 | 插入值 | 描述 |
---|---|---|
b | β | 希腊字母 beta |
m | μ | 希腊字母 mu |
n | ñ | 带波浪号的 n |
'a (单引号-a) | á | 带尖音符的 a |
'c | ç | 带软音符的 c |
'e | é | 带尖音符的 e |
'i | í | 带尖音符的 i |
'o | ó | 带尖音符的 o |
'u | ú | 带尖音符的 u |
`a (反引号-a) | à | 带抑音符的 a |
`e | è | 带抑音符的 e |
`i | ì | 带抑音符的 i |
`o | ò | 带抑音符的 o |
`u | ù | 带抑音符的 u |
"a (双引号-a) | ä | 带分音符的 a |
"e | ë | 带分音符的 e |
"i | ï | 带分音符的 i |
"o | ö | 带分音符的 o |
"u | ü | 带分音符的 u |
^a | â | 带扬抑符的 a |
^e | ê | 带扬抑符的 e |
^i | î | 带扬抑符的 i |
^o | ô | 带扬抑符的 o |
^u | û | 带扬抑符的 u |
例如,<F4>'a 将 á(带尖音符的 a)插入到文本中。
DocBook 是一种庞大的标记语言,提供了许多标签,而大多数项目仅使用可用标签的子集。上面的绑定是为标记 LJ 文章而开发的。您对 DocBook 的使用可能会侧重于一组不同的标签,因此您可能需要更改模板和快捷键绑定。
文件 tagtmps.vim 包含由 <F2> 键插入的模板。清单 2 显示了 article 标签的模板。
清单 2. Article 标签模板
let g:Template_article ="<?xml version=\"1.0\" encoding=\"ISO-8859-1\" standalone=\"no\"?><CR>" \."<!DOCTYPE article SYSTEM \"docbookx.dtd\"><CR><CR>" \."<article><CR><CR>" \."<simplesect><title/><CR>" \."<para><CR>-:-<CR>" \."</para><CR>" \."</simplesect><CR><CR>" \."<simplesect><title></title><CR>" \."<para><CR>" \."</para><CR>" \."</simplesect><CR><CR>" \."</article>"
所有模板都存储在全局字符串变量中,这些变量的名称以 Template_ 开头,并以模板对应的标签结尾。变量名称中的 g: 前缀使其成为全局变量。长字符串可以通过在第二行和后续行前加上反斜杠 (\) 并使用点 (.) 连接运算符将这些行连接在一起来放置在多行上。每个字符串片段都包含在双引号内。双引号字符串理解常用的 C 转义序列。您可以通过遵循所述的命名序列来修改现有模板或为其他标签添加新模板。在模板中,序列-:-用于指定您希望在插入模板后将光标放置在何处。宏在插入宏后会自动删除此字符串。
如果您想更改用于执行宏的功能键,请修改文件 mfuncs.vim 中的以下行
let s:InsertTagTemplateKey = "<F2>" let s:InsertSymbolKey = "<F3>" let s:InsertForeignCharKey = "<F4>" let s:InsertStartTagKey = "<F5>" let s:InsertEndTagKey = "<F6>" let s:TagWordKey = "<F7>" let s:TagRangeKey = "<F7>" let s:ChangeTagKey = "<F8>"
如果您想更改跟随功能键的标签键、符号键或外文字符键,或者更改与键关联的标签,请更改 maps.vim 中的相应行。例如,要将 b 更改为与标签 <book> 而不是标签 <emphasis role="bold"> 关联,请在 maps.vim 中查找以下行
call MapTagKey("b", 0, 0, "emphasis", " role=\"bold\"")
并将其更改为
call MapTagKey("b", 1, 1, "book", "")
函数 MapTagKey 在 mfuncs.vim 中定义。其原型为
function! MapTagKey(key, snewline, enewline, tag, stagx)
其参数在表 5 中进行了解释。
表 5. MapTagKey 参数
参数 | 描述 |
---|---|
key | 要将标签键绑定到的按键(例如,<F2>key)。 |
snewline | 如果开始标签应放在新行上,则为 1,否则为 0。 |
enewline | 如果结束标签应放在新行上,则为 1,否则为 0。 |
tag | 与键关联的标签。 |
stagx | 应放在开始标签中的额外属性。 |
函数 MapTagKey 仅设置并执行许多 Vim nmap 和 imap 命令,以进行适当的快捷键绑定。类似地,符号键和外文字符键分别由函数 MapSymbolKey 和 MapForeignCharKey 映射。这些函数都接受两个参数:键和要插入的文本。例如
call MapSymbolKey("3", "¾") call MapForeignCharKey("b", "β")
在文件 maps.vim 的底部附近,有一些 Vim nmap 命令,用于绑定标签操作和移动键,包括删除标签、更改标签和移动标签。所有这些绑定都调用文件 tfuncs.vim 中定义的函数。
nmap <S-F8> :call DeleteTag()^M " Delete tag at cursor. nmap <F9> :call CursorLeftByTag()^M " Move left by tags. nmap <F10> :call MoveTagLeft()^M " Move tag left of preceding word. nmap <F11> :call MoveTagRight()^M " Move tag right of following word. nmap <F12> :call CursorRightByTag()^M " Move right by tags. nmap <S-F9> :call TightenTagLeft()^M " Delete whitespace left of tag. nmap <S-F10> :call InsertStringLeftOfTag(" ")^M " Insert space to the left of tag. nmap <S-F11> :call InsertStringRightOfTag(" ")^M " Insert space to the right of tag. nmap <S-F12> :call TightenTagRight()^M " Delete whitespace right of tag.
如果您 cat 此文件,这些行看起来会很奇怪,并且在某些编辑器中,所有行都会在调用中的右括号后立即断开。如果您使用 vim 查看它,您可以看到右括号后跟 ^M,即回车符。当您 cat 文件时,这会导致行的一部分被擦除。某些编辑器会导致此处换行。这些映射在命令模式下工作,并且 ^M 结束命令。
如果您是 vim 用户并且需要编辑 DocBook,那么此处描述的宏可以通过为您提供用于插入标签和实体以及插入预定义标签模板的 vim 快捷键绑定来简化您的工作。它还提供了快捷键绑定,使您可以在文档中移动标签,以及通过标签在文档中移动。
尽管最初设计用于 DocBook/XML,但这些宏可以与任何类似的标记语言一起使用,例如 HTML、SGML 或其他基于 XML 的标记语言。
DocBook 官方主页 DocBook DTD 在这里可用。
O'Reilly 图书 DocBook: The Definitive Guide 的在线版本 DocBook DTD 也在这里可用。