简短回答

简短回答

我想在目录中添加线段分隔符,并发现以下方法有效:

\documentclass[12pt]{book}
\usepackage{tocloft}

\begin{document}
\thispagestyle{empty}

\addtocontents{toc}{{\textbf{------------------}}}
%\addtocontents{toc}{\rule{1.5in}{.02mm}}
\tableofcontents
\end{document}

输出结果如下:

在此处输入图片描述

不过,我想让分隔符更厚;我想我可以尝试这个:

\addtocontents{toc}{\rule{1.5in}{.02mm}}

但遗憾的是,它不起作用(导致出现大量错误行)。

问题:如何调整目录中线段分隔符的粗细(和长度)?这似乎应该是一项简单的任务,但我一直不知道该怎么做。

答案1

简短回答

使用\protect\rule而不是\rule,或者更新你的 TeX 发行版。

长答案

\addtocontents使用 TeX 的\write原语将 LaTeX 代码写入 .toc 文件,并\write在页面发送出去时递归扩展标记(\write导致那是什么节点添加到 TeX 正在组装的当前列表中,因此最终,此节点位于明确定义的页面上)。这是必要的,以便\thepage扩展到正确的页码,尽管 TeX 在段落被组装之前不知道给定字符/框/什么/等的位置。完整阅读(这是因为它优化了所有换行符的集合在每个段落中)。

因此,此\write操作会导致宏被展开,但有些宏是稍后在读取 .toc 文件排版目录时展开的,而不是在编写目录时展开的。测试通常就是这种情况。

在您的示例中,\rule使用\@ifnextchar来测试 是否存在[,即确定是否提供了可选参数(指定应提高规则的量)。这是如何工作的?

经过一些简化(因为\@ifnextchar在寻找下一个非空间标记时会跳过空间标记),\@ifnextchar使用\futurelet设置\@let@token为输入流中的下一个标记并插入一些宏来测试是否\@let@token等同\ifx[。这就是早期扩展\write使其惨遭失败的地方:\futurelet当 TeX 仅扩展标记时(\write递归扩展其参数时就是这种情况),原语无法完成其工作。\futurelet不可扩张;其展开式为\futurelet。因此,当\write展开其参数时,\futurelet不会分配\@let@token,但是以下测试看是否\@let@token等同\ifx[本质上可扩展。因此,它会被展开(根据当前的含义丢弃真或假分支\@let@token,无论它是什么),结果(在所有可扩展的内容都已展开之后)将写入 .toc 文件。如果没有进一步的错误阻止执行\write,则意味着将做出选择并将结果刻在石头上(.toc 文件),但不会以正确的方式做出此选择。

如果采用了“错误的”代码分支,例如如果剩余分支对应于可选参数的存在而实际上没有参数,则此分支中的宏在\write扩展它们时很可能会在早期导致错误:例如,可能有一个宏采用以 分隔的参数[,如果在预期的位置没有 ,则会导致错误[(它可能会抓取文档的大部分内容,然后找到合适的[,从而导致以后出现进一步的错误,或者在到达文件末尾之前找不到任何参数)。

这可能是第一次运行 LaTeX 时出错的原因。在后续运行中,当读取 .toc 文件时,也可能出现错误,因为其中写入的代码\write扩展得太早了。

为了避免此类问题,有几种技术。首先,请注意\addtocontents不直接使用\write,而是使用名为 的包装宏\protected@write。默认情况下,此包装宏会立即扩展所有可扩展标记,但 除外\thepage;此外, 之前的标记\protect根本不会通过 进行扩展\protected@write\protect\whatever写为\protect \whatever)。

考虑到这一点,以下是用于防止您遇到的问题的典型技术:

  • \rule可以制作宏强壮的。这是一种特殊类型的定义,由 完成\DeclareRobustCommand,它\protect在后台使用,以便“真实”代码仅在排版期间传递,而不是在\protect-aware 扩展上下文中传递,例如在\protected@write\protected@edef& Co 内。这是最近版本的 LaTeX 内核所具有的(一个强大的\rule宏);在这种情况下,处于您这种情况的用户不会遇到任何问题。

  • \rule(或任何导致问题的脆弱命令) 不够强大时,这显然是您的情况,您可以在其前面加上\protect,即:使用\protect\rule而不是。这可以防止被使用\rule的 扩展,因此在此阶段甚至看不到问题。读取 .toc 文件时,的实际代码会扩展(然后- 等于,通常等于)。\rule\protected@write\addtocontents\@ifnextchar\rule\protect\let\@typeset@protect\let\relax

  • 另一种主要可能性是使用类似(或等) 的东西将其定义\rule为宏。在这种情况下,甚至不会扩展它 — — 该机制是不需要的。但原语不是 Knuth TeX 的一部分;它是在 e-TeX 中添加的。我认为 LaTeX 团队在此期间开发了 + 技术,或者可能是后来开发的,但他们仍然希望 LaTeX 可以与当时的 Knuth TeX 一起使用;因此,+技术保留了下来,并且仍然在 LaTeX 内核中广泛使用,尽管据我所知,当前的 LaTeX 需要 e-TeX 扩展。\protected\protected\def\rule...\NewDocumentCommand\write\protected@write\protected\DeclareRobustCommand\protect\DeclareRobustCommand\protect

注意:据我所知,所有正在积极开发中的 TeX 引擎都具有\protected原语;我相信它们实现了大多数(如果不是全部) e-TeX 的扩展。

相关内容