.aux
这可能是一个奇怪的问题,但是当我将文档拆分为多个文件时,我在主文件上写入信息时遇到了麻烦.tex
。
情况是这样的:我试图计算最宽的目录标签的大小,以便我可以根据这个测量值对齐目录中的所有章节/部分名称。有人已经告诉我如何进行测量,但我需要将此信息写入文件中,.aux
以便在第一次传递时计算尺寸,并在第二次传递时使用它。
令我感到困扰的是,我使用的命令不起作用,我相信原因在于文档的模块化,因为当我在单文件文档中尝试它时,它可以正常工作。
以下是应该写入信息的代码部分:
\AtEndDocument{
\protected@write\@auxout{}%
{\string\global\string\setlength{\string\widesttoclabel}{\the\widesttoclabel}}
}
作为\widesttoclabel
保存我计算的长度的宏。
但是当我检查.aux
文件时,该条目并不在任何地方,既不在“主文档”的辅助文件中,也不在其他文件中。
我是否遗漏了什么?
光子发射站:我知道我可以解决这个问题,将 s 替换\include
为\input
s,但这会很糟糕,因为我的文档有很多页......所以如果可以选择的话,这不应该是一个选项。
答案1
当 LaTeX 执行时\end{document}
,
- 它调用钩子来收集东西
\AtEndDocument
, - `\clearpage 被调用并且
- 主
.aux
文件已关闭。
您使用的\protected@write
是延迟写入。它会在输出页面时执行(实际写入)的输出中放置一个写入节点。但是,如果在文档末尾已经输出了最新页面,则不会发生任何事情,因为如果页面仅包含写入节点,TeX 不会创建页面。因此您需要\immediate\write
。
文档结尾钩子的顺序就是调用的顺序。因此,如果通过 添加标题较长的部分,则\AtEndDocument
写入文件可能会太早。软件包提供了钩子命令,该命令在钩子之后 (1.) 和文件关闭之前(3.) 调用。.aux
\AtEndDocument
atveryend
\AfterLastShipout
\AtEndDocument
\clearpage
.aux
因此代码示例变为:
\usepackage{atveryend}
\newdimen\widesttoclabel
\setlength{\widesttoclabel}{0pt}
\makeatletter
\AtBeginDocument{%
\xdef\thewidesttoclabel{\the\widesttoclabel}%
}%
\AfterLastShipout{%
\if@filesw
\immediate\write\@mainaux{%
\global\string\widesttoclabel=\the\widesttoclabel\relax
}%
\fi
}
\makeatother
% ...
\begin{document}
% Macro \thewidesttoclabel contains the width of the widest toc label
% from the previous run. Dimen register \widesttoclabel is initially 0pt
% and should be updated for each longer entry found during the document.
\end{document}
进一步说明:
\global\setlength
是不正确的,因为它依赖于宏的实现\setlength
。文档不保证\global
可以使用来获取全局分配。相反,包calc
重新定义\setlength
。然后前缀\global
失败。正确的变体:\setlength{\mylength}{...}% \global\mylength=\mylength
或者如果在这种情况下没有任何计算,那么我们可以使用
\global\widesttoclabel=\the\widesttoclabel\relax
LaTeX 提供了
\nofiles
禁用对辅助文件的写入。\protected@write
相应地重新定义。 并且它设置了\if@filesw
可以询问辅助文件是否可写的开关。 由于解决方案\immediate\write
直接使用,因此将写入放在和之间\if@filesw
以\fi
尊重\nofiles
。
变体
以下是使用全局宏定义\xdef
而不是.aux
文件中的全局赋值的变体:
\documentclass{article}
\usepackage{atveryend}
% Dimen register \widesttoclabel is used for measuring and
% finding the maximal value that is written to the `.aux` file
% at the end of document.
\newdimen\widesttoclabel
\setlength{\widesttoclabel}{0pt}
% \thewidesttoclabel is a macro with the width of the
% widest toc label. It is defined in the `.aux` file.
% In the first run, the dummy value 0pt is used.
\AtBeginDocument{%
\providecommand*{\thewidesttoclabel}{0pt}%
}
\makeatletter
% \set@widesttoclabel is used at the end of the main .aux file
\newcommand*{\set@widesttoclabel}[1]{%
\xdef\thewidesttoclabel{#1}%
}
\AfterLastShipout{%
\if@filesw
\immediate\write\@mainaux{%
\xdef\string\thewidesttoclabel{\the\widesttoclabel}%
}%
\fi
}
\begin{document}
Widest entry: \thewidesttoclabel
\settowidth{\widesttoclabel}{Hello World}% dummy
\end{document}