LaTeX教程(011)- LaTeX \LaTeX LATEX文档结构(11)
2.3 目录的结构
首先简单介绍一下与目录相关的信息。目录(TOC: table of contents)是一个特殊的列表,它列出章节单位的标题以及它们所在的页码。这些标题可能会嵌套多层。而有关文档中浮动体的列表,也就是表格清单(list of tables)和图形清单(the list of figures),并不会如此复杂,因为它们都在同一个级别上。标准的 LaTeX \LaTeX LATEX可以自动创建这三种列表。
我们在003篇讲到了,目录的信息会保存在.toc
文件中。该文件会保存所有的目录信息,但是在文档中,并不是所有的级别的目录都会被生成。我们在004篇提到,控制所生成的目录的结构深度的计数器是tocdepth
。该计数器默认是3,也就是说,在不设置的情况下,文档中的目录会显示到\subsubsection
。使用\setcounter
命令可以设置它的值。我们做个演示:
\documentclass{article}
\usepackage[a5paper,margin=1in]{geometry}
\begin{document}
\setcounter{tocdepth}{2}
\tableofcontents
\section{A section}
some text ...
\subsection{A subsection}
some text ...
\subsubsection{A subsubsection}
some text ...
\paragraph{A paragraph} some text ...
\end{document}
编译:
目录只生成到第2级标题(\subsection
)。注意,只有将\setcounter{tocdepth}{2}
命令放置在\tableofcontents
的前面,它才会生效。
我们打开.toc
文件,可以发现尽管文档中的目录仅生成了一部分,但.toc
文件中依旧保存了所有的目录信息:
\contentsline {section}{\numberline {1}A section}{1}{}%
\contentsline {subsection}{\numberline {1.1}A subsection}{1}{}%
\contentsline {subsubsection}{\numberline {1.1.1}A subsubsection}{1}{}%
\contentsline {paragraph}{A paragraph}{1}{}%
这个计数器的影响是全局的。如果想要更细致的控制,比如,你如果想要使附录部分比前面的章节在目录中显示的标题级别更多或更少,可以使用tocvsec2
(作者Peter Wilson)宏包。
类似的,图形清单(the list of figures)的信息保存在.lof
文件中,表格清单(list of tables)的信息保存在.lot
文件中。这些文件保存了图形和表格的\caption
命令的参数中指定的文本。
在生成这些交叉引用时,至少需要运行两次。第一次收集相关信息,第二次将这些信息排版在文档中。而第二次排版的内容可能导致交叉引用信息发生变化,从而可能需要第三次编译。这也是传统的文档在前言和正文使用不同的页码系统的原因。否则,每多生成一页目录,后面的页码就会全部发生变化。
常规情况下,目录文件都是
LaTeX
\LaTeX
LATEX自动生成的,通过在底层使用\addcontentsline
、\addtocontents
和\numberline
命令(有的是我们可以在.toc
文件中看到的命令)。我们可以手动使用这些命令,为目录添加一些特殊的条目。例如,\section*
命令,不会生成目录条目。但如果你不想要标题的编号,但是又想在.toc
文件中有条目,你可以使用\addcontentsline
命令,我们做个演示:
\documentclass{article}
\usepackage[a5paper,left=1.8in,right=1.8in,top=2.6in,bottom=2.8in]{geometry}
% 为了生成两页内容,这里设置尽可能大的页边距
\begin{document}
\tableofcontents
\section*{Foreword}
\addcontentsline{toc}{section}{\protect\numberline{}Foreword}
A starred heading with the TOC entry manually added. Compare this to the form used for the bibliography.
\section{Thoughts}
We find all in \cite{k1}.
\subsection{Contact info}
E-mail Ben at \cite{k2}.
\begin{thebibliography}{9}
\addcontentsline{toc}{section}{\refname}
\bibitem{k1} Ben User, Some day will
never come, 2010
\bibitem{k2} BUser@earth.info
\end{thebibliography}
\end{document}
编译:
\addcontentsline
命令用来手动向一个列表中插入一个条目,它有三个参数,第一个参数用文件后缀指定要写入的文件,如toc
表示目录文件(.toc
)。可以通过同样的方式指定lof
文件以及lot
文件(见下一个例子)。第二个参数指定插入条目的层级,上面的例子中,我们指定的是section
。第三个参数指定我们要插入的条目,\protect
命令是一个保护命令,这里先不讲。\numberline
命令是生成该条目的编号的命令。它带有一个参数,参数里填入我们想要的编号(不是数字也可以)。在前面的例子中,我们不需要编号,但是仍然使用了这个命令,只是参数是空的。这是为了保留编号的位置,以使得同级别的标题文本能够对齐。如果不使用它,那么标题文本就会占据编号的位置(就像下面的演示那样)。
\documentclass{article}
\usepackage[a5paper,margin=1in]{geometry}
\usepackage{graphicx}
% graphicx是用来支持图片的宏包
\begin{document}
\listoffigures
\addcontentsline{lof}{subsection}{\protect\numberline{no.}test01}
\addcontentsline{lof}{subsection}{test02}
\begin{figure}[htbp]
\centering % 图片居中
\includegraphics[width=\columnwidth]{fig001.png}
% \includegraphics是用来插入图片的命令。
% 注意,我们暂且不讲外部资源的读取路径问题,只需要将图片和.tex文件放在同一文件夹下,
% 并且名称与上面参数中的字符相同(这里是fig001.png)。
\caption{this is a test}
% 不论是图片还是表格,都使用\caption命令生成名称出现在图片或表格的下方。
% 名称同时也是一个索引,会出现在对应的清单中。
\end{figure}
\end{document}
编译:
这一次我们生成的是图形清单,写入的是lof
文件。插入test01
时,将编号设置为no.
。test02
没有使用\numberline
命令,因此编译的位置被标题文本占据了。一般情况下这不是我们想要的,因此建议加上\numberline
命令,无论该条目有没有编号。另外,可以看到默认情况下,图形列表中的条目层级都是subsection
。这个例子中,插入的图片没有截取出来,我们暂时不讲与图片有关的内容。
这里要注意,\caption
命令还可以指定一个选项,它可以让我们分开指定图表下的名称和清单中的条目。例如,我们使用\caption[A test]{This is a test}
之后,就会在发现图表下方的名称依旧是This is a test
,而清单中的条目变成了A test
。
条目对应的页码,和\addcontentsline
使用的位置有关。也就是说,我们在第几页使用该命令,插入的条目就会生成对应的页码。因此总是建议在标题后面紧接着使用\addcontentsline
命令插入对应的条目。例如,在上一个例子中,我们在\section*{Foreword}
后面立刻使用\addcontentsline{toc}{section}{\protect\numberline{}Foreword}
,以使得目录能够正确地捕获该标题的页码。如果我们在第1页的\section*
命令后面增加一些内容,直到第2页才使用\addcontentsline
插入它的条目,那么目录就会认为该标题位于第2页。
也正是基于这个原因,我们可能无法将图形清单和表格清单的标题(例如List of Figures)准确地插入到目录(TOC)中,因为这些清单可能会生成很多页。例如,我们使用\listoffigures
以使得
LaTeX
\LaTeX
LATEX从第x页开始生成图形清单,直到x+3页结束。此时仅管我们在\listoffigures
命令之后立刻使用\addcontentsline
命令插入List of Figures条目,目录也会认为该标题在第x+4页。即使将\addcontentsline
放在\listoffigures
前面也不行,通常这些清单命令会从新的一页开始,放在前面的\addcontentsline
会让
LaTeX
\LaTeX
LATEX认为该标题在第x-1页。这和清单命令的定义有关,如果要实现这一点,我们可以修改类文件中的清单命令的定义,将\addcontentsline
命令放在这些命令的定义中(例如放在标题的后面)。
另外一种方法是使用tocbibind
包。它自动将所有清单的标题都插入到目录中。如果不想要某个清单的条目,则可以在调用该包时指定对应的选项排除它。可以指定的选项有notbib
、notindex
、nottoc
、notlof
和notlot
。例如,默认情况下,目录本身的标题Contents
也会出现在目录中,我们可以指定nottoc
选项排除它,还可以使用numbib
和numindex
为对应的标题增加编号。
这里介绍一下makeidx
宏包。makeidx
宏包允许我们插入索引,从而自制一些类似于目录的索引列表。我们做个演示:
\documentclass{article}
\usepackage[a5paper,margin=1in]{geometry}
\usepackage{makeidx} % 加载 makeidx 宏包用于索引功能
\makeindex % 初始化索引
\begin{document}
\section{A section}
some text ... \index{idx01}
\section{An another section}
some text ... \index{idx02}
\printindex
\end{document}
这个包会生成特殊的文件,最好使用命令行编译,否则文档中无法生成索引目录。先使用
LaTeX
\LaTeX
LATEX正常编译.tex
文件,会在同一个文件夹内生成一个.idx
文件,然后使用makeindex
命令编译.idx
文件:
makeindex filename.idx # filename是你的文件名
生成一个.ind
文件。最后再用
LaTeX
\LaTeX
LATEX编译一次.tex
文件。一共至少三次编译:
\printindex
命令可以将索引列表打印出来,列表中的每一条索引后面都会显示出插入索引处的页码。tocbibind
包的选项numindex
可以在Index
前面增加编号。
在book
以及report
类中,这些清单在目录中生成的条目(如List of Figures)的层级都是chapter
,我们可以通过指定tocbibind
的包选项section
,来将它们变成section
层级。
2.3.1 tocdata
—向目录中添加额外的数据
Brian Dunn开发的tocdata
包提供了一个接口,使我们可以向目录中添加一些额外的数据,例如,有些多人合著的作品会想要将不同的作者名单陈列在他们各自的条目旁边。该宏包与大多数文档类兼容良好,并且支持titletoc
或tocloft
等宏包。
在调用了tocdata
包之后,在要添加作者的标题前面使用\tocdata{toc}{...}
命令即可将文本(作者名称)添加在目录中对应的条目之后:
\documentclass{article}
\usepackage[a5paper,margin=1in]{geometry}
\usepackage{tocdata} % 调用tocdata包
\begin{document}
\tableofcontents
\section{On Cookies}
\tocdata{toc}{Ben User} % 给下面的标题添加作者
\subsection{Preparing cookies}
Text of his recipes \ldots
\tocdata{toc}{Cookie Monster} % 给下面的标题添加作者
\subsection{Eating cookies}
How to do it \ldots
\end{document}
编译:
默认情况下添加的材料为小号斜体,这些格式是通过\tocdataformat
格式化的,因此我们可以通过重定义该命令来修改它们的格式。我们在上一个例子中的导言区中添加以下内容:
\usepackage{color}
\renewcommand\tocdataformat[1]{\textnormal{%
\textcolor{blue}{--- \small\itshape#1}}}
编译:
color
包可以设置文档中材料的颜色,例如使用\textcolor{red}{text}
可以将text变成红色。而\tocdataformat
的一个参数显然就是要添加的文本。---
生成一个破折号。
你也可以向图形清单或者表格清单中添加数据,只需要将\tocdata
命令用在图形或者表格的前面,并且将第一个参数换成lof
或者lot
。
如果这样的数据你不仅想添加在目录或者清单中,也想添加在文档中,那么就要使用一组特殊的命令\<name>author
:
\sectionauthor[list-entry]{title}[prefix]{first}{last}[suffix]
\sectionauthor*{title}[prefix]{first}{last}[suffix]
出于\sectionauthor
的定义,使用第一个命令就相当于插入了以下命令:
\tocdata{toc}{first last} % 将姓名插入到目录中
\section[list-entry]{title\nopagebreak\tocdatapartprint{prefix}{first}{last}{suffix}}
\index{last, first}
这里的first
和last
指的是first name
和last name
,也就是名和姓。当然,它们可以是任意文本,只是通常来说,填入姓名对我们才是有意义的。prefix
和suffix
分别是前置文本与后置文本。另外,上面我们用\sectionauthor
做演示,实际上,每一个章节划分命令都有一个对应的\<name>author
命令。<name>
就是章节命令的名称。
title
是我们要生成的标题; \nopagebreak
是禁止在此处断页的命令; \tocdatasectionprint
命令将姓名及与姓名相关的数据以一定格式排版到标题文本中。
星号命令\sectionauthor*
与其原命令的区别仅仅是它的定义中没有\tocdata
,这意味着它不会将名字添加到目录中。first
参数可以空置。我们用一个例子演示:
\documentclass{article}
\usepackage[a5paper,margin=1in]{geometry}
\usepackage{makeidx}
\makeindex
\renewcommand\indexspace{\par\vspace{2pt}} % 重定义索引列表中的间距
\usepackage{tocdata}
\begin{document}
\tableofcontents \smallskip
\section{On Cookies}
\subsectionauthor{Preparing cookies}[Sir]{Ben}{User}
Text of his recipes \ldots
\subsectionauthor{Eating cookies}{}{Cookie Monster}[!!]
How to do it \ldots
\printindex
\end{document}
对于图片或表格的名称,也有一个和\<name>author
相似的命令\captionartist
来插入额外数据(如作者姓名)。不同的是\captionartist
多了一个extra-text
选项。我们使用该命令替换\caption
命令。它的形式如下:
\captionartist[list-entry]{title}[extra-text][prefix]{first}{last}[suffix]
选项list-entry
和参数title
分别相当于\caption
命令的选项和参数,extra-text
参数允许我们可以在title
的后面,作者姓名的前面,再插入一段额外的文本,这段文本不会出现在清单中。其余参数均和\<name>author
的参数意义一致。
你也可以使用prefix
参数来放置这段额外的文本,而如果你想这样做,你就需要将extra-text
的选项空置(像[]这样),而不是忽略,这样
LaTeX
\LaTeX
LATEX才知道extra-text
选项被跳过了。由于选项的可忽略机制,在有两个相邻的选项的地方只指定一个选项,而将另一个忽略,那么
LaTeX
\LaTeX
LATEX会按顺序指定,即默认指定的是第一个选项。
有两个组可以直接影响姓名和额外文本的布局的命令,一组是\tdartist...
,其中...
可以是justify
,left
,center
或者right
。例如,\tdartistright
使插入的作者名称靠右。另一组\tdartisttext...
,...
与上述意义相同。
我们用一个例子演示:
\documentclass{article}
\usepackage[a5paper,margin=1.5in]{geometry}
\usepackage{graphicx,tocdata}
\tdartistright % 作者姓名靠右
\tdartisttextleft % 额外文本靠左
\begin{document}
\listoffigures
\begin{figure}[htbp]
\centering
\includegraphics[width=60pt]{cat.png}
% 这里在将图片cat.png放置在和.tex文件同一文件夹内
\captionartist{A cat}[This has been already used\\
in the first edition of TLC]{Sebastian}{Rahtz}[ (1955--2016)]
\end{figure}
\end{document}
编译:
如果这些变化还不能满足你,你可以试着重定义\tocdataartistprint
以及\tocdataartisttextprint
,具体操作请查阅宏包手册。
你也可以使用\captionauthor
代替 \captionartist
,它们的使用方法完全相同,不同的仅仅是默认情况下,\captionartist
排版的姓名居中,而\captionauthor
排版的姓名靠右对齐。对于很宽的图片,后者可能更美观一些。
如果你调用了caption
包(它支持\caption*
命令),你就可以使用\captionauthor*
和 \captionartist*
,和不带星号的命令的不同之处是,星号命令不在清单中插入条目,并且图片名称前的标头和编号均会消失(其机制和\section*
等命令类似)。
注意,只有调用了caption
包之后,才可以使用它们。因为它们在底层调用了caption
包支持的\caption*
命令。
我们将上一个例子中的\captionartist
例子加了*
之后,文档就会变成这样: