LaTeX教程(013)-LaTeX文档结构(13)

LaTeX教程(013)- LaTeX \LaTeX LATEX文档结构(13)

接上一篇

一个新的设计案例

首先,我们先建立一个目录文件,并导入到文档中。操作如下:

第一步创建文件test.tex,写入如下代码并编译两次:

\documentclass{book}
\usepackage[a5paper,margin=1in]{geometry}
\usepackage{titletoc}
\begin{document}
\tableofcontents
\chapter{Chapter one}
\section{Section 1.1}
\section{Section 1.2}
\chapter{Chapter two}
\section{Section 2.1}
\section{Section 2.2}
\section{Section 2.3}
\chapter{Chapter three}
\section{Section 3.1}
\section{Section 3.2}
\section{Section 3.3}
\end{document}

两次编译之后,我们就得到一个test.toc文件。进行第二步,打开test.toc文件,并将该文件里面,后两章的代码复制下来,即从\contentsline {chapter}{\numberline {2}Chapter two}{5}{}%开始,直到最后的内容都复制下来。创建一个新的文件,命名为partial.toc文件,将复制的内容放置其中。最后加一行命令\contentsfinish。这里在注意,所有自定义的特殊目录文件,最后最好都放上这个命令。当然,使用它的前提是调用了titletoc包。对标准的目录,\contentsfinish命令是在底层默认调用的。

第三步,创建一个新文件:

\documentclass{book}
\usepackage[a5paper,margin=1in]{geometry}
\usepackage{titletoc}
\begin{document}
\input{partial.toc} % 引入文件
\end{document}

编译:

在这里插入图片描述

这样我们就得到了一个局部的目录。局部命令在编写一部体量较大的书时很实用,这种情形下,我们可以在一个part或者一个chapter后面放置这个部分的目录。并且,.toc文件中的内容(如编号,页码等)是可以手动修改的,只是通常都用不着去动它。通过这种方法,我们也可以看出像\tableofcontents这样的命令在 LaTeX \LaTeX LATEX​的底层是如何工作的。

现在我们可以在上面例子的基础上给条目增加一些样式。我们设置chapter条目为靠左对齐(\filright)的粗体(\bfseries),在条目上方放置一段1 派卡(pica,单位pc)的垂直距离(1pc=12pt)和一条紧随其后的线段(rule)。条目缩进5pc,在这5pc的空间中放置标头。首先将\chaptername,也就是Chapter,改成大写形式,放置一个空格之后,再放置标题编号。对于无编号的标题并没有特别的设置。页码的前面使用\hfill填充(空白),并在chapter条目的下面放置一个2pt的垂直距离,使其与后面的section条目分得更开。

\documentclass{book}
\usepackage[a5paper,margin=1in]{geometry}
\usepackage{titletoc}
\titlecontents{chapter}[6.5pc]%
{\addvspace{1pc}\bfseries\titlerule[2pt]\filright}%
{\contentslabel[{\MakeUppercase{\chaptername}}\ \thecontentslabel]{6.5pc}}%
{}{\hfill\contentspage}[\addvspace{2pt}]
\begin{document}
\input{partial.toc}
\end{document}

编译:

在这里插入图片描述

为了方便对比,我们将partial.toc文件中的chapter标题换成长短不一的文本,然后再将样式进行以下修改: 将chapter的标题设置成无衬线字体,标题文本居中,标题编号靠左,页码靠右,其余空间用基线上的线段填充。section标题缩进1pc,标题编号与标题文本之间用一个短破折号连接,并且没有页码。

\documentclass{book}
\usepackage[a5paper,margin=1in]{geometry}
\usepackage{titletoc}
\titlecontents{chapter}[0pt]%
{\addvspace{6pt}}%
{\large\sffamily\oldstylenums{\thecontentslabel}\ \hrulefill\ }%
{}{\large\sffamily\ \hrulefill\ 
\oldstylenums{\thecontentspage}}[\addvspace{2pt}]

