Вот очень загадочное поведение компилятора (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
После компиляции он печатает какой-то символ альфа, хотя должен был бы печатать какой-то символ бета...! Это первое удивительное поведение.
Еще более загадочно, если я это сделаю.илииз следующих трех:
- Комментируем строку
\AtBeginDocument{\relax}
вsandbox.sty
; - Комментируем строку
\RequirePackage{unicode-math}
вsandbox.sty
; - Заменив строку
\usepackage{sandbox}
наmain.tex
основное содержимоеsandbox.sty
(т.е. три строки, являющиеся фактическим содержимым пакета),
затем он печатает некоторую бета, как изначально и ожидалось... Это кажется совершенно бессвязным! Есть ли у кого-нибудь подсказка для объяснения?...
решение1
Как отмечено в комментариях, это связано с поведением добавления в хуки. Материал добавляется в хуки, и порядок по умолчанию таков, что «более ранние» файлы получают свое содержимое хука, выполненное раньше,кромезаписи верхнего уровня (The user doc) являются последними. Мы можем увидеть это, если добавим \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.