这是 (Lua)LaTeX 编译器的一个非常令人费解的行为。在下面的情况下,输出取决于某些代码是放在包中还是直接放在主文件中;\relax
在文档开头请求额外的命令会改变行为;我无法确定某些神秘错误的来源……我想了解编译器内部发生了什么,从而产生这样的行为,以避免后续出现类似的不良行为!
情况如下。让以下文件main.tex
:
\documentclass{minimal}
\usepackage{sandbox}
\begin{document}
$\alpha$
\end{document}
以及以下sandbox.sty
文件:
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{sandbox}
\AtBeginDocument{\relax}
\RequirePackage{unicode-math}
\AtBeginDocument{\renewcommand\alpha{\beta}}
\endinput
编译后,它会打印一些 alpha 符号,而它应该打印一些 beta...!这是第一个令人惊讶的行为。
更神秘的是,如果我这样做任何一个以下三者之一:
\AtBeginDocument{\relax}
注释中的行sandbox.sty
;\RequirePackage{unicode-math}
注释中的行sandbox.sty
;- 用 的核心内容替换
\usepackage{sandbox}
中的行(即,这三行是包的实际内容),main.tex
sandbox.sty
然后它打印了一些 beta,正如最初预期的那样...这似乎完全不连贯!有人能解释一下吗?...
答案1
正如评论中所述,这与添加到钩子的行为有关。材料被添加到钩子中,默认顺序是“较早”的文件会更早执行其钩子内容,除了顶级条目(用户文档)位于最后。我们可以看到,如果我们添加\ShowHook{begindocument}
到输入,则得到:
-> The hook 'begindocument':
> Code chunks:
> sandbox -> \relax \renewcommand \alpha {\beta }
> fontspec-luatex -> \tl_set_eq:NN \cyrillicencoding \g_fontspec_encoding_t
l \tl_set_eq:NN \latinencoding \g_fontspec_encoding_tl \RenewDocumentCommand \o
ldstylenums {m}{\__fontspec_main_oldstylenums:n {##1}}\fontspec_maybe_setup_mat
hs:
> amsmath -> \reset@strutbox@ \MakeRobust \dddot \MakeRobust \ddddot \Umath
charnumdef \std@minus \Umathcodenum `\-\relax \Umathcharnumdef \std@equal \Umat
hcodenum `\=\relax \expandafter \let \csname overleftarrow \endcsname \@undefin
ed \expandafter \let \csname overrightarrow \endcsname \@undefined \MakeRobust
\overrightarrow \MakeRobust \overleftarrow \MakeRobust \overleftrightarrow \Mak
eRobust \underrightarrow \MakeRobust \underleftarrow \MakeRobust \underleftrigh
tarrow
> unicode-math-luatex -> \__um_define_math_chars: \tl_if_eq:onT {\g__fontsp
ec_mathrm_tl }{\rmdefault }{\__fontspec_setmathrm_hook:nn {}{}}\tl_if_eq:onT {\
g__fontspec_mathsf_tl }{\sfdefault }{\__fontspec_setmathsf_hook:nn {}{}}\tl_if_
eq:onT {\g__fontspec_mathtt_tl }{\ttdefault }{\__fontspec_setmathtt_hook:nn {}{
}}\bool_if:NF \g__um_main_font_defined_bool \__um_load_lm: \__um_setup_mathtext
: \__um_define_prime_commands: \__um_define_prime_chars: \cs_new_protected:Npn
\__um_patch_url: {\tl_put_left:Nn \Url@FormatString {\__um_switch_to:n {literal
}}\tl_put_right:Nn \UrlSpecials {\do \`{\mathchar `\`}\do \'{\mathchar `\'}\do
\${\mathchar `\$}\do \&{\mathchar `\&}}}\@ifpackageloaded {url}{\__um_patch_url
: }{}\cs_new_protected:Npn \__um_patch_mathtools_B: {\cs_set_eq:NN \MToverbrack
et \overbracket \cs_set_eq:NN \MTunderbracket \underbracket \AtBeginDocument {\
msg_warning:nn {unicode-math}{mathtools-overbracket}\cs_set:Npn \downbracketfil
l ####1####2{\tl_set:Nn \l_MT_bracketheight_fdim {.27ex}\downbracketend {####1}
{####2}\leaders \vrule \@height ####1\@depth \z@ \hfill \downbracketend {####1}
{####2}}\cs_set:Npn \upbracketfill ####1####2{\tl_set:Nn \l_MT_bracketheight_fd
im {.27ex}\upbracketend {####1}{####2}\leaders \vrule \@height \z@ \@depth ####
1\hfill \upbracketend {####1}{####2}}\cs_set_eq:NN \Uoverbracket \overbracket \
cs_set_eq:NN \Uunderbracket \underbracket \cs_set_eq:NN \overbracket \MToverbra
cket \cs_set_eq:NN \underbracket \MTunderbracket }}\@ifpackageloaded {mathtools
}{\__um_patch_mathtools_B: }{}\cs_new_protected:Npn \__um_patch_mathtools_C: {\
msg_warning:nn {unicode-math}{mathtools-colon}\DeclareDocumentCommand \dblcolon
{}{\Colon }\DeclareDocumentCommand \coloneqq {}{\coloneq }\DeclareDocumentComm
and \Coloneqq {}{\Coloneq }\DeclareDocumentCommand \eqqcolon {}{\eqcolon }}\@if
packageloaded {mathtools}{\__um_patch_mathtools_C: }{}\Umathcharnumdef \std@min
us \Umathcodenum `-\Umathcharnumdef \std@equal \Umathcodenum `=\debug_suspend:
\__um_resolve_greek: \debug_resume: \@ifpackageloaded {amsmath}{}{\__um_redefin
e_radical: }\__um_setup_active_frac: \g__um_secret_hook_tl
> Document-level (top-level) code (executed last):
> ---
> Extra code for next invocation:
> ---
> Rules:
> ---
> Execution order:
> sandbox, fontspec-luatex, amsmath, unicode-math-luatex.
<recently read> }
请注意, for 的钩子sandbox
将在 for 之前出现unicode-math
,因此后者将“获胜”以重新定义相同的条目。
钩子系统的目的是允许控制顺序。因此,你只需要添加
\DeclareHookRule{begindocument}{sandbox}{after}{unicode-math-luatex}
\DeclareHookRule{begindocument}{sandbox}{after}{unicode-math-xetex}
到您的sandbox
文件中以确保钩子代码是有序的:
> Execution order (after applying rules):
> fontspec-luatex, amsmath, unicode-math-luatex, sandbox.