\titlecontents{section} [1pc]{}
{\oldstylenums{\thecontentslabel} -- }{}{}

\begin{document}
\input{partial.toc}
\end{document}

编译:

在这里插入图片描述

最后一个例子中,我们将标题编号取消,将页码放在左边,也就是原本放编号的地方。chapter标题靠右对齐,页码和标题文本之间用\dotfill填充。section标题的页码和标题文本之间用一个短破折号连接。

\documentclass{book}
\usepackage[a5paper,margin=1in]{geometry}
\usepackage{titletoc}
\titlecontents{chapter}[2pc]
{\addvspace{5pt}}%
{\large\bfseries\contentslabel[\hfill\thecontentspage]{2pc}\dotfill}%
{}{}[\addvspace{2pt}]

\titlecontents{section}[2pc]{}
{\contentslabel[\hfill\thecontentspage]{2pc}%
\enspace --\enspace }{}{}

\begin{document}
\input{partial.toc}
\end{document}

编译:

在这里插入图片描述

将条目合并到段落中

标准 LaTeX \LaTeX LATEX只支持将目录条目放置在单独的行中,而有时候将一些低级条目合并到一个段落里是一种更经济的方式,我们使用titletoc包可以做到它。

达到这一目的需要使用\titlecontents命令的变体,即\titlecontents*,根据我们指定选项的个数的不同,它有以下三种形式:

\titlecontents*{type}[left-indent]{before-code}{numbered-entry-format}{numberless-entry-format}{page-format}[mid-code]
\titlecontents*{type}...{page-format}[mid-code][final-code]
\titlecontents*{type}...{page-format}[start-code][mid-code][final-code]

\titlecontents*命令用于将一些条目放置在一个段落中,即,它们会水平地拼接在一起,在达到段落右边距时断行,就像排版段落文本时那样。该命令的前六个参数和\titlecontents的前六个参数相同。

在这六个参数之后,\titlecontents还有最后一个可选参数,below-code,而\titlecontents*的最后的可选参数,分别是start-codemid-codefinal-code。这三个选项的执行规则与普通的选项不同,在最后三个选项中,当我们只指定一个进项时,它会被当作mid-code选项执行,当我们指定两个选项时,它们会按照从左到右的顺序被分别当作mid-codefinal-code,指定三个选项时,它们会按照从左到右的顺序被分别当作start-codemid-codefinal-code。也就是上面展示的三种形式。这三个选项中的命令依情况而有选择地执行(以递归的方式):

  • 如果当前条目是第一个被拼接的条目,那么在排版该条目之前,先执行start-code
  • 如果前面已经有被拼接的条目了,那么:
    • 如果当前条目与前面的条目是同一级别的,那么在当前条目的前面执行mid-code
    • 如果当前条目是更低级别的,那么这意味着这是一个新的层级的第一个条目,因此在该条目的前面执行start-code
    • 如果当前条目是更高级别的,这意味着前面的低级别的若干条目拼接结束了,因此首先执行前面所有的已经结束了的层级的final-code。然后,如果当前条目不再参与拼接,则完成拼接(执行上一个同级条目的final-code)。否则,继续将mid-code插入到该条目的前面。

我们先看一个例子(在这之前,为了使文档更具代表性,你最好修改一下partial.toc文件,将不同的标题文本改成长短不一的文本):

\documentclass{book}
\usepackage[a5paper,margin=1.5in]{geometry}
\usepackage{titletoc}
\usepackage{xcolor} %用来设置颜色的红包
\contentsmargin{0pt}
%回顾一下,这是设置右侧缩进的命令,用来放置页码的,现在不需要页码了,设置为0
\titlecontents*{chapter}[0pt]{\sffamily}{}{}{, \thecontentspage}%
[\ \textbullet \ ] [~\P] % mid, final
% \textbullet生成一个实心圆点 \P是一个特殊符号
\titlecontents*{section}[0pt]{\color{blue}\footnotesize\slshape}{}{}{}%
[ \{] [; ] [\}] % start, mid, final
\begin{document}
\input{partial.toc}
\end{document}

