\chapter[bibtex]{文献管理} 稍微严肃一些的文章,往往会附上一些与文章内容密切相关的参考文献。科研论文更是如此,牛顿都说过自己是站在巨人的肩膀上做事情的。参考文献便是巨人。任何一个 \TeX\ 系统皆不敢对支持参考文献排版这一事宜掉以轻心,否则 \TeX\ 无以为科技文献排版软件之先驱和典范。 \section{数据格式} 大多数 \TeX\ 系统在排版参考文献时,皆需依赖一个名为 bibtex 的外部程序。由 bibtex 基于文献数据文件生成参考文献列表信息,然后交由 \TeX\ 进行排版,这一过程通常是自动进行的,并不需要用户了解和干预。\ConTeXt\ 已在自身内部实现了 bibtex 程序的全部功能,故而不再依赖这个外部程序了。本文档在谈及 Bib\TEX\ 时,主要指文献数据格式。 Bib\TEX\ 文献数据文件是纯文本文件,其中包含着论文、专著和手册等文献数据。例如,一篇期刊论文,其信息可表示为 \starttyping @article{knuth-1984-literate, title={Literate programming}, author={Knuth, Donald Ervin}, journal={The computer journal}, volume={27}, number={2}, pages={97--111}, year={1984}, publisher={Oxford University Press} } \stoptyping \noindent 再例如一本专著,其信息可表示为 \starttyping @book{knuth-1986-texbook, title={The \TeX\ book}, author={Knuth, Donald Ervin and Bibby, Duane}, volume={1993}, year={1986}, publisher={Addison-Wesley Reading, MA} } \stoptyping 为了学习 \ConTeXt\ 的参考文献排版功能,可将上述文献数据保存到一份空的文本文件里,例如 foo.bib,然后在同一目录下,建立 \CONTEXT\ 源文件 test.tex,其内容为 \starttyping[option=TEX] \usebtxdataset[foo.bib] % 加载 foo.bib \starttext Knuth 基于文学编程\cite[knuth-1984-literate]技术开发了 \TEX\ 系统\cite[knuth-1986-texbook]。 \blank \placelistofpublications \stoptext \stoptyping \noindent 编译 test.tex,可得以下结果: % 大概因为 externalfigure 构造的对象没有基线,从而导致其后有一块难以消除的半行留白 % 不得不在前面加上半行空行以达到留白对称的效果。 \blank[halfline] \externalfigure[14/bibtex-example-01.pdf][width=\textwidth] 若将文献数据文件视为文献数据库,则 bibtex 程序或者 \CONTEXT\ 内部实现的同样功能的模块相当于数据库的搜索引擎。在科研工作中,你可以将自己所读的所有文献置于一份 \type{.bib} 文件中,然后在写论文或专著时,按需引用。 上述示例所用的文献样式是 \ConTeXt\ 默认样式。有三种预定义的文献样式:apa,aps 和 chicago,可在 \type{\placelistofpublications} 之前使用 \type{\usebtxdefinitions} 设定文献样式,例如若使用 aps 样式,只需 \starttyping[option=TEX] \usebtxdefinitions[aps] \placelistofpublications \stoptyping \blank[halfline] \externalfigure[14/bibtex-example-02.pdf][width=\textwidth] 预定义的样式,其细节可以调整。例如,以下命令将文献序号宽度设定为 \type{auto},并将其与文献条目的间距设为半个字宽。 \starttyping[option=TEX] \setupbtxlist[aps][width=auto,distance=.5em] \stoptyping \blank[halfline] \externalfigure[14/bibtex-example-03.pdf][width=\textwidth] \section{自制样式} \ConTeXt\ 提供的这几种文献样式可能并不符合你的要求,此时你有两个方案,第一个方案是放弃这一切,使用 \in[itemcite] 所述的廉价方案,第二个方案是基于 \CONTEXT\ 的文献样式机制,自己定义一种你想要的样式。如果你选择了后者,下文可为你提供一个简单的示例,希望有所帮助。 假设要定义一种名为 bar 的文献样式。首先,按照 \ConTeXt\ 的文件命名约定,创建文件 publ-imp-bar.tex,先写入以下内容: \starttyping[option=TEX] \definebtx[bar] \stoptyping \noindent 上述代码定义了一个命名空间,其上层还有个空间,即 \type{btx}。然后你可以根据自己需要定义一些子空间。例如,为 \type{bar} 定义子空间 \type{list},再为后者定义子空间 \type{article}: \starttyping[option=TEX] \definebtx[bar:list][bar] \definebtx[bar:list:article][bar:list] \stoptyping \noindent 实际上,子空间通常无需定义,只有当你需要为某个子空间设定外观时才需要定义它。 \type{list} 空间包含了 Bib\TEX\ 数据格式中所有的文献条目和字段名。例如,\type{article} 空间表示期刊论文条目,在该空间内可以定义期刊论文的各种字段空间,例如 \starttyping[option=TEX] \startsetups btx:bar:list:article \texdefinition{btx:bar:list:author}\btxperiod\btxspace \texdefinition{btx:bar:list:title}\btxperiod\btxspace \texdefinition{btx:bar:list:journal}[J]\btxcomma\btxspace \texdefinition{btx:bar:list:year}\btxcomma\btxspace \texdefinition{btx:bar:list:volume} \texdefinition{btx:bar:list:number}\btxcolon\btxspace \texdefinition{btx:bar:list:pages}\btxperiod \stopsetups \stoptyping \noindent 上述代码定义了期刊论文的构成,其中 \type{\btxcomma},\type{\btxperiod},\type{\btxcolon},\type{\btxspace} 分别为西文的逗号,句号,冒号和空格。倘若需要使用中文标点,亦可自行定义,例如: \starttyping[option=TEX] \def\btxchinesecomma{,} \def\btxchineseperiod{.} \def\btxchinesecolon{:} \stoptyping 接下来,在 publ-imp-bar.tex 文件中定义期刊论文的各个字段,如下 \starttyping[option=TEX] \starttexdefinition btx:bar:list:author \btxflush{author} \stoptexdefinition \stoptyping \starttyping[option=TEX] \starttexdefinition btx:bar:list:title \color[darkred]{\bf\btxflush{title}} \stoptexdefinition \stoptyping \starttyping[option=TEX] \starttexdefinition btx:bar:list:journal \btxflush{journal} \stoptexdefinition \starttexdefinition btx:bar:list:year \btxflush{year} \stoptexdefinition \starttexdefinition btx:bar:list:volume \btxflush{volume} \stoptexdefinition \starttexdefinition btx:bar:list:number \ignorespaces % 忽略空白字符 \btxleftparenthesis % 左括号 ( \btxflush{number} \btxrightparenthesis % 右括号 ) \stoptexdefinition \starttexdefinition btx:bar:list:pages \btxflush{pages} \stoptexdefinition \stoptyping 上述代码定义了样式 bar 的数据格式,其中 \tex{btxflush} 命令的作用是从 Bib\TEX\ 格式的文献库里获得各条目的字段内容。 若让 \CONTEXT\ 能够按照这种格式将其呈现为文献列表的形式,需要定义一个同名的渲染环境,亦即在 publ-imp-bar.tex 文件中增加以下设定: \startTEX \definebtxrendering[bar] \stopTEX 至此,新的文献样式 bar 便已定义完毕。在 publ-imp-bar.tex 文件所在目录下,建立测试文件 test.tex,其内容如下: \starttyping[option=TEX] \usebtxdataset[foo] % 加载 foo.bib \starttext Knuth 发明了文学编程语言 WEB\cite[knuth-1984-literate]。 \blank \usebtxdefinitions[bar] % 使用上文定义的参考文献列表样式 bar \placelistofpublications % 排版文献列表 \stoptext \stoptyping \noindent 编译 test.tex,结果如下图。 \blank[halfline] \externalfigure[14/bibtex-example-04.pdf][width=\textwidth] \section{样式微调} 上一节定义的 bar 样式,不满足多数中文学术期刊和学位论文的要求,存在的主要问题是,文献序号并非方括号形式且序号与文献条目的间距过大,英文的作者姓名没有将姓放在前面,名字放在后面并缩写。 文献需要的样式可以用 \tex{setupbtxlist} 设定。类似于上文设定 apa 样式的文献序号的方法,将 bar 样式的文献序号设定为方括号形式,并缩小序号与文献条目的间距,只需 \startTEX \setupbtxlist[bar][starter={[},stopper={]},width=auto,distance=1em] \stopTEX \noindent 实际上 \tex{setupbtxlist[bar]} 是 \tex{setuplist[btx:bar]} 的别名,二者是等效的。\tex{setuplist} 命令,我们在 \in[TOC] 节设定目录样式时已经见识过了。 要设置文献条目中的作者信息的样式,需要为其定义命名空间,例如为 bar 样式定义作者信息的命名空间,需作以下定义: \startTEX \definebtx[bar:list:author][bar:list] \stopTEX \noindent 然后便可设定 \type{bar:list:author} 的外观,如下: \startTEX \setupbtx[bar:list:author] [authorconversion=invertedshort, separator:invertedinitials=\btxspace, stopper:initials=\btxspace] \stopTEX \noindent 参数 \type{authorconversion} 用于设定作者姓名格式,\type{invertedshort} 可将作者的姓氏前置,名字后置,且该设定只会作用于西文的作者姓名,对中文作者姓名无效,原因是前者的姓名之间有空格作为间隔,有前后之分,而中文的作者姓名之间没有间隔。\type{separator:invertedinitials} 用于设定姓名之间的间隔符,默认是西文逗号。\type{stopper:initials} 用于设定作者姓氏简写字母后的符号,默认是西文句点。 上述样式微调的结果如下图所示: \blank[halfline] \midaligned{\externalfigure[14/bibtex-example-fin.pdf][width=\textwidth,frame=on]} 如果你不想为 bar 样式定义作者信息命名空间,也可以直接基于默认的作者信息命名空间设定样式,例如 \startTEX \setupbtx[default:list:author] [authorconversion=invertedshort, separator:invertedinitials=\btxspace, stopper:initials=\btxspace] \stopTEX 自定义的文献样式,若未为其定义子命名空间,可以直接用默认的命名空间设定样式,而且这些默认的空间也皆有默认的样式,倘若你不设定,\CONTEXT\ 便按默认的样式渲染该空间表征的文献字段。 \section{更具一般性} 实际上,\CONTEXT\ 文件管理模块为文献数据源提供了别名机制,你可以为载入的文献数据取一个名字,然后基于该名字和文献样式定义渲染环境,最后再将该渲染环境呈现出来,便可得到文献列表,见下例 \startTEX \usebtxdataset[bibdata][foo.bib] \setupbtx[dataset=bibdata] % 为 \cite 命令设定数据源 \usebtxdefinitions[bar] % 载入 bar 样式 \definebtxrendering[references][bar][dataset=demo] \starttext Knuth 发明了文学编程语言 WEB\cite[knuth-1984-literate]。 \blank % 排版文献列表,也可以用 \placebtxrendering[reference] \placelistofpublications[references] \stoptext \stopTEX \CONTEXT\ 的文献管理功能之所以设计得如此复杂,其意图是要支持同一份文献数据,可以用不同的文献样式排版。不过,我觉得这实在是一种过度设计,可以称得上失败。 \section{第三条路} 如果你对 \CONTEXT\ 的文献管理功能颇为不满,实际上还有第三条路可以走,那就是先用 \CONTEXT\ 内置的文献样式管理引用的文献,待完全定稿后,再手工将文献列表排版成你期望的样式。为了降低工作量,你也可以用现代的一些容易使用的脚本语言编写一个简陋的类似 bibtex 的程序作为辅助工具。 \subject{结语} Hans Hagen 为 \ConTeXt\ 文献管理功能专门写了一份约 100 页的手册,见 \starttyping $ mtxrun --search mkiv-publications.pdf \stoptyping \noindent 在不理解本文自定义文献样式所用的各命令及其参数的含义时,可从该手册获得更多的理解……只是这份手册内容凌乱,缺乏概观式的介绍,我建议先阅读文档 \cite[bib],先存下一些不解,然后再阅读该手册。