LaTeX教程(014)-LaTeX文档结构(14)

LaTeX教程(014)- LaTeX \LaTeX LATEX文档结构(14)

2.3.3 multitoc - 将目录设置为多栏

multitoc包的使用方法相当简单,只需要调用这个包,并将要设置为多栏(默认是双栏)的目录指定到包选项中即可。如\usepackage[toc]{multitoc},设置的就是目录列表,除此之外还可以指定loflot(图形列表和表格列表)。我们用一个例子演示一下:

\documentclass{article}
\usepackage{geometry}
\usepackage[toc]{multitoc} %将目录设置为双栏
\begin{document}
\tableofcontents
\section{section one}
\subsection{subsection one}
\section{section two}
\subsection{subsection two}
\subsection{subsection three}
\subsection{subsection four}
\end{document}

编译(只截取目录):

在这里插入图片描述

很用有使用超过双栏的时候,但是在必要的时候,你可以重定义\multicolumntoc\multicolumnlof或者\multicolumnlot,将它们重定义为你想要的数字(栏数)。如上面的例子中放置一行\renewcommand{\multicolumntoc}{3},可将目录设置为3栏:

在这里插入图片描述

2.3.4 LaTeX \LaTeX LATEX的底层接口

我们前面讲了如何通过一些包定制目录,在这一节的最后一个小节中,我们介绍一下 LaTeX \LaTeX LATEX为目录提供的底层接口,其中有一些命令是我们之前用过的。实际上titletoc包也在底层调用了这些接口。

将信息写入目录文件

有两个命令用来将数据写入目录文件: \addcontentsline\addtocontents。它们自动被标题命令和图表的标签命令调用,当然,如果有必要的话,我们是可以直接手动调用它们的。

\addcontentsline{ext}{type}{text}

\addcontentsline命令将text参数中的内容,连同一些附带的信息,比如当前的页码等,一起放入后缀为ext的文件中(这里是指ext参数中填的内容,通常是loftoc或者lot,分别对应我们已经熟悉的三种列表文件)。最好用\protecttext内容保护起来。type参数中填写当前条目的类型,对于.toc文件来说,通常就是标题的类型,如chaptersection等(不带反斜线),对于.lof.lot文件来说,通常分别是figure或者table

\allcontentsline命令会在使用章节划分命令(如\chapter\section等),或者浮动体环境中的\caption命令时自动调用。然而,该命令没有为条目的编号单独分配一个参数,而是关于标题的一切文本内容,只留了一个text参数,那么我们如何通过该命令让 LaTeX \LaTeX LATEX知道当前条目有没有编号,以及编号是什么呢?我们可以在text参数中使用\numberline命令:

\protect\numberline{number}heading

heading就是我们的标题文本,number是我们要填的标题编号。例如,在一个插图环境(figure)中使用\caption命令, LaTeX \LaTeX LATEX就会调用命令:

\addcontentsline{lof}{figure}{\protect\numberline{\thefigure}caption text}

\numberline会直接被写入文件中,而\thefigure会被替换成一个编号(当前图片的编号),被写入lof文件中。

在排版目录列表期间,一个合适的\numberline的定义会被用来以一种特定的方式排版条目的编号,如插入一段额外的距离,或者变一种不同的字体等。不足之处是,这种方式不具有更好的通用性,它没有为编号单独划分一个参数,你不能轻易地对编号进行任意的改变,并且它需要一个好的\numberline定义,这并不是那么容易提供的。

\addtocontents{ext}{test}

\addtocontents命令没有type参数,它被用来插入特殊格式的条目,和任何其他的目录行都不直接相关。例如,标准类的\chapter命令会调用以下命令:

\addtocontents{lof}{\protect\addvspace{10pt}}
\addtocontents{lot}{\protect\addvspace{10pt}}

.lof.lot文件中额外放置一段空白,来将不同章的图表条目分开。使用\addvspace(只能在垂直模式下使用)在不同的章之间至多插入10pt的距离,如果一章中没有图表,也不会产生奇怪的缺口。这是\addvspace的特殊之处,如果某处插入多个\addvspace命令,那么只有参数最大的会生效。例如

abc...

\addvspace{10pt} %