编译:

在这里插入图片描述

如果有几个不同的层级被拼接起来,那么需要将段落的排版信息放在被拼接的最高级条目的设置命令的before-code中,否则你的设置可能不会覆盖整个段落。

如果你觉得前面的描述比较绕,那么我们就从这个例子并始讲解,请仔细观察。

首先是第一个chapter条目,我们说过,第一个被拼接的条目,在排版该条目前执行它所在层级的start-code,由于我们没有指定chapter标题的start-code,所以不执行。其次是第一个section条目,我们前面说,如果当前条目比前一个条目层级更低,就意味着该条目是它所在层级的第一个条目,于是要在该section条目的前面执行section条目的start-code,在这个例子中,section条目的start-code是左大括号{。然后到了第二个section条目。我们前面说过,如果当前条目与前一个条目层级相同,那么在当前条目的前面插入mid-code,这个例子中mid-code是一个分号。第三个section条目依旧是在前面插入一个分号。

到了第二个chapter条目,我们说如果当前条目比前一个条目的层级更高,就意味着前面的更低层级的条目拼接已经完成,我们执行前一个条目所在层级的final-code,也就是右大括号}。然后开始当前条目的拼接,我们前面说,如果当前条目继续参与拼接,那么在当前条目的前面插入mid-codechapter条目的mid-code是一个圆点,我们用\textbullet表示。接着,第二个chapter条目下的section条目,重复上一过程。从第一个开始,直到最后一个section条目拼接完成,其后不再有参与拼接的条目,则执行前面拼接结束了的条目层级的final-codechapterfinal-code是一个特殊符号,我们用\P来生成它,~是一个空格,和普通的空格不同的是,这种方式生成的空格使 LaTeX \LaTeX LATEX不会在此处断页。

仔细观察可以发现,其实条目拼接的基本逻辑就是同层级条目的相互拼接,而低级条目是高级条目的附属。即,无论一个chapter条目下有多少个section条目,不管它们如何拼接,都不影响下一个chapter的拼接方式,因为它本质上是与上一个chapter条目拼接。并且直到所有section标题拼接完成,且不再有新的chapter条目参与拼接,才会执行chapter条目的final-code。而subsection之于section也是如此,层层嵌套。

基于这样的逻辑,我们说在最高级条目的before-code中的排版设置会影响整个段落(如上一个例子中了\sffamily)。而低层级的条目设置不会影响高层级的条目。

在下一个例子中,我们使用圆点来连接section标题,并且在圆点两侧各放置一段弹性距离,我们将它定义为\xquad,最后用一个句点结束。chapter标题将页码放在左边(注意这个例子中,chapter条目不参与拼接),并且所有标题取消编号。我们将页码放到了左边,和上一个例子一样,将右侧缩进设置为0。

\documentclass{book}
\usepackage[a5paper,margin=1in]{geometry}
\usepackage{titletoc}
\contentsmargin{0pt}
\titlecontents{chapter}[0pt]%
{\addvspace{1.4pc}\bfseries}{{\Huge\thecontentspage\quad}}{}{}
\newcommand\xquad{\hspace{1em plus.4em minus.4em}}
\titlecontents*{section}[0pt]{\filright\small}{}{}{,~\thecontentspage}%
[\xquad\textbullet\xquad][.] % mid, final
\begin{document}
\input{partial.toc}
\end{document}

编译:

在这里插入图片描述

生成局部目录

前面讲了如何通过引入一个新的.toc文件来生成一个局部的目录。接下来我们讲一下如何通过titletoc的一些命令在每一章的章标题下面生成本章的次级条目列表,如本章的所有节目录。

首先介绍两个命令,第一个是

\startcontents[name]

这个命令用来收集局部命令的数据,并将它们存储在一个.ptc文件中。第二个命令是

