为什么 \msg_fatal: 会显示一个看似不相关的错误?

为什么 \msg_fatal: 会显示一个看似不相关的错误?
\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允许的情况下尝试,但本质上这不是给出致命错误的“正确”位置。

相关内容