LaTeX
摘要
文档的协作编写要求作者之间有强大的同步机制。本书描述了组织 LaTeX 文档协作准备的几种可能方式。
首先,介绍了几种不基于版本控制系统的方法。
接下来,讨论了几种适合协作的 LaTeX 样式文件。
然后,介绍了一个基于版本控制系统 Subversion(http://subversion.apache.org/)的解决方案。本书描述了如何将 Subversion 与其他多个软件工具和 LaTeX 包结合使用,以组织 LaTeX 文档的协作准备。
另一种方法是使用 Mercurial https://www.mercurial-scm.org/ 和 Bitbucket https://bitbucket.org/
其他方法(非基于版本控制)
您可以使用安装章节中列出的在线解决方案。大多数都具有协作功能。
另一种协作选择是 Dropbox。它提供 2 GB 的免费存储和版本控制系统。与 SVN 类似,但更自动化,因此特别适合 LaTeX 初学者。然而,Dropbox 并非真正的版本控制系统,因此不允许您将文档回滚到先前的版本。基于 Web 的 LaTeX 编辑器 LaTeX Base 支持与 Dropbox 的同步。
您还可以使用建立在版本控制系统之上的在线协作工具,如 Authorea 或 ShareLatex。Authorea 执行本文档中描述的大多数操作,但在后台(它是基于 Git 的)。它允许作者通过 GUI 输入 LaTeX 或 Markdown,支持数学符号、图形、d3.js 图表、IPython 笔记本、数据和表格。所有内容都渲染为 HTML5。Authorea 还具有评论系统和基于文章的聊天功能,以便于协作和审阅。
由于 LaTeX 系统使用纯文本,您可以使用同步协作编辑器,如 Gobby。在 Gobby 中,您可以与任何人实时协作编写文档。强烈建议使用 utf8 编码(尤其是当有多个操作系统的用户协作时),并使用稳定的网络(通常是有线网络)。
一个例子是 Wikimedia 上的 EtherPad 实例。在编译时使用以下命令:
wget -O filename.tex "https://etherpad.wikimedia.org/ep/pad/export/xxxx/latest?format=txt" && (latex filename.tex)
其中 'xxxx' 应替换为 pad 编号(类似 'z7rSrfrYcH')。
通过配置一个专用的 Linux 服务器并与 LaTeX 和 Dropbox 配合使用,您可以通过 Google 文档和一些脚本从 Google 文档的更新自动生成 PDFs,并将其存储到 Dropbox。
您还可以使用分布式版本控制系统,如 Fossil、Mercurial 或 Git。这是寻找控制和高级功能(如分支和合并)用户的最终解决方案。学习曲线会比基于 Web 的解决方案陡峭。
Syncthing 是另一个开源替代品,用于跨机器同步文件。
在 LaTeX 中可视化差异:latexdiff 和 changebar
工具 latexdiff 和 changebar 可以在生成的文档中可视化两个 LaTeX 文件之间的差异。这使得查看某些更改的影响或与不熟悉 LaTeX 的人讨论更改变得更容易。Changebar 带有一个脚本 chbar.sh
,该脚本在边距中插入一条线,指示已更改的部分。Latexdiff 允许不同的可视化样式。默认情况下,丢弃的文本标记为红色,添加的文本标记为蓝色。它还支持类似 Changebar 的模式,在边距中添加一条线。Latexdiff 还带有一个脚本 latexrevise
,可以用来接受或拒绝更改。它还具有一个包装脚本,支持如 Subversion 这样的版本控制系统。
使用 Latexdiff 的 Terminal 示例:
latexdiff old.tex new.tex > diff.tex # 比较 old.tex 和 new.tex,生成的差异文件写入 diff.tex
pdflatex diff.tex # 创建一个显示更改的 PDF
如果使用 Mercurial,语法如下:
latexdiff-vc --hg test.tex -r revnumber
其中 revnumber
是相关变更集的(本地)版本号。
重要提示:
有时 latexdiff 会遇到问题(生成的 LaTeX 代码无法编译)。这种情况可能发生在涉及数学方程的重大更改时。为了处理这个问题,latexdiff 提供了 --math-markup
选项:
程序 DiffPDF 可以用于比较两个现有的 PDF 文件。基于 DiffPDF,还有一个命令行工具 comparepdf
。
有用的 LaTeX 样式
Subfiles
对于协作,通常建议采用模块化的方法,因为它减少了冲突编辑的风险。详情见 Modular Documents,subfiles
是推荐的,但不是唯一的解决方案。
Todonotes
todonotes.sty
允许您插入待办项,既可以作为边距注释,也可以作为行内注释,并在文档开头添加一个(支持超链接的)待办列表。与 fixme.sty
相比,todonotes
的特别之处在于,边距的待办项会通过一条线指向相关文本。这一特性在 LibreOffice、MS Office 等软件中非常常见,详情见手册 todonotes。
示例:
\documentclass{article}
\usepackage[colorinlistoftodos, textwidth=3cm, shadow]{todonotes}
\newcounter{ubcomment}
\newcommand{\ubcomment}[2][]{%
\refstepcounter{ubcomment}%
{%
\todo[linecolor=black,backgroundcolor={green!40!},size=\footnotesize]{%
\textbf{Fixme: UB [\uppercase{#1}\theubcomment]:}~#2}%
}}
\newcommand{\ubcommentinline}[2][]{%
\refstepcounter{ubcomment}%
{%
\todo[linecolor=black,inline,backgroundcolor={green!40!},size=\footnotesize]{%
\textbf{Fixme: UB [\uppercase{#1}\theubcomment]:}~#2}%
}}
\newcommand{\ubcommentmultiline}[2]{%
\refstepcounter{ubcomment}%
{%
\todo[linecolor=black,inline,caption={\textbf{{Fixme: UB}
[\theubcomment] #1}} ,backgroundcolor={green!40!},size=\footnotesize]{%
\textbf{Fixme: UB [\theubcomment]:}~#2}%
}}
% 支持在方程中插入待办注释
\usepackage{marginnote}
\makeatletter
\renewcommand{\@todonotes@drawMarginNoteWithLine}{%
\begin{tikzpicture}[remember picture, overlay, baseline=-0.75ex]%
\node [coordinate] (inText) {};%
\end{tikzpicture}%
\marginnote[{% 绘制左边的注释
\@todonotes@drawMarginNote%
\@todonotes@drawLineToLeftMargin%
}]{% 绘制右边的注释
\@todonotes@drawMarginNote%
\@todonotes@drawLineToRightMargin%
}%
}
\makeatother
\begin{document}
\listoftodos
这是一个示例 \ubcomment{评论 1}
现在是更多的文本和一个行内注释: \ubcommentinline{这是一个行内注释}。
现在是更多的文本和一个带有列举列表的注释。
\ubcommentmultiline{第三个注释}{
这不对,因为
\begin{enumerate}
\item 理由 1
\item 理由 2
\end{enumerate}
}
最后是一个数学环境中的注释。
\begin{equation}
\label{eq:todo-example:1}
\int f dx =0 \ubcomment{你确定这个积分是零吗?}
\end{equation}
\end{document}
请注意: 您需要使用 pdflatex
(xelatex
也可以)并运行多次,通常是三次或四次。
rcsinfo (和 rcs-multi)
这个包 https://ctan.org/pkg/rcsinfo?lang=en (和 rcs-multi https://ctan.org/pkg/rcs-multi)以类似的方式自动插入当前版本、日期和文件所有者信息,这些文件在版本控制系统下,支持 RCS 语法(如 CVS、Subversion 和 Mercurial)。(见下文关于如何设置 Mercurial 的说明)。以下是一个示例:
\documentclass[12pt]{article}
\usepackage[scrpage2]{rcsinfo}
\makeatletter \def\@rcsInfoFancyInfo{{\footnotesize%
\emph{ \fcolorbox{black}{green}{Rev: \rcsInfoRevision,}
\fcolorbox{black}{yellow}{\rcsInfoOwner,} \rcsInfoLongDate,
\rcsInfoTime}}} \makeatother
\rcsInfo $Id: main.tex,v [Hg:291] 2018/08/08 16:36:51 oub Exp oub $
\begin{document}
This is a test.
\end{document}
版本控制系统
无论是协作还是单作者文档,版本控制系统都很有用,因为它们允许跟踪更改并在必要时恢复较旧的版本。最早使用的版本控制系统是 RCS,但它是单文件导向的,并且不是基于服务器模型的。CVS 基于 RCS,但支持多个文件,并且包含一个服务器模型。CVS 在某种程度上被 Subversion(见下文)所取代。另一种方法是分布式版本控制系统,最流行的有 Git 和 Mercurial(见下文)。
使用版本控制系统进行协作的要求
多用户
系统应该允许多个用户拥有对系统的读写访问权限,类似于一个“服务器”。
版本应保存
关键是不要覆盖文件或文件的较新版本,而是系统应该以某种形式保存不同的版本。其原因包括:
-
可以通过运行适当的 diff 程序(例如 latexdiff)比较文件的不同版本。
-
它允许在必要时恢复旧版本。
非顺序的贡献应得到管理
顺序协作是指一个用户工作时,其他用户没有任何操作,之后下一个用户开始。
我们来考虑一个非顺序的协作示例。(为了说明问题,下面的例子是一个文件,实际上对于目录中的不同文件也会出现相同的问题,但这种情况不太直观。)
-
User1 想在 file1 中修改第 1 节,并需要 2 周时间,结果是 file1-modified-by-user1。
-
与此同时,User2 修改了 file1 中的第 2 节,结果是 file1-modified-by-user2。
-
User3 修改了 file1 中的第 3 节,结果是 file1-modified-by-user3。
一个版本控制系统必须能够“合并”这三种更改,而不会出现问题。
应检测冲突编辑
冲突编辑定义为在同一文件的同一行上发生编辑。系统应能够检测到这些冲突,并提供解决方法。
使用版本控制系统交换文档
文档的协作准备需要作者之间的协调。这种协调可以通过多种方式组织,最佳方式取决于具体情况。
有许多方法可以在作者之间交换文档。一个可能的方式是通过交换电子邮件消息来编写文档。这种方法的优点是大多数用户通常不需要安装和学习任何额外的软件,因为几乎所有作者都有电子邮件账户。此外,修改文档的作者可以轻松地附加文档并通过电子邮件解释更改。不幸的是,当两个或更多作者同时在同一文档上工作时,会出现问题。那么,如何同步这些文件呢?除此之外,当涉及多个文件时,基于电子邮件的方法可能会变得繁琐。另一种方法是使用分布式或基于服务器的版本控制系统。在进入详细内容之前,将在下一小节中概述这种方法的基本要求。
第二种可能性是将文档提供到公共文件服务器,这在大多数部门中都是可用的。通过锁定当前正在编辑的文件,可以消除覆盖彼此修改的风险。然而,通常文件服务器只能从部门内部访问。因此,部门外的作者无法使用此方法更新/提交他们的更改。在这种情况下,他们将不得不使用其他方法来克服这个问题。那么,如何访问这些文件呢?
第三种可能性是使用版本控制系统。有关版本控制系统的全面列表可以在 Wikipedia 上找到。版本控制系统跟踪项目中文件的所有更改。如果多个作者同时修改文档,版本控制系统会自动尝试合并所有修改。然而,如果多个作者修改了同一行,则无法自动合并修改,用户必须手动解决冲突,决定保留哪些更改。作者还可以注释他们的修改,以便共同作者轻松了解文件的工作流程。由于版本控制系统通常通过互联网进行通信(例如通过 TCP/IP 连接),它们可以从不同计算机上使用,只要计算机连接到互联网即可。限制性的防火墙策略可能会阻止版本控制系统连接到互联网。在这种情况下,网络管理员需要开放适当的端口。互联网仅用于同步文件,因此不需要永久的互联网连接。版本控制系统的唯一缺点可能是必须安装和配置它。
此外,即使单个用户正在处理项目,版本控制系统也是有用的。首先,用户可以跟踪(并可能撤销)所有先前的修改。第二,这是在其他计算机上备份文件的便捷方式(例如,在版本控制服务器上)。第三,这允许用户轻松地在不同计算机之间切换(例如办公室、笔记本、家里)。
版本控制系统 Subversion
Subversion(SVN)是流行的版本控制系统 CVS 的继任者。SVN 基于客户端-服务器模型,其中中央服务器托管一个项目仓库,用户可以将其复制并在本地修改。仓库的功能类似于图书馆,用户可以签出当前项目,进行更改,然后再签回。服务器记录用户签入的所有更改(通常会附带一个总结用户所做更改的消息),以便其他用户可以轻松地将这些更改应用到他们自己的本地文件中。
每个用户都有一个本地的工作副本。例如,用户可以从仓库更新更改到他们的工作副本,将更改从他们的工作副本提交到仓库,或者(重新)查看工作副本与仓库之间的差异。
要设置 SVN 版本控制系统,必须在具有永久互联网访问的计算机上安装 SVN 服务器软件。(如果该计算机没有静态 IP 地址,可以使用像 DynDNS 这样的服务,使得通过静态主机名访问服务器成为可能。)它可以运行在许多 Unix、现代 MS Windows 和 Mac OS X 平台上。
用户不必安装 SVN 服务器软件,但需要安装 SVN "客户端" 软件。这是访问服务器上的仓库的唯一方式。除了基本的 SVN 命令行客户端外,还有一些图形用户界面工具(GUI)和插件可用于访问 SVN 服务器(见 http://subversion.tigris.org/links.html)。此外,关于 SVN 的非常好的手册可以在互联网上免费获取(例如 http://svnbook.red-bean.com)。
在我们的部门,我们在 GNU-Linux 系统上运行 SVN 服务器,因为大多数 Linux 发行版都包括它。从这个角度来看,安装、配置和维护 SVN 是一项非常简单的任务。
大多数 MS Windows 用户通过 TortoiseSVN 客户端访问 SVN 服务器,因为它为普通用户提供了最常用的界面。Linux 用户通常使用命令行中的 SVN 工具,或者使用 eSvn —— 一个图形界面前端 —— 结合 KDiff3 来显示复杂的差异。
在 Subversion 中托管 LaTeX 文件
图 1:eSvn 的仓库浏览器中显示的常见 texmf 树
在我们的 Subversion 服务器上,我们有一个用于公共 texmf 树的仓库。其结构符合 TeX 目录结构(TDS)指南(http://www.tug.org/tds/tds.html,见图 1)。该仓库提供 LaTeX 类、LaTeX 样式和 BibTeX 样式,这些在用户的 LaTeX 发行版中不可用,例如,因为它们是为我们部门的内部使用购买或开发的。所有用户都有这个仓库的工作副本,并且已经配置 LaTeX 使用它作为个人 texmf 树。例如,teTeX(http://www.tug.org/tetex/)用户可以编辑他们的 TeX 配置文件(如 /etc/texmf/web2c/texmf.cnf
),并将变量 TEXMFHOME 设置为公共 texmf 树的工作副本路径(例如:TEXMFHOME = $HOME/texmf
);MiKTeX(http://www.miktex.org/)用户可以在 MiKTeX 选项的“Roots”标签中添加公共 texmf 树工作副本的路径。
如果添加了新的类或样式文件(但未修改这些文件),用户必须在使用这些类和样式之前更新他们的“文件名数据库”(FNDB)。例如,teTeX 用户必须执行 texhash
;MiKTeX 用户必须点击 MiKTeX 选项中“常规”标签下的“刷新 FNDB”按钮。
此外,仓库还包含说明我们部门特定 LaTeX 软件解决方案的手册(例如,本文件)。
Subversion 服务器为我们部门的每个项目托管一个单独的仓库。尽管分支、合并和标记对写作文本文件比对编写软件源代码更不重要,但我们的仓库布局遵循“Subversion 手册”的建议(http://svnbook.red-bean.com)。因此,每个仓库都有三个目录:/trunk
、/branches
和 /tags
。
最重要的目录是 /trunk
。如果单个文本文件属于项目,则该文本文件的所有文件和子目录都在 /trunk
中。如果项目产生两个或更多不同的文本文件,/trunk
中包含每个文本文件的子目录。文本文件的一个略微不同的版本(例如,为了在会议上展示)可以在 /trunk
的一个额外子目录中准备,或者在 /branches
的一个新子目录中准备。当文本文件提交到期刊或会议时,我们在 /tags
目录中创建一个标签,以便稍后轻松识别提交版本。这个功能被证明非常有用。在创建分支和标签时,重要的是始终使用 Subversion 客户端(而不是本地文件系统的工具)来执行这些操作,因为这样可以节省服务器上的磁盘空间,并保持文档相同的历史信息。
通常会有一个问题,那就是哪些文件应该放在版本控制下。一般来说,所有用户直接修改并且编译文档所必需的文件都应该包含在版本控制系统中。通常,这些是 LaTeX 源代码(.tex)文件(主文档和可能的一些子文档)以及插入文档中的所有图片(.eps、.jpg、.png 和 .pdf 文件)。所有 LaTeX 类(.cls)、LaTeX 样式(.sty)、BibTeX 数据库(.bib)和 BibTeX 样式(.bst)通常应该托管在公共 texmf 树的仓库中,但如果某些(外部)共同作者无法访问公共 texmf 树,它们也可以包含在相应的仓库中。另一方面,所有在编译过程中自动创建或修改的文件(例如 .aut、.aux、.bbl、.bix、.blg、.dvi、.glo、.gls、.idx、.ilg、.ind、.ist、.lof、.log、.lot、.nav、.nlo、.out、.pdf、.ps、.snm 和 .toc 文件)或由(LaTeX 或 BibTeX)编辑器创建的文件(例如 .bak、.bib~、.kilepr、.prj、.sav、.tcp、.tmp、*.tps 和 *.tex~ 文件)通常不应放在版本控制下,因为这些文件对编译来说并不必要,且通常不包含附加信息。此外,这些文件经常被修改,因此很容易发生冲突。
Subversion 的特点及其工作流程
版本控制系统的一个重要特点是,所有作者都可以通过查看文件的任意版本之间的差异,轻松追踪项目的工作流程。作者主要关注对源代码的“有效”修改,这些修改会改变编译后的文档,而不关注对编译后文档没有影响的“无效”修改(例如换行位置)。比较文本文件的工具(“diff 工具”)通常无法区分“有效”和“无效”修改;它们会突出显示两种修改。这大大增加了查找和审查“有效”修改的工作量。因此,应该避免“无效”修改。
因此,重要的是不要无缘无故地改变换行位置。用户的 LaTeX 编辑器应该关闭自动换行功能,并且换行应该手动添加。否则,如果在段落开始处添加或删除一个单词,整个段落的换行可能会发生变化,导致大多数 diff 工具将整个段落标记为修改,因为它们逐行比较文件。wdiff
(http://www.gnu.org/software/wdiff/)和 dwdiff
(http://os.ghalkes.nl/dwdiff.html)工具不会受换行位置影响,因为它们逐字比较文档。然而,它们的输出不太清晰,因此修改更难跟踪。此外,这些工具不能直接与 Subversion 命令行选项 --diff-cmd
一起使用,需要使用一个小的包装脚本(http://textsnippets.com/posts/show/1033)。
一个合理的约定是,在每个句子后添加换行,并在每个新句子开始时换行。请注意,这不仅对于版本控制有好处:如果您想在编译后的 DVI、PS 或 PDF 文件中找到一个句子,您可以轻松识别该句子的前几个单词,并在编辑器窗口的左侧查找这些单词。
此外,我们将长句拆分成多行,以便每行最多有大约 80 个字符,因为在长行中查找(小)差异相当不方便。(例如,LaTeX 编辑器 Kile(http://kile.sourceforge.net/)可以在配置时帮助用户完成此任务,标记第 80 列。)我们发现将换行插入句子的逻辑断点(例如,在相对从句或新部分开始之前)非常有用。根据这些指南格式化的 LaTeX 代码示例如下,它是文章《Tools for Collaborative Writing of Scientific LaTeX Documents》(作者 Arne Henningsen)在 2007 年第 3 期《The PracTeX Journal》中的源代码(http://www.tug.org/pracjourn/2007-3/henningsen/)。
如果作者使用不同的操作系统,他们的 LaTeX 编辑器可能会使用不同的换行符(w:Newline)。为了避免这种“无效”修改,所有用户可以统一约定使用特定的换行符,并配置他们的编辑器使用该换行符。另一种选择是添加 Subversion 属性 svn:eol-style
并将其设置为 native
。在这种情况下,Subversion 会自动将该文件的所有换行符转换为作者操作系统的本地换行符(http://svnbook.red-bean.com/en/1.4/svn.advanced.props.file-portability.html#svn.advanced.props.special.eol-style)。
减少“无效”修改的数量还有另一个重要原因:如果多个作者在同一个文件上工作,随着修改行数的增加,两位或多位作者同时修改同一行的概率增加。因此,“无效”修改不必要地增加了冲突的风险(见章节《交换文档》)。
此外,版本控制系统提供了非常有效的质量保证措施:所有作者应在提交修改到仓库之前,批判性地审查自己的修改(见图 2)。用户的工作副本与仓库之间的差异可以通过一条 Subversion 命令或在图形 Subversion 客户端中点击一到两次轻松检查。此外,作者应在提交修改到仓库之前,验证他们的代码是否能够无错误地编译。如果不这样做,共同作者在编译文档时将不得不为这些错误买单。然而,这一指令不仅对于版本控制系统合理,对于所有其他作者间交换文档的方法也是适用的。
Subversion 具有一个名为“关键词替换”的功能,它将关于文件的动态版本信息(例如修订号或最后修改作者)包含到文件本身的内容中(例如,见 http://svnbook.red-bean.com,第 3 章)。有时,将这些信息不仅作为 LaTeX 源代码中的注释,而还包括在(编译后的)DVI、PS 或 PDF 文档中是有用的。这可以通过 LaTeX 包 svn(http://www.ctan.org/tex-archive/macros/latex/contrib/svn/)、svninfo(http://www.ctan.org/tex-archive/macros/latex/contrib/svninfo/)或(优选)svn-multi(http://www.ctan.org/tex-archive/macros/latex/contrib/svn-multi/)来实现。
使用版本控制系统协作编写 LaTeX 文档的最重要指令总结如下:
使用版本控制系统的 LaTeX 指令
-
避免“无效”修改。
-
没有充分理由时,不要更改换行符。
-
关闭 LaTeX 编辑器的自动换行功能。
-
每个新句子从新的一行开始。
-
将长句分成多行,使每行最多约 80 个字符。
-
仅将用户直接修改的文件置于版本控制中。
-
在提交修改到仓库之前,验证代码能否无错误地编译。
-
使用 Subversion 的 diff 功能,在提交修改之前批判性地审查自己的修改。
-
提交修改到仓库时,添加有意义且描述性的评论。
-
使用 Subversion 客户端复制、移动或重命名处于版本控制下的文件和文件夹。
-
如果用户愿意放弃 SVN 内建的 diff 工具并使用本地工作站上的 diff 工具,他们可以使用更适合文本文件的工具。SVN 自带的 diff 工具是针对源代码设计的,因此,它更适用于短行文件。其他工具,如 Compare It! 允许方便地比较每行可以跨越数百个字符的文本文件(例如,当每行代表一个段落时)。使用允许方便查看长行文件的 diff 工具时,用户可以在没有严格换行规则的情况下编写 TeX 文件。
分布式版本控制系统 Mercurial(和 Git)
如在 https://en.wikipedia.org/wiki/Distributed_version_control 中所述:在软件开发中,分布式版本控制(也称为分布式修订控制)是一种版本控制形式,其中完整的代码库——包括其完整历史——都在每个开发者的计算机上进行镜像。这使得分支和合并的管理变得自动化,增加了大多数操作的速度(推送和拉取除外),提高了离线工作的能力,并且不依赖于单一位置的备份。
软件开发作者 Joel Spolsky 将 DVCS 描述为“可能是过去十年中软件开发技术的最大进步。”
目前最流行的 DVCS 是:
-
mercurial https://www.mercurial-scm.org/
虽然 git 更受欢迎,可能更适合非常大的软件项目,但 mercurial 拥有一些使其特别适合基于 LaTeX 的科学协作的功能。
-
它除了变更集哈希外,还具有本地修订号,这使得处理不同的变更集变得更容易。
-
它具有关键词扩展,因此适合使用 rcs-multi.sty 和其他在文档页脚或页眉中添加版本号的 LaTeX 样式。
-
它具有命名分支,除了书签外,这在需要多个分支时更为直观。
-
它在所有已知操作系统上都能完美运行。
-
图形用户界面 https://www.mercurial-scm.org/wiki/TortoiseHg 提供了直观的界面。
设置 Mercurial(Git)
以下说明描述了如何设置 Mercurial。Git 的设置几乎是相同的,几乎可以直接使用,参见例如 Git/Mercurial Rosetta Stone:https://github.com/sympy/sympy/wiki/Git-hg-rosetta-stone
有关在不同操作系统上安装 Mercurial,请参见:https://www.mercurial-scm.org/downloads
Mercurial 编写并提供了多种所谓的扩展,这些扩展必须在全局 .hgrc
配置文件中单独启用。
以下是一个示例:
# 示例配置(查看 "hg help config" 获取更多信息)
[ui]
username = Joe Doe <user@gmail.com>
[extensions]
churn =
# 阅读关于如何设置 notify 扩展的文档,如果使用 bitbucket 的通知系统,则无需此扩展
# notify =
strip =
share =
progress =
eol =
hgk =
hgext.bookmarks =
interhg =
rebase =
shelve =
purge =
record =
color =
keyword =
hgext.fetch=
histedit =
# 高级扩展
# evolve =
# hggit =
# 最小设置用于关键词扩展
[keyword]
**.tex =
[keywordmaps]
Author = {author|user}
Date = {date|utcdate}
Header = {root}/{file},v {node|short} {date|utcdate} {author|user}
Id = {file|basename},v {rev} {date|utcdate} {author|user} Exp {author|user}
# 其他选项
# Id = {file|basename},v {rev}{latesttag}.{latesttagdistance} {date|utcdate} {author|user} Exp {author|user}
# 这样做的问题是,添加标签会增加修订号,因此在 LaTeX 文档中字符串总是 v4.2 或 5.2,而不是 v4.1。
# Id = {file|basename},v {latesttag}.{latesttagdistance}[Hg:{rev}] {date|utcdate} {author|user} Exp {author|user}
# 简化版
# Id = {file|basename},v |Brch:{branches}|{latesttag}[Hg:{rev}] {date|utcdate} {author|user} Exp {author|user}
RCSFile = {file|basename},v
RCSfile = {file|basename},v
Revision = {node|short}
Source = {root}/{file},v
[hostfingerprints]
bitbucket.org.fingerprints=sha256:ae:ca:bf:83:41:14:55:8d:ea:70:ae:06:7d:ad:c0:44:77:6f:81:1a:c9:1e:d3:ab:f5:38:98:2b:07:4b:d4:70
[color]
custom.rev = red
custom.decorate = yellow
custom.date = green
custom.author = blue bold
[eol]
native = LF
设置一个模板 LaTeX 目录
如前所述,建议采用模块化方法进行 LaTeX 协作,使用 subfile
包。一个典型的 LaTeX 模板目录可能如下所示:
-rw-r--r-- 1 oub oub 254K Aug 7 21:15 bibfile.bib
-rw-r--r-- 1 oub oub 637 Aug 14 09:21 main.tex
-rw-rw-r-- 1 oub oub 576 Aug 14 09:21 sec1-main-result.tex
-rw-rw-r-- 1 oub oub 576 Aug 14 09:21 sec2-proof.tex
创建一个本地 Mercurial 仓库
在该目录下,必须执行以下命令(使用 Linux/MacOS,MS Windows 类似):
hg init
hg addremove
hg commit -m "First commit"
可选地,可以添加一个 .hgignore
文件,针对 LaTeX 文件,它可以是这样的:
syntax: glob
*.aux
*.toc
*.mw
*.backup
*.brf
*.tdo
*.bbl
*.blg
*.bib
*.el
*.log
*.dvi
*.nav
*.pdf
*.glo
*.idx
*.ilg
*.ind
*.nlo
*.nls
*.out
*.synctex.gz
然后执行:
hg addremove
hg commit -m "Added .hgignore"
此时目录结构应如下所示:
drwxrwxr-x 11 oub oub 4.0K Aug 14 09:15 ..
-rw-r--r-- 1 oub oub 254K Aug 7 21:15 bibfile.bib
drwxr-xr-x 4 oub oub 4.0K Aug 14 09:34 .hg
-rw-r--r-- 1 oub oub 215 Aug 14 09:31 .hgignore
-rw-r--r-- 1 oub oub 630 Aug 14 09:34 main.tex
-rw-rw-r-- 1 oub oub 568 Aug 14 09:34 sec1-main-result.tex
-rw-rw-r-- 1 oub oub 562 Aug 14 09:34 sec2-proof.tex
现在可以设置一个空的 Bitbucket 仓库并邀请合作者。
Bitbucket 和 Helix
建议使用托管的 Mercurial 仓库,如 Bitbucket。对于学术用户,Bitbucket 提供了更慷慨的使用限制(例如没有限制合作者人数)。因此,推荐的方法是所有合作者都开设一个 Bitbucket 账户。
然后,一位作者(作为维护者)创建一个仓库并推送模板作为第一个版本。Bitbucket 网站提供了很好的说明,但也请参见下文的详细信息。
他与其他合作者共享该仓库。
建议所有合作者设置 Bitbucket 的通知系统。
合作者克隆仓库:例如,hg clone https://bitbucket.org/user/project1
。
合作者编辑文件并提交,例如 hg commit -m "Add Introduction"
。
然后推送:hg push
其他合作者会被通知该推送,执行:hg pull -u
然而,从 2020 年 8 月 1 日起,Mercurial 已停止通过 Mercurial 访问。现在有两个替代方案:
-
继续使用 Mercurial,但使用 hg-git 插件。即使是为命名分支,虽然需要一些配置,仍然可以使用此方法。
-
切换到 Helix,这个服务的功能略逊色,但仍提供免费的仓库(每个账户有 1 GB 空间+5 个合作者)。(https://info.perforce.com/try-perforce-helix-teamhub-free)
将本地 Mercurial 仓库移至 Bitbucket
以下是从 Bitbucket 网站复制的步骤。
步骤 1:切换到仓库目录
cd /path/to/your/repo
步骤 2:将现有仓库连接到 Bitbucket
hg push https://user@bitbucket.org/user/test
步骤 3:更新仓库 .hgrc
文件中的默认字段为其新 URL
[paths]
default = https://user@bitbucket.org/user/test
工作流程
简而言之,大多数合作者(维护者除外)需要学习以下命令:
hg clone https://bitbucket.org/user/project1
hg commit -m "Commit message"
hg push
hg pull -u
也建议在推送之前总是先拉取(pull)。
接下来,可能会发生两种情况:
-
没有变化,没有上游更新。
-
有更新,可以通过
hg log -G
检查更改。
看起来像这样
@ changeset: 1:cd6ae8660e6f
| tag: tip
| user: Joe Doe <user@gmail.com>
| date: Thu Aug 09 22:17:47 2018 +0200
| summary: My second commit
|
o changeset: 0:cb0b44f99bd2
如果上游有更改并被拉取,那么现在你有了一个新的分支头,你应该合并它。
所以在第二种情况下:
hg log -G
看起来像这样:
o changeset: 2:05548327a272
| tag: tip
| parent: 0:cb0b44f99bd2
| user: John Smith <user2@gmail.com>
| date: Thu Aug 09 22:17:22 2018 +0200
| summary: My second commit
|
| @ changeset: 1:cd6ae8660e6f
|/ user: Joe Doe <user@gmail.com>
| date: Thu Aug 09 22:17:47 2018 +0200
| summary: My second commit
|
o changeset: 0:cb0b44f99bd2
所以你应该合并:
hg merge -r 2
并得到:
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
所以 hg log -G
显示为:
@ changeset: 3:df2f1f46a80c
|\ tag: tip
| | parent: 1:cd6ae8660e6f
| | parent: 2:05548327a272
| | user: Joe Doe <user@gmail.com>
| | date: Thu Aug 09 22:20:44 2018 +0200
| | summary: Merged successfully
| |
| o changeset: 2:05548327a272
| | parent: 0:cb0b44f99bd2
| | user: John Smith <user2@example.com>
| | date: Thu Aug 09 22:17:22 2018 +0200
| | summary: My second commit
| |
o | changeset: 1:cd6ae8660e6f
|/ user: Joe Doe <user@gmail.com>
| date: Thu Aug 09 22:17:47 2018 +0200
| summary: My second commit
|
o changeset: 0:cb0b44f99bd2
冲突的更改集应留给维护者来合并。
实时协作写作
有几种选择可供使用:
-
Overleaf(和 ShareLatex,现在是 Overleaf 的一部分)是一个基于 Web 的实时协作编辑器。
-
Bluelatex 是一个用 Scala 编写的基于 Web 的实时协作编辑器。
-
Cocalc(前身为 SageMathCloud)提供一个协作 LaTeX 编辑器。
-
Authorea 是一个基于 Web 的实时协作编辑器。
-
Papeeria 是一个基于 Web 的实时协作编辑器。
这种方法的优点是无需额外的软件,缺点是无法轻松使用自己喜欢的 LaTeX 编辑器。因此,几乎所有这些服务都允许通过 Git 访问(这要求安装 Git 或 Mercurial + hg-git 插件)。
这些服务在几年前几乎都是免费的;然而,现在只有非常基本的功能是免费的,以下表格详细说明了这一点。
名称 | 合作者 | 文档 | 通过 Git 访问(或 Mercurial) |
---|---|---|---|
Authorea | 无限制 | 免费提供 3 个文档 | 是 |
Overleaf | 仅限一个作者 | 无限制 | 是 |
Papeeria | 无限制 | 无限制 | 仅限公共仓库(免费版本) |
管理协作参考文献
撰写科学文章、报告和书籍需要引用所有相关的来源。BibTeX 是一个非常好的引用工具,用于引用参考文献并生成参考书目(Markey 2005, Fenn 2006)。可以在 CTAN(http://www.ctan.org)和 LaTeX 参考文献样式数据库(http://jo.irisson.free.fr/bstdatabase/)中找到许多不同的 BibTeX 样式。如果找不到合适的 BibTeX 样式,大多数常见样式可以方便地使用 custombib/makebst(http://www.ctan.org/tex-archive/macros/latex/contrib/custom-bib/)进行自定义组合。此外,BibTeX 样式文件可以手动创建或修改;但是,这需要了解 BibTeX 样式文件中使用的(无名)后缀堆栈语言(Patashnik 1988)。
在我们的部门,我们有一个共同的 BibTeX 格式的参考文献数据库(.bib 文件)。它位于我们的公共 texmf 树中的 /bibtex/bib/
子目录下(见图 1)。因此,所有用户只需使用文件名(不包括完整路径)来指定这个参考文献数据库,无论用户的公共 texmf 树工作副本位于何处。
所有用户都使用图形 BibTeX 编辑器 JabRef(http://www.jabref.org)编辑我们的参考文献数据库。由于 JabRef 是用 Java 编写的,它可以在所有主要操作系统上运行。由于 JabRef 的不同版本通常会以稍微不同的方式保存文件(例如,在不同的位置插入换行符),因此所有用户应该使用相同的(例如最新的稳定版)JabRef 版本。否则,不同版本的 .bib 文件之间会有很多差异,这些差异仅来自使用不同版本的 JabRef。因此,找到比较文档之间的真实差异将变得很困难。此外,冲突的可能性会大大增加(见“Subversion 真正的不同”部分)。由于 JabRef 使用作者操作系统的本地换行符保存 BibTeX 数据库,因此建议添加 Subversion 属性 svn:eol-style
并将其设置为 native
(见“Subversion 真正的不同”部分)。
图 3:JabRef 的高度灵活性与配置
JabRef 非常灵活,并且可以在许多细节上进行配置。为了简化我们的工作,我们对 JabRef 的默认配置进行了一些修改。首先,我们指定了 BibTeX 键的默认模式,以便 JabRef 可以自动生成我们所需格式的键。这可以通过选择 Options → Preferences → Key pattern 并修改 Default pattern 字段中的所需模式来完成。例如,我们使用 [auth:lower][shortyear]
来获取第一作者的姓氏的小写形式和出版年份的最后两位数字(见图 3)。
图 4:在 JabRef 中设置常规字段
其次,我们添加了 BibTeX 字段 location
,用于存放出版物的硬拷贝信息(例如书籍或文章副本所在位置)。该字段可以包含持有硬拷贝的用户姓名以及其所在位置,或是图书馆的名称及书架编号。可以通过选择 Options → Set up general fields 并在以 General: 开头的行中添加 location
(使用分号 ;
作为分隔符)来在 JabRef 中添加此字段(见图 4)。
图 5:在 JabRef 中指定“主 PDF 目录”
第三,我们将所有出版物的 PDF 文件存放在文件服务器的特定子目录中,并使用 BibTeX 键作为文件名。我们通过选择 Options → Preferences → External programs 并在 Main PDF directory 字段中添加此子目录的路径来告知 JabRef 该子目录(见图 5)。如果有出版物的 PDF 文件可用,用户可以点击 JabRef 中 PDF 字段左侧的 Auto 按钮,自动将 PDF 文件的文件名添加进去。现在,所有访问文件服务器的用户都可以通过简单地点击 JabRef 中的 PDF 图标打开出版物的 PDF 文件。
如果我们将项目的 LaTeX 源代码发送到期刊、出版社或其他没有访问我们公共 texmf 树的人的地方,我们不会包含整个参考文献数据库,而是使用 Perl 脚本 aux2bib(http://www.ctan.org/tex-archive/biblio/bibtex/utils/bibtools/aux2bib)提取相关条目。
结论
本 Wikibook 描述了有效组织 LaTeX 文档协作准备的一种可能方式。所提出的解决方案基于 Subversion 版本控制系统,以及其他几个软件工具和 LaTeX 包。然而,仍然有一些可以改进的问题。
首先,我们计划让所有用户安装相同的 LaTeX 发行版。由于 TeX Live 发行版(http://www.tug.org/texlive/)适用于 Unix 和 MS Windows 操作系统,我们可能会建议用户将来切换到这个 LaTeX 发行版。(目前,我们的用户使用不同的 LaTeX 发行版,这些发行版提供不同的 LaTeX 包选择和某些包的不同版本。我们通过在我们的公共 texmf 树中提供一些包来解决这个问题。)
其次,我们考虑简化共同参考文献数据库的解决方案。目前,它基于版本控制系统 Subversion、图形 BibTeX 编辑器 JabRef 和存储出版物 PDF 文件的文件服务器。对于不常使用这些工具的用户来说,使用三种不同的工具来完成一个任务是非常具有挑战性的。此外,文件服务器仅能由本地用户访问。因此,我们考虑实施一个集成的服务器解决方案,如 WIKINDX(http://wikindx.sourceforge.net/)、Aigaion(http://www.aigaion.nl/)或 refBASE(http://refbase.sourceforge.net/)。使用此解决方案只需要一台可以连接互联网的计算机和一个 Web 浏览器,这使得不常使用的用户可以更加方便地使用我们的数据库。此外,存储的 PDF 文件不仅可以从部门内部访问,还可以从全球访问。(根据存储 PDF 文件的版权,服务器的访问——或者至少是 PDF 文件的访问——需要限制为部门成员。)即使我们部门的非 LaTeX 用户也可能从基于服务器的解决方案中受益,因为这些服务器不仅提供 BibTeX 格式的数据,还可以提供其他格式的数据,从而使得在其他文字处理软件中使用这个参考文献数据库变得更容易。
我们鼓励所有读者通过添加更多提示或想法,或者提供更多协作编写 LaTeX 文档的解决方案,来为本 Wikibook 做出贡献。
致谢
Arne Henningsen 感谢 Francisco Reinaldo 和 Géraldine Henningsen 提供的评论和建议,这些帮助他改进并澄清了本文内容;感谢 Karsten Heymann 提供的许多关于 LaTeX、BibTeX 和 Subversion 的提示和建议;还感谢 Christian Henning 及其同事们支持他在部门内推广 LaTeX 和 Subversion 的愿望。
参考文献
-
Fenn, Jürgen (2006): 管理引用和参考书目与 BibTeX。The PracTEX Journal, 4. http://www.tug.org/pracjourn/2006-4/fenn/.
-
Markey, Nicolas (2005): Tame the BeaST. The B to X of BibTeX. http://www.ctan.org/tex-archive/info/bibtex/tamethebeast/ttb_en.pdf. Version 1.3.
-
Oren Patashnik. Designing BibTeX styles. http://www.ctan.org/tex-archive/info/biblio/bibtex/contrib/doc/btxhak.pdf.
-
Tools for collaborative paper-writing.