\printcontents[name]{prefix}{start-level}{toc-code}

这个命令用来将收集到的局部命令的数据打印到文档中。我们用一个例子演示一下:

\documentclass{book}
\usepackage[a5paper,margin=1in]{geometry}
\usepackage{titletoc}
\begin{document}
\chapter{This is chapter one}
\startcontents %开始收集
\printcontents{p-}{1}{} %打印该次收集
some test of the current chapter
\section{this is section one}
\section{this is section two}
\subsection{this is subsection one}
\subsection{this is subsection two}
\startcontents %结束上一次收集,并开始下一个收集
\chapter{this is chapter two}
\end{document}

编译(截取部分):

在这里插入图片描述

可以看到,我们在第一章的标题下面放置了一个局部目录,它正是我们用命令\startcontents收集,并且用\printcontents打印出来的。一个文档中可以有很多个\startcontents命令(实际上,如果使用了这个命令,很少有只用一个的情况),第一个局部目录的数据从第一个\startcontents开始,到第二个\startcontents结束,第二个局部目录的数据从第二个\startcontents开始,到第三个\startcontents结束,以此类推,\startcontents结束一个局部目录的收集,同时也会发起下一个收集。如果我们要打印第一个局部目录,就在第一个\startcontents和第二个\startcontents之间使用\printcontents命令, LaTeX \LaTeX LATEX就会根据\printcontents的位置将这个局部目录放置在文档中,以此类推,第n个\printcontents要放置在第n个\startcontents与第n+1个\startcontents之间。

局部目录的收集是可以重叠的(大多数时候是嵌套),例如,你可能会想在part标题的下方放置该part的所有本章、节与子节的目录列表,同时也想在chapter标题下放置该章所有的节和子节标题,那么必然有一些目录是重复的,那么,如何收集重复的目录数据呢?例如,我们在文档中放置4个\startcontents:

\startcontents % A
...
\startcontents % B
...
\startcontents % C
...
\startcontents % D

我们如何让 LaTeX \LaTeX LATEX知道,我们想收集从A到D的目录,和从B到C的目录呢?因为按照上述原理, LaTeX \LaTeX LATEX会收集A-B、B-C以及C-D这三个区域的局部目录标题。这个时候就要用到选项name了。name是一个自定义的自符串,用来将相应的\startcontents匹配起来,并且在使用\printcontents时使用指定name选项,能够让 LaTeX \LaTeX LATEX知道我们要打印哪一部分的局部目录。若要实现上述想法,只需要:

\startcontents[part] % A
\printcontents[part]{p-}{0}{}
...
\startcontents[chapter] % B
\printcontents[chapter]{p-}{1}{}
...
\startcontents[chapter] % C
...
\startcontents[part] % D

这样,我们就可以A-D中间的局部目录在\printcontents[part]{p-}{0}{}处打印出来,将B-C中间的局部目录在\printcontents[chapter]{p-}{1}{}处打印出来。name可以是任意字符串,但是通常用有意义的名字,以便于我们能够轻易识别它们的意义。如果不指定name,则默认namedefault\startcontents开始收集一个局部目录的数据,直到下一个相同name\startcontents停止,同时开始收集下一个局部目录的数据,以此类推。这些目录的收集将同时进行,最后所有局部目录的数据都被放入一个.ptc文件中。该文件在\startcontents命令执行后自动生成。

现在我们暂且不管prefix的作用,这里讲一下start-level参数。它表示被打印出来的当前局部目录的开始层级。在前面的例子中,如果我们将第7行的\printcontents{p-}{1}{}中的参数1改为2,那么此处的局部目录就会从subsection(2级标题)开始打印:

在这里插入图片描述

我们可以设置开始层级,那么如何设置结束层级呢?即,如何告诉 LaTeX \LaTeX LATEX该局部目录显示的最底层级呢?我们可以在toc-code中设置tocdepth,回忆一下,这是一个影响目录显示深度的计数器。其他的初始化操作也都可以放在toc-code中,比如我们前面将目录条目的右侧缩进设置为0,这是因为局部目录是作为一个单独段落排版的,不需要右侧缩进。

