脆弱的 \end{frame} 破坏了 beamer 之后的评论

脆弱的 \end{frame} 破坏了 beamer 之后的评论

今天我花了比我想承认的更多的时间被代码中的一条评论打败了......

我试图在演示文稿中插入一些逐字记录,但出现了以下错误:

Runaway argument?
! File ended while scanning use of \next.

然后,将整个事情简化为 MWE,我得到了这个:

\documentclass{beamer}

\begin{document}

\begin{frame}[fragile]
Hello :)
\end{frame}% NO :(

\end{document}

并且错误仍然存​​在。

然后,当我删除评论后,\end{frame}整个事情就成功了。

有人能解释一下这里发生了什么吗?


免责声明:不,我不需要那里的评论:P

答案1

在对 的内部进行一些挖掘之后,beamer我发现答案正如埃格格指出的那样,是逐字处理器。

对于[fragile]框架,beamer使用位于的逐字处理器beamerbaseverbatim.sty。Beamer 有一个简洁的逐字处理器:

\protected\long\gdef\beamer@processframeline#1^^M{%
  \edef\beamer@test{\beamer@strip@whitespace#1\beamer@strip@stop}%
  \ifx\beamer@test\beamer@stopframe%
    \let\next=\beamer@framewritten%
  \else%
    \immediate\write\beamer@verbatimfileout{#1}%
    \let\next=\beamer@processframeline%
  \fi%
  \next%
}%

处理器是一个分隔宏,它将读取直到回车符(换行符)的所有内容。读取的内容存储在其中\beamer@test并与之进行比较\beamer@stopframe,大多数情况下,其定义为:

\xdef\beamer@stopframe{\string\\end\string\{frame\string\}}

扩展为精确的字符串\ e n d { f r a m e }

处理器会比较\beamer@test\beamer@stopframe,如果不同,则将 的内容\beamer@test写入\beamer@verbatimfileout(.vrb 文件),\next宏是\let处理器,它会递归调用自身继续读取。否则,如果\beamer@test是字符串\end{frame},处理器会正常退出。

发生该错误的原因是处理器不会忽略注释(在逐字上下文中可能需要它们!),因此处理器会\end{frame}与进行比较\end{frame}% NO :(,这显然会失败,并且会继续读取 之后的内容\end{frame}

现在可能会发生两件事:

首先,这是最后一帧,因此处理器永远找不到匹配\end{frame},并且! File ended while scanning use of \next.会出现错误并且编译停止。

第二步,也是更痛苦的一步,还有另一个框架,它将包含处理器正在寻找的机器人 。但在这种情况下,将是,它本质上是将 .vrb 文件的内容读回框架。但内容将是这样的:\end{frame}\next\let\beamer@framewritten

Hello :)
\end{frame}% NO :(
\begin{frame}
Hello again!

这会让事情变得疯狂:)

总结

请记住,孩子们,使用[fragile]镜框时,\end{frame} 必须成为仅有的行中的内容。不允许有前导空格或注释(尾随空格会被 TeX 吞噬)。

正如 samcarter 在她的评论中指出的那样,当前版本的 Beamer 允许引导尾随空格和制表符。此\beamer@strip@whitespace宏将在与 进行比较之前吃掉空格和制表符\beamer@stopframe

相关内容