我正在处理一个大型 LaTeX 文档(超过 1000 页)。我使用得\include
非常多,并且有 47 个.tex
文件在运行。运行结束时,我得到了以下诊断信息:
(\end occurred when \iftrue on line 366 was incomplete)
(\end occurred when \ifnum on line 366 was incomplete)
我使用的 TeX 版本声明如下:
This is pdfTeX, Version 3.14159265-2.6-1.40.15 (TeX Live 2015/dev/Debian) (preloaded format=latex 2015.5.11) 29 DEC 2015 17:28
我的问题:我如何找到有问题的命令? 我使用 Awk 打印了.tex
目录中每个文件的第 366 行,但这些文件似乎都没有任何条件。我也查看了这些.aux
文件。本地.sty
文件不起作用,因为它们都不是 366 行。
我应该在哪里查找?我应该寻找什么?有没有办法让 TeX 吐出有问题的文件的名称而不仅仅是行号?也许是一些 luatex 诡计?
(我不知道如何提供一个最小的例子。如果我能提供的话,我可能就能解决这个问题。)
答案1
如果你看看
\tracingifs=2
\ifnum9=9
\stop
使用\tracingifs
设置后日志会显示更多信息:
(./file.tex
LaTeX2e <2016/01/01>
Babel <3.9m> and hyphenation patterns for 79 languages loaded.
{vertical mode: \ifnum: (level 1) entered on line 4}
{\ifvmode: (level 2) entered on line 6}
{\ifnum: (level 3) entered on line 6}
{\fi: \ifnum (level 3) entered on line 6}
{\fi: \ifvmode (level 2) entered on line 6}
{\iftrue: (level 2) entered on line 6}
{\ifx: (level 3) entered on line 6}
{\fi: \ifx (level 3) entered on line 6}
{\fi: \iftrue (level 2) entered on line 6}
{\iffalse: (level 2) entered on line 6}
{\fi: \iffalse (level 2) entered on line 6}
{\iffalse: (level 2) entered on line 6}
{\fi: \iffalse (level 2) entered on line 6}
{internal vertical mode: \ifnum: (level 2) entered on line 6}
{\ifnum: (level 3) entered on line 6}
{\ifvoid: (level 4) entered on line 6}
{\ifvbox: (level 5) entered on line 6}
{\fi: \ifvbox (level 5) entered on line 6}
{\ifx: (level 5) entered on line 6}
{\else: \ifx (level 5) entered on line 6}
{\fi: \ifx (level 5) entered on line 6}
{\ifx: (level 5) entered on line 6}
{\else: \ifx (level 5) entered on line 6}
{\fi: \ifx (level 5) entered on line 6}
{\iffalse: (level 5) entered on line 6}
{\fi: \iffalse (level 5) entered on line 6}
{\iffalse: (level 5) entered on line 6}
{\fi: \iffalse (level 5) entered on line 6}
{\ifx: (level 5) entered on line 6}
{\else: \ifx (level 5) entered on line 6}
{\fi: \ifx (level 5) entered on line 6}
{\else: \ifvoid (level 4) entered on line 6}
{\fi: \ifvoid (level 4) entered on line 6}
{\else: \ifnum (level 3) entered on line 6}
{\fi: \ifnum (level 3) entered on line 6}
{\else: \ifnum (level 2) entered on line 6}
{\fi: \ifnum (level 2) entered on line 6}
{\ifnum: (level 2) entered on line 6}
{\ifdim: (level 3) entered on line 6}
{\else: \ifdim (level 3) entered on line 6}
{\fi: \ifdim (level 3) entered on line 6}
{\else: \ifnum (level 2) entered on line 6}
{\fi: \ifnum (level 2) entered on line 6}
{\ifnum: (level 2) entered on line 6}
{\ifnum: (level 3) entered on line 6}
{\else: \ifnum (level 3) entered on line 6}
{\ifnum: (level 4) entered on line 6}
{\ifnum: (level 5) entered on line 6}
{\fi: \ifnum (level 5) entered on line 6}
{\else: \ifnum (level 4) entered on line 6}
{\fi: \ifnum (level 4) entered on line 6}
{\fi: \ifnum (level 3) entered on line 6}
{\else: \ifnum (level 2) entered on line 6}
{\fi: \ifnum (level 2) entered on line 6}
{\ifnum: (level 2) entered on line 6}
{\else: \ifnum (level 2) entered on line 6}
{\fi: \ifnum (level 2) entered on line 6}
)
(\end occurred when \ifnum on line 4 was incomplete)
所以你可以看到,在这种情况下,这是一个无与伦比的(level 1)
\ifnum
从线开始向上工作
{vertical mode: \ifnum: (level 1) entered on line 4}
您会看到第一个(
节目(./file.tex
,因此第 4 行file.tex
出现了令人反感的 if。
答案2
尝试在主文件之前输入的文件之一中搜索最终的 \end{documentation} ...
答案3
对于大型日志文件的一些提示:
因为它真的很难寻找
(file
,)
在这种情况下,您可以使用一些 LaTeX 钩子在文件更改时记录一些消息:\ExplSyntaxOn \seq_new:N \__file_list \seq_put_right:Nn \__file_list {\msg_expandable_error:nn{}{this~cannot~happen!}} \seq_put_right:Nn \__file_list {<main~file>} \AddToHook{file/before}{ \seq_put_right:NV \__file_list \CurrentFile \wlog {enter~file\use_none:n{}::\CurrentFile} } \AddToHook{file/after}{ \seq_pop_right:NN \__file_list \__last_file \seq_get_right:NN \__file_list \__last_file \wlog {return~to~file\use_none:n{}::\__last_file} } \ExplSyntaxOff
(显然效果是,您会在日志中得到一行
enter file::X
和return to file::X
。搜索file::
。\use_none:n {}
是为了防止在启用宏日志记录时在进行宏扩展时找到消息。)“二进制搜索”的替代方法是向某些 TeX 文件中插入(带注释的)空行,然后查看行号是否增加。(这是“蛮力”,但大多数情况下都有效,除非 catcode 很奇怪。)
请注意,即使某个特定因素
\if
被报告为罪魁祸首,它也不一定是原因。例如\if ... % A \if ... % B (accidentally inserted) \fi % C
显然
B
,这里的错误A
是 TeX 报告的,尽管如此,它还是不完整的。并且A
可能深埋在某些库代码中(例如,如果\if
某个文件中存在不完整代码.sty
,则可能会发生这种情况)if.* <line number>}
一般来说,从文件末尾搜索 (regex) 很有用,因为您可以观察到,如果有多个这样的\if
,则最后一个可能有问题;尽管如此,如果第一个匹配项是,\fi
则跳过一个\if
。示例日志
{\if entered on line X} {\else: \if entered on line X} {\fi: \if entered on line X} {\if entered on line X} {\else: \if entered on line X} {\fi: \if entered on line X} {\if entered on line X} {\else: \if entered on line X} {\fi: \if entered on line X} {\if entered on line X} {\if entered on line X} {\else: \if entered on line X} {\fi: \if entered on line X}
在这个例子中,可以看出,如果从末尾向后搜索日志行,您将首先看到一个
\fi
,然后跳过一个\if
,然后立即找到有问题的命令。(这可以(level X)
部分帮助搜索匹配的行,但仅此而已。)