\addvspace{20pt}

\addvspace{10pt}

def...

只会在abc…和def…之间插入一段20pt的垂直距离。然而,\addcontentsline\addtocontents\addvspace在作为用户层命令使用时,很容易出现奇怪的错误,尤其是\addvspace,它只能在垂直模式下使用,这就意味着,\addcontentsline设置的条目必须以垂直模式结束。因此你需要了解这样的条目是如何被处理的,以至于能够在其中进行任意的格式化操作。而这正是下一节的任务。

如果文档使用了\include声明,那么\addcontentsline\addtocontents命令的使用就有一个局限,它们都不能和\include命令在同一层级下使用。例如:

\addtocontents{toc}{\protect\setcounter{tocdepth}{1}}
\include{sect1}

其中sect1.tex文件中含有\section命令,这样就会得到一个意料之外的结果,.toc文件中会有以下内容:

\contentsline {section}{\numberline {1}Section from sect1}{2}{}%
\setcounter{tocdepth}{1}

可以看到这两行命令的顺序颠倒了,\section条目本应在\setcounter{tocdepth}{1}命令的后面,现在跑到前面去了。解决方法就是避免使用\include,或者把\addtocontents\addcontentsline命令放在\include所包含的文件里面。

排版一个目录列表

在上一篇中,我们做了一个演示,我们手动创建了一个.toc文件,并且还手动修改过里面的内容,然后使用\input命令将.toc文件插入到了文档中。我们知道,对于文档中的条目,真正起作用的是.toc.lof.lof文件中的那些内容。

而从上面的内容中,我们又知道了,目录条目的产生都缘于\addcontentsline\addtocontents命令或隐示或显示的调用,那么在这两个命令被执行之后,接下来发生了什么?它们是如何对.toc.lof.lof文件产生影响的?

实际上, LaTeX \LaTeX LATEX执行命令

\addcontentsline{ext}{type}{text}

时,就会在后缀名为ext(这取决于我们在这个参数里填的是什么)的文件中放置一行(连同注释符%一起):

\contentsline{type}{text}{page}{anchor-name}%

其中page是当前\addcontentsline放置的位置在文档中的页码。anchor-name默认是空的,除非加载了hyperref包。这种情况下该参数内会被填入一个超链接的锚点名(anchor name)。

\addtocontents{ext}{text}则更简单,它仅仅是将text参数的内容复制到后缀名为ext的文件中,不会写入其他更多的信息。因此,一个典型的目录列表文件包含一些\contentsline命令,可能还包含一些由\addtocontents命令写入的特殊格式的文本。我们做个演示:

\documentclass{article}
\usepackage[a5paper,margin=1in]{geometry}
\begin{document}
\tableofcontents
\section{section one}
\subsection{subsection one}
\stepcounter{subsection}
\addcontentsline{toc}{subsection}%
{\protect{\numberline{\thesubsection}}this is a test of add contentsline}
\section{section two}
\addtocontents{toc}{the is a test of addtocontents}
\end{document}

编译:

在这里插入图片描述

我们使用\addcontentsline添加了一个subsection的条目,并且将编号\thesubsection也放置了进去,由于我们没有使用\subsection命令,所以subsection的计数器不会自动递增,我们要使用命令\stepcounter使subsection加1。

\addtocontents命令没有type参数,但是我们从格式上可以看出,添加的文本的默认层级等同于subsection

打开.toc文件,可以看到以下内容:

\contentsline {section}{\numberline {1}section one}{1}{}%
\contentsline {subsection}{\numberline {1.1}subsection one}{1}{}%
\contentsline {subsection}{{\hbox to\@tempdima {1.2\hfil }}this is a test of add contentsline}{1}{}%
\contentsline {section}{\numberline {2}section two}{1}{}%
the is a test of addtocontents

当然,既然最终起作用的命令是\contentsline,那么我们也可以在文档中直接使用\contentsline命令来创建一个目录。

下面展示一个典型的例子。注意大多数(并非全部)标题编号都是作为\numberline的参数输入的,以便能有统一的、合适的缩进。出于历史的原因, LaTeX \LaTeX LATEX在这一点上并不一致,标准类的\part命令的编号并没有使用\nunmberline命令,而是直接为其指定了一种特殊的格式。

