我有一个文档使用了breqn
、thm-restate
( thmtools
) 和cleveref
。我无法让它编译。
这是一个简单的例子:
\documentclass{article}
\usepackage{thm-restate}
\usepackage{breqn}
\usepackage{cleveref}
\begin{document}
\begin{restatable}{theorem}{foo}
Test
\end{restatable}
\end{document}
pdflatex 的输出包含许多类似这样的错误:
! Extra \else.
<argument> \else
l.11 \end{restatable}
! Extra \else.
\cref@ifstreq ... \@firstoftwo \else \let \@tempc
\@secondoftwo \fi \expanda...
l.11 \end{restatable}
! Extra \else.
\cref@ifstreq ...i \expandafter \endgroup \@tempc
{#3}{#4}
我已尝试了多个(我想是全部)命令来加载包裹。
我的感觉是,这可以通过改变定义来解决这个问题,\cref@ifstreq
但这超出了我目前的 LaTeX 技能。
有解决方法吗?我应该报告错误吗?(在哪个软件包中?)
我使用 TeX Live 2019,它有breqn
0.98g、thm-restate
/ thmtools
67 和cleveref
0.21.4。这些都是 CTAN 的最新软件包,除了thmtools
,我尝试将其更新到 68,但这也没有帮助。
答案1
哇,这是一个很好的发现(如果你可以这么称呼它的话)。。。
顺序并不重要,但是所有三个包都发挥了作用(尽管cleveref
是无辜的)。
首先,breqn
重新定义 LaTeX\@ifstar
来\@temp(a|b|c)
代替\reserved@(a|b|c)
(见这里关于这些),所以当你定义一个宏时\def\test{\@ifstar{A}{B}}
,然后使用\test\else
,\@tempc
最终会变得与相同\else
(这是很危险的)。
thmtools
的代码\begin{restatable}{theorem}{foo}
最终会变成\expandafter\foo\ifprint\else*\fi
,然后\expandafter
扩展\ifprint
(名称实际上是\ifthmt@thisistheone
),在您的情况下,这是正确的,因为您使用了\begin{restatable}
,而不是\begin{restatable*}
。完成后,\expandafter
您只剩下\foo\else*\fi
(是的,这很糟糕:-)。
现在猜猜第一件事是什么\foo
?
是的!\@ifstar
,现在\@tempc
是\else
。
cleveref
只是不幸\@tempc
在\cref@ifstreq
这里使用:
\ifx\@tempa\@tempb%
\let\@tempc\@firstoftwo%
\else%
\let\@tempc\@secondoftwo%
\fi%
这很好,直到\@tempc
与相同\else
。\ifx
测试为假,因此您有:
\iffalse
\@tempc % \else
\@firstoftwo%
\else%
\let\@tempc\@secondoftwo%
\fi%
你也可以看到这是怎么回事……
这是一个修复 的补丁thm-restate
。该补丁改变了这种\expandafter\foo\ifprint\else*\fi
情况,以确保整个块在有机会查看它\if...\fi
之前完全展开。\foo
\@ifstar
\usepackage{xpatch} % Needs to be loaded before breqn
\makeatletter % The patch needs to appear after thm-restate is loaded
\xpatchcmd\thmt@restatable % fixing thm-restatable
{\csname #3\@xa\endcsname\ifthmt@thisistheone\else*\fi}
{\begingroup\edef\x{\endgroup
\expandafter\noexpand\csname #3\endcsname
\ifthmt@thisistheone\else*\fi}\x
}{}{\FailedToPatch}
\makeatother
完整文档:
\documentclass{article}
\usepackage{xpatch} % Needs to be loaded before breqn
\usepackage{thm-restate}
\usepackage{breqn}
\usepackage{cleveref}
\makeatletter % The patch needs to appear after thm-restate is loaded
\xpatchcmd\thmt@restatable % fixing thm-restatable
{\csname #3\@xa\endcsname\ifthmt@thisistheone\else*\fi}
{\begingroup\edef\x{\endgroup
\expandafter\noexpand\csname #3\endcsname
\ifthmt@thisistheone\else*\fi}\x
}{}{\FailedToPatch}
\makeatother
\begin{document}
\begin{restatable}{theorem}{foo}
Test
\end{restatable}
\end{document}