难道我们每生成一个局部目录,就要手动输入一次收集与打印命令吗?当然不用,回忆一下我们讲过的titlesec包(从007篇开始),该包有一个用来定制标题样式的命令:

\titleformat{cmd}[shape]{format}{label}{sep}{before-code}[after-code]

我们可以将\startcontents\printcontents放在after-code中,这样,被定制样式的标题每生成一个,就会自动执行这两个命令,也就会自动收集该标题下的局部目录的信息,并将它们打印出来:

\documentclass{book}
\usepackage[a5paper,margin=1in]{geometry}
\usepackage{titlesec,titletoc}
\begin{document}
\titleformat{\section}{\normalfont}%
{\large\bfseries\thesection\enspace}{0.5em}{\large\bfseries}%
[\vspace*{5pt}\startcontents\printcontents{p-}{2}{\contentsmargin{0pt}}]

\titlespacing*{\section}{0pc}{*4}{*2.3}[1pc]

\chapter{This is chapter one}
\section{this is section one}
\section{this is section two}
\subsection{this is subsection one}
\subsection{this is subsection two}
\section{this is section three}
\subsection{this is subsection three}
\end{document}

编译:

在这里插入图片描述

如果我们想为局部目录的条目单独设置样式,使其与主目录的样式不同,应该如何做呢?我们上一讲中讲过设置条目样式的命令\titlecontents,其后的第一个命令就是划分命令的标题,如\titlecontents{subsection}...,那么如何区分主目录的subsection和局部目录的subsection呢?这就要讲到\printcontents命令的prefix参数了,它用来给局部目录中的条目类型增加一个前缀,用来将它与主目录区分开来,例如我们将其设置为-p,那么局部目录中的条目类型前面就会多出一个-p,如p-subsection

另外再讲两个命令,分别是

\stopcontens[name]
\subsection{test}
\resumecontents[name]

\stopcontens[name]用来中断一个局部目录的收集,\resumecontents[name]用来继续一个局部目录的收集。\resumecontents[name]startcontents[name]的功能不同,后者会开始一个新的局部目录,而前者会继续旧的局部目录。前面展示的情况中,名为name的局部目录的收集会在\subsection{test}之前停止,然后在其后继续,即会跳过\subsection{test}。我们用一个例子演示一下(连同局部目录的条目样式设置):

\documentclass{article}
\usepackage[a5paper,margin=1in]{geometry}
\usepackage{titlesec,titletoc}
\titleformat{\section}[frame]{\normalfont}{\footnotesize \enspace SECTION \thesection\enspace}%
{6pt}{\large\bfseries\filcenter}%
[\vspace*{5pt}\startcontents\printcontents{p-}{2}{\contentsmargin{0pt}}]

\titlespacing*{\section}{1pc}{*4}{*2.3}[1pc]%
\titlecontents*{p-subsection}[0pt]%
{\small\itshape\fillast}{}{}{}[ --- ][.]

\begin{document}
\section{A Title Test}
Some text to prove that this paragraph is not indented.
\subsection{A first} Some text \ldots \newpage
\subsection{A longer second} Some more text.
\stopcontents \subsection{A third} \resumecontents
\subsection{An even longer fourth}
\end{document}

编译(只截取一部分):

在这里插入图片描述

注意,上面的两个例子,经过笔者本人反复测试,一旦指定了name选项,就会报错。当前使用的 LaTeX \LaTeX LATEX版本是TeXLive2024。读者也可自行测试,如果发现问题的原因,请留言。

还有一些类似的用来生成局部的表格清单和图形清单的命令,如\startlist\printlist\stoplist\resumelist等。语法上有一些细微的差别,它们很少用到,我们这里不再细讲,如果需要,讲查阅titletoc包文档。

关注【年轻人 你渴望力量么】

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值