\documentclass{book}
\usepackage[a5paper,margin=1in]{geometry}
\setcounter{tocdepth}{3}
\begin{document}
\tableofcontents
\contentsline {part}{I\hspace{1em}Part}{2}{}%
\contentsline{chapter}{\numberline{1}A-Head}{2}{}%
\contentsline{section}{\numberline{1.1}B-Head}{3}{}%
\contentsline{subsection}%
{\numberline{1.1.1}C-Head}{4}{}%
\contentsline{subsection}%
{\numberline{}With Empty Number}{5}{}%
\contentsline{subsection}{Unnumbered C-Head}{6}{}%
\contentsline{subsection}%
{\numberline{1.1.2}Another C-Head}{8}{}%
\contentsline{section}%
{\numberline{1.2}Another B-Head}{10}{}%
\end{document}

编译:

在这里插入图片描述

\contentsline命令执行后,又会根据type参数的不同,调用\l@type命令。每一种\l@type命令都有一个定义,例如,在report类中你可以看到以下定义:

\newcommand\l@section {\@dottedtocline{1}{1.5em}{2.3em}}
\newcommand\l@subsection {\@dottedtocline{2}{3.8em}{3.2em}}
\newcommand\l@subsubsection{\@dottedtocline{3}{7.0em}{4.1em}}
\newcommand\l@paragraph {\@dottedtocline{4}{10em}{5em}}
\newcommand\l@subparagraph {\@dottedtocline{5}{12em}{6em}}
\newcommand\l@figure {\@dottedtocline{1}{1.5em}{2.3em}}
\newcommand\l@table {\l@figure}

根据定义,\l@type实际上是被指定了3个参数的命令\@dottedtocline(它实际上有5个参数),被指定了的参数分别是level-条目层级、indent-缩进和numwidth-编号宽度,剩下两个保留参数分别是textpage,它会自动从\contentsline命令中接收到。我们知道其实还有一个anchor-name参数,这个参数大多数时候是空的,而如果指定了hyperref包,这些定义就会改变,同时最后一个参数也会被接收到。

注意,有一些标题以一种更复杂的方式建立它们的目录条目,这就使得标准类中的\l@part\l@chapter(包括article类中的\l@section)并不是使用\@dottedtocline定义的。通常它们用一些特殊的格式命令,可能会省略引导线或者用更大的字体排版等。

所以要定义这些条目列表的布局,就必须声明合适的\l@type命令(这些正是titletoc包的\dottedcontents\titlecontents所做的事)。下面我们展示一种不通过宏包来使用\@dottedtocline的简单方法。这个命令的形式如下:

\@dottedtocline{level}{indent}{numwidth}{text}{page}

最后两个命令和\contentsline的第二和第三个命令保持一致,\@dottedtocline通常会被\contentsline所调用。其他的命令如下:

  • level: 条目的层级。
  • indent: 从左边距开始的缩进。
  • numwidth: 用来放置条目编号的盒子的宽度(如果使用了\numberline的话),对于多行的标题文本,这些缩进对所有行都有效。

另外,还使用了以下这些全局格式参数,它们对所有出现的条目生效。这些参数都是长度数值。要改变它们,必须使用\renewcommand重定义。

  • \@pnumwidth: 放置页码的盒子的宽度
  • \@tocrmarg: 条目文本的右侧缩进,对于多行文本来说,它是除最后一行的所有行的缩进。可以是一个弹性长度。
  • \@dotsep: (引导线中)两个点之间的间隔,单位是mu(18mu-1em),这里填入一个数字(如1.7,或2),单位不用写。你可以通过将数字设置的足够大来让这些点显示不出来。

我们用一张图表示这些参数的作用位置:

在这里插入图片描述

numwidth参数中的编号靠左对齐(如果有编号的话)。我们可以通过改变indentnumwidth的设置来为嵌套的条目实现合适的缩进。

有时候对它们进行调整是必须的,如果你使用的是标谁类,比如article,而文档的篇幅又很长,那么就可能会出现11.12这样的编号(第11节第12小节),此时原本的放置编号的空间可能就不太够用了,编号和文本会离得很近,甚至重叠。我们作个演示:

