\documentclass{article}
\usepackage{expl3}
\usepackage{everypage}
\ExplSyntaxOn
\AddEverypageHook { \sean_test: }
\msg_new:nnnn { test } { message }
{ this ~ is ~ a ~ rubbish ~ message }
{ it's ~ a ~ minimal ~ example }
\cs_new_protected:Npn \sean_test:
{
\typeout{++before++}
\msg_fatal:nn { test } { message }
\typeout{++after++}
}
\ExplSyntaxOff
\usepackage{mwe}
\begin{document}
\lipsum[1-1000]
\end{document}
我很惊讶我能够做出这个最小的例子,但上面会产生(许多副本)
++after++
[26]
++before++
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! Fatal test error: "message"
!
! this is a rubbish message
!
! See the test documentation for further information.
!
! For immediate help type H <return>.
!...............................................
l.23 \lipsum[1-1000]
! You can't use `\end' in internal vertical mode.
\__msg_fatal_code:nnnnnn ...l_text_tl }\tex_end:D
l.23 \lipsum[1-1000]
++after++
[27]
++before++
这生意是怎么回事?
! You can't use `\end' in internal vertical mode.
\__msg_fatal_code:nnnnnn ...l_text_tl }\tex_end:D
我尝试过引入两者\leavevmode\tex_end:D
,但\clearpage\tex_end:D
没有效果。
答案1
你不能死在那里。
您正在使用的钩子大概在输出例程中运行,该例程始终处于内部垂直模式(因为根据定义,您不在主垂直列表中),所以您不能停在那里,您需要先退出输出例程。
有可能做一些事情来尝试在内心的盒子之外死去,再死一天(引用 Paulo 的话)但不能保证 aftergroup 令牌会落到安全的地方(如果执行致命错误是安全的)
\documentclass{article}
\usepackage{expl3}
\usepackage{everypage}
\ExplSyntaxOn
\AddEverypageHook { \sean_do_test: }
\cs_new:Nn \sean_do_test:
{
\bool_if:nTF { \mode_if_inner_p: || \mode_if_horizontal_p: }
{
\group_insert_after:N \sean_do_test:
}
{
\sean_test:
}
}
\msg_new:nnnn { test } { message }
{ this ~ is ~ a ~ rubbish ~ message }
{ it's ~ a ~ minimal ~ example }
\cs_new_protected:Npn \sean_test:
{
\typeout{++before++}
\msg_fatal:nn { test } { message }
\typeout{++after++}
}
\ExplSyntaxOff
\usepackage{mwe}
\begin{document}
\lipsum[1-1000]
\end{document}
答案2
错误类别fatal
实际上是针对重大问题而设计的,几乎肯定是在加载时。在您的示例中,您最终将其放在一个框内:TeX 不允许我们在那里“退出”,因此出现错误。我们或许可以添加一个保护来检查当前模式,并且只在\end
允许的情况下尝试,但本质上这不是给出致命错误的“正确”位置。