考虑如下的两份近乎等价的MWE:
\documentclass[fontset=fandol]{ctexbook}
\begin{filecontents*}[overwrite]{thesis.bib}
@book{revuz,
title = {Continuous Martingales and Brownian motion},
author = {Revuz, Daniel and Yor, Marc},
year = {1999},
publisher = {Springer},
location = {Berlin}
}
\end{filecontents*}
\usepackage{amsmath}
\let\proofname\relax
\usepackage[amsmath,thmmarks,amsthm,hyperref,thref]{ntheorem}
\usepackage{biblatex}
\addbibresource{thesis.bib}
\newtheorem{theorem}{定理}[section]
\begin{document}
\chapter{intro}
\begin{theorem}[ \parencite{revuz} Theorem 4]\label{thm1}
This is a theorem environment, used to state a theorem.
\end{theorem}
\begin{proof}
This is a proof of\thref{thm1}.
\end{proof}
\end{document}
一切正常。
然而如果把正文纳入\include中:
\documentclass[fontset=fandol]{ctexbook}
\begin{filecontents*}[overwrite]{thesis.bib}
@book{revuz,
title = {Continuous Martingales and Brownian motion},
author = {Revuz, Daniel and Yor, Marc},
year = {1999},
publisher = {Springer},
location = {Berlin}
}
\end{filecontents*}
\begin{filecontents*}[overwrite]{test.tex}
\chapter{intro}
\begin{theorem}[ \parencite{revuz} Theorem 4]\label{thm1}
This is a theorem environment, used to state a theorem.
\end{theorem}
\begin{proof}
This is a proof of\thref{thm1}.
\end{proof}
\end{filecontents*}
\usepackage{amsmath}
\let\proofname\relax
\usepackage[amsmath,thmmarks,amsthm,hyperref,thref]{ntheorem}
\usepackage{biblatex}
\addbibresource{thesis.bib}
\newtheorem{theorem}{定理}[section]
\begin{document}
\include{test.tex}
\end{document}这将会导致:
! Extra \else.
\@include ...ediate \closeout \@partaux \fi \else
\deadcycles \z@ \@nameuse ...
l.29 \include{test.tex}
? ! Extra else.
@include ... fi else ...
l.194 include{chapter1}真正必要的最小触发链是:
usepackage[amsmath,thmmarks,amsthm,hyperref,thref]{ntheorem}
...
begin{theorem}[parencite{revuz} Theorem 4]label{thm1}
...
end{theorem}thref{thm1}
也就是:
- ntheorem 开启 hyperref,thref
- 定理标题写入 .thm
- 定理标题含 parencite
- 后面调用 thref
不用 include 时,你已经能看到核心症状:
Package hyperref Warning: Suppressing link with empty target
(end occurred when ifx ... was incomplete)用了 include 后,同一个内部条件未闭合问题会在 include 收尾宏里爆成 Extra else。所以如果你要构造“机制 MWE”,可以不用 include;如
果你要复现和原工程完全一致的报错文本,就需要 include。
该问题源自某份(有一定年份,但不多)的模板,这里仅作背景补充用,贴上部分导言区:
\documentclass[UTF8,a4paper,twoside,zihao=-4,AutoFakeBold=2,reqno]{ctexbook}
\usepackage{mathrsfs}
\usepackage{amsmath, amssymb, amscd}%amsthm, %\usepackage{amsthm}
\usepackage{latexsym}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage[usenames,dvipsnames]{xcolor}%\usepackage[a-1b]{pdfx}
\usepackage{amsfonts}
\usepackage{bookmark}
\usepackage{hyperref}
\definecolor{tianyi}{HTML}{1A237E}
\definecolor{secondary}{HTML}{1B5E20}
\let\proofname\relax
\usepackage[amsmath,thmmarks,amsthm,hyperref,thref]{ntheorem}
\usepackage[backend=biber,bibstyle=gb7714-2015,citestyle=gb7714-2015,gblocal=gb7714-2015,gbalign=gb7714-2015,block=space,url=false,doi=false,gbfieldtype = true,backref=true]{biblatex}
\addbibresource[location=local]{thesis.bib}
\usepackage{graphicx}
\usepackage{caption}
\usepackage{subfigure}
\usepackage{float}
\usepackage{tikz}
\usepackage{dsfont}
\usepackage{lipsum}
\usepackage{zhlipsum}
\usepackage[subfigure]{tocloft}
\renewcommand{\cftchapleader}{\cftdotfill{\cftdotsep}}
\renewcommand\contentsname{\zihao{3}\heiti \hspace*{\fill}目\quad 录\hspace*{\fill}}
\usepackage{fancyhdr}
\usepackage{setspace}
\usepackage{bbm}
\ctexset{
chapter={
format={\heiti\zihao{3}\centering\bfseries},%章标题格式
number={\arabic{chapter}},
afterskip={15.05625pt},
beforeskip={-30pt},%这里设置的是章标题与上页边距的距离. 默认时是比较大的. 记得自己设置
},
section={
format={\heiti\zihao{-3}\centering\bfseries},% 节标题格式
afterskip={15.05625pt},
beforeskip={7pt},
},
subsection={
format={\heiti\zihao{4}\indent},%小节标题格式
beforeskip={7pt},
afterskip={15.05625pt},
},
}
\newcommand{\nomenclatureitem}[3][ ]{%
\noindent\makebox[0.15\textwidth][l]{#2}{{#3}\hfill{#1}}\par
}
\newcommand{\Unit}[1]{\,\mathrm{#1}}
\newcommand{\norm}[1]{\left\Vert #1\right\Vert}
\newcommand{\abs}[1]{\left\vert #1\right\vert}
\newcommand{\cRed}[1]{\textcolor{red}{#1}}
%%%%%%%%%%%%%%%%%下面两个命令主要是用来盲审屏蔽作者信息的, 有需求的可以使用
\newcommand{\censor}[1]{#1}
\newcommand{\starcensor}[1]{#1}
\allowdisplaybreaks
\makeatletter
\renewtheoremstyle{plain}%
{\item[\hskip\labelsep \theorem@headerfont ##1\ ##2\theorem@separator]}%
{\item[\hskip\labelsep \theorem@headerfont ##1\ ##2\ \normalfont({##3})\theorem@separator]}
\makeatother
\theoremstyle{plain}
\theorembodyfont{\itshape}
\theoremheaderfont{\normalfont\bfseries}
\theoremseparator{\textbf{.}}
\newtheorem{theorem}{定理}[section]
\newtheorem{corollary}[theorem]{推论}
\newtheorem{proposition}[theorem]{命题}
\newtheorem{lemma}[theorem]{引理}
\newtheorem{nature}[theorem]{性质}
\newtheorem{remark}[theorem]{注记}
%\theoremstyle{definition}
\newtheorem{definition}[theorem]{定义}
\newtheorem*{remarkn}{注记}
\newtheorem{example}[theorem]{示例}
\newtheorem{Assumption}[theorem]{假定}
\newtheorem{hypothesis}[theorem]{假设}
\renewcommand{\proofname}{\indent 证明}
\renewcommand\thesection{\thechapter{}.\arabic{section}}
\renewcommand\thetable{\thechapter{}.\arabic{table}}
\renewcommand\thefigure{\thechapter{}.\arabic{figure}}
\newcommand{\headingstobeshown}{}
\newcommand{\set}[1]{\{#1\}}
\newcommand*{\dif}{\mathop{}\!\mathrm{d}}
\newcommand{\RomanNum}[1]{\uppercase\expandafter{\romannumeral #1\relax}}
\newcommand{\etal}{\text{et al.\ }}
不用 \include 编译,你可以在 log 最后几行看到这样的内容:
(\end occurred when \ifx on line 42 was incomplete)
Output written on main.pdf (1 page).用了 \include 只是将这个问题过早地暴露出来而已。
实际是 ntheorem 的 hyperref,thref 这两个选项导致的问题。ntheorem 并不会自动加载 hyperref(即使启用 hyperref 选项也是如此)。需要自己在 ntheorem 之后加载 hyperref。
\usepackage[amsmath,thmmarks,amsthm,hyperref,thref]{ntheorem}
\usepackage{hyperref}这样应该就能正常编译了。
ntheorem 最近更新已经是15年前。这期间 LaTeX 里涉及到引用的相关代码已经发生了很大改变,主要是 LaTeX 内核里 \newlabel 内部的参数由原来的 2 个变成了 5 个,保证了与 hyperref 一致。ntheorem 却没有,如果只使用 hyperref 选项而不加载 hyperref 宏包,它写入的 label 是用的 2 个参数,但却是按 5 个参数来用的,参数不足,TeX 只能吞掉后面的 tokens 了。
现在如果硬要用 ntheorem,还要正确的交叉引用,最好是不用它自己的实现,而用 zref-clever 宏包:
\usepackage[amsmath,thmmarks,amsthm]{ntheorem}
\usepackage{hyperref}
\usepackage{biblatex}
\addbibresource{thesis.bib}
\newtheorem{theorem}{定理}[section]
\usepackage{zref-clever}
\let\thref\zcref
\zcsetup{noname}
\zcRefTypeSetup{theorem}{refbounds={,定理,,}}编译结果应该是一致的。这在 TeXLive 2023 以及之后应该都是能正确编译的。更早一点的版本,就要使用 cleveref 宏包,不过,它最近更新也是 8 年前了,与现在的 LaTeX 内核也有不兼容的地方。
Ops,看起来我的MWE还没有去掉biblatex的依赖(bushi)
这个问题的出现很大程度上是由于该模板是流传很多代的,在当时还不存在
thmtools/keytheorems以及zref-clever这类比较新的和当前内核更加契合的宏包。当前来看,还是根据TL26的当下更新模板的定理类环境更加合适。模板也要与时俱进 ;-)