\documentclass{article}
\usepackage[a5paper,margin=1in]{geometry}
\setcounter{tocdepth}{3}
\begin{document}
\contentsline{section}{\numberline{11}A-Head}{3}{}%
\contentsline{subsection}{\numberline{11.1}B-Head}{3}{}%
\ldots %
\contentsline{subsection}{\numberline{11.12}B-Head}{7}{}%
\end{document}

编译:

在这里插入图片描述

这种情况下,可以重定义\@subsection为编号保留更多的空间(调整\@dottedtocline的第三个参数),我们作个演示:

\documentclass{article}
\usepackage[a5paper,margin=1in]{geometry}
\setcounter{tocdepth}{3}
\makeatletter
\renewcommand\l@subsection{\@dottedtocline{2}{1.5em}{3em}}
\makeatother
\begin{document}
\contentsline{section}{\numberline{11}A-Head}{3}{}%
\contentsline{subsection}{\numberline{11.1}B-Head}{3}{}%
\ldots %
\contentsline{subsection}{\numberline{11.12}B-Head}{7}{}%
\end{document}

编译:

在这里插入图片描述

这里要注意, LaTeX \LaTeX LATEX的内部命令(就是带@符号的命令)在文档中使用时要用\makeatletter\makeatother将其包含其中。其他类似的命令的重定义方式也和\@subsection一样,我们不再一一演示。

少数时候我们可能需要扩展放置页码的盒子的宽度,例如,如果页码是根据part设置的,如"A-78"、"B-328"等,那么默认的空间可能就不够了,然后弹出一个Overfull hbox的警告(盒子溢出)。一种解决方法就是重定义\@pnumwidth的值,使其至少能够放置最宽的页码:

\makeatletter
\renewcommand\@pnumwidth{2cm}
\makeatother

\@pnumwidth一经调整,通常\@tocrmarg也要跟着调整,以保证其布局的一致性。

这些例子能让我们看出titletoc提供的高级接口的优势,使用像\contentspush这样的命令显然是一种更简单的解决方法。

添加其他的目录文件

有些时候你可能会想要标记一些其他的数据,并将其做成列表。这样你就需要创建一个新的目录文件。

例如,假设你想要在一个article中收集所有对艺术家的注释,那么你需要定义两个命令。第一个是\artist,用来排版艺术家的姓名,并且将这两个参数联结起来,同时将当前命令在文档中所处的位置写为当前的页码记录到文件中。第二个是\listofartistnotes,用来读取文件中的内容,并且将这些内容布局在文档中插入该文件的地方。

要实现这一点,\listofartistnotes命令要调用\@starttoc{ext},它会读取后缀为ext的文件(这里指我们在ext处填的参数),这个命令也会被\tableofcontents\listoffigures\listoftables调用。这个文件的后缀是自定义的,可以是任意没有用过的字符串,如.rec。我们可以单独创建一章,如\chapter*{Notes on artists},用来放置这个列表(只需要将命令\listofartistnotes放置在这一章中),如果想要的话,也可以使用\addcontentsline将这一章的标题放置在目录文件中(.toc)。

而真正控制.rec文件中的条目排版的命令是\l@note,这是一个需要我们定义的命令。在下面的例子中,这些注释都分别作为一个段落排版,并且后面紧跟着一个斜体的页码。如果不想直接定义页码的样式命令,也可以使用titletoc's接口,如\titlecontents{note}...

\documentclass{article}
\usepackage[a5paper,margin=1in]{geometry}
\newcommand\artist[2]{#1\addcontentsline{rec}{note}{#1: #2}}

\makeatletter
\newcommand\listofartistnotes%
{\section*{Notes on artists}\@starttoc{rec}}%
\newcommand\l@note[2]{\par\noindent#1,~\textit{#2}\par}
\makeatother
\begin{document}
The version of Ravel's Boléro by \artist{Jacques Loussier Trio}{A strange experience} is rather unusual. Quite interesting is Davis' Blue in Green
by \artist{Cassandra Wilson}{A wonderful version}.
\listofartistnotes
\end{document}

编译:

在这里插入图片描述
关注【年轻人 你渴望力量么】

  • 11
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值