我们都知道,在使用脆弱框架时,beamer
必须小心确保\end{frame}
命令恰好出现在行首。我理解为什么会出现这个问题:环境的内容必须写入文件,因此 Beamer 必须扫描所有内容,直到\end{frame}
收集到必须写入的标记。
但是我不明白,也找不到任何地方,为什么\end{frame}
标记序列必须正好位于行首。为什么 beamer 在寻找此标记序列时至少不能跳过行首的空格?
我认为 Beamer 无法完成这件看似简单的事情肯定有技术原因。您能总结一下这些原因吗?
答案1
用于查找帧结束的当前测试beamer
设置在\beamer@processframeline
\long\gdef\beamer@processframeline#1^^M{%
\def\beamer@test{#1}%
\ifx\beamer@test\beamer@stopframe%
\let\next=\beamer@framewritten%
\else%
\immediate\write\beamer@verbatimfileout{#1}%
\let\next=\beamer@processframeline%
\fi%
\next%
}%
正如皮特·范奥斯特鲁姆这依赖于抓取的线的性质与“参考”的性质相同(\beamer@stopframe
)。
当然,从技术上来说,这是可以解决的,只需付出额外的努力即可。例如,可以使用循环来删除抓取行开头的空格:
\documentclass{beamer}
\makeatletter
{\catcode`\^^M=12\endlinechar=-1%
\long\gdef\beamer@processframeline#1^^M{%
\edef\beamer@test{\beamer@spacestrip#1\beamer@stop}%
\ifx\beamer@test\beamer@stopframe%
\let\next=\beamer@framewritten%
\else%
\immediate\write\beamer@verbatimfileout{#1}%
\let\next=\beamer@processframeline%
\fi%
\next%
}%
}
\begingroup
\catcode`\ =12\relax%
\gdef\beamer@spacestrip#1{%
\ifx#1\beamer@stop\else%
\ifx#1 \expandafter\expandafter\expandafter\beamer@spacestrip%
\else%
\noexpand#1%
\expandafter\expandafter\expandafter\beamer@strip@end%
\fi%
\fi%
}%
\endgroup%
\def\beamer@strip@end#1\beamer@stop{\unexpanded{#1}}
\def\beamer@stop{\beamer@stop}
\makeatother
\begin{document}
\begin{frame}[fragile]
Hello world
\end{frame}
\end{document}
(标签也可以被覆盖,但由于它们无法正确粘贴到网站中,所以我省略了该代码。)
目前这被视为问题 #326在 中beamer
,并且取决于设计决策(应该和不应该跳过什么)将在下一个版本中修复。
请注意,以上内容确实允许对结束帧进行“嵌套”逐字演示,例如
\newenvironment{slide}
{\begin{frame}[fragile,environment=slide]}
{\end{frame}}
\begin{slide}{My title}
Text.
\begin{verbatim}
\end{frame}
\end{verbatim}
\end{slide}
答案2
Beamer 以脆弱(逐字)模式逐行读取帧。然后检查该行是否恰好是\end{frame}
,或者\end{xxxx}
是否environment=xxxx
给出了选项。测试使用简单的 TeX\ifx
命令完成。
显然,花费额外的精力在 前面留出额外的空格是不值得的\end
。