为了简化非平凡的 beamer 框架的排版,我经常使用本地辅助宏。这在 beamer 中并不容易,因为在和\def\myfmt#1{\emph{#1}}
之间定义带有参数的宏(例如)会失败:\begin{frame}
\end{frame}
! Illegal parameter number in definition of \beamer@doifinframe.
<to be read again>
1
l.11 \end{frame}
对此常见的解决方法是在框架外部定义宏,并在组内部定义后者:
\bgroup
\def\myfmt#1{\emph{#1}}
\begin{frame}[label=problem]{A frame that uses a ,,local'' macro}
\myfmt{Slide content}
\end{frame}
\egroup
\againframe
但是,如果想要稍后(完整的 MWE)使用该框架,则此方法不起作用:
\documentclass{beamer}
\begin{document}
\bgroup
\def\myfmt#1{\emph{#1}}
\begin{frame}[label=problem]{A frame that uses a ,,local'' macro}
\myfmt{Slide content}
\end{frame}
\egroup
\bgroup
\def\myfmt#1{\color{red} #1}
\begin{frame}{Another frame that uses a ,,local'' macro}
\myfmt{Slide content}
\end{frame}
\egroup
% fails with "Undefined control sequence \myfmt"
\againframe{problem}
\end{document}
显然,只插入和\againframe
之间定义的内容——这当然是有意义的。\begin{frame}
\end{frame}
那么,我如何定义与之一起工作的“框架本地”辅助宏\againframe
?
答案1
环境frame
是一个伪环境,即实际上是\frame{ .. }
伪装的。参数存储在至少一个无参数的宏中,因此将#1
作为其参数。#
在这种情况下,您可以像往常一样尝试将 s 翻倍。在我的测试中,我需要将全部翻倍#
两次:\def\myfmt####1{\emph{####1}}
。这在第一帧中有效,但在 中无效\againframe
。显然内容在那里再次分配并导致问题。
最简单的解决方案是使用fragile
框架选项来警告beamer
此类问题并使其更frame
谨慎地处理。
\documentclass{beamer}
\begin{document}
\begin{frame}[label=noproblem,fragile]{A frame that uses a ,,local'' macro}
\def\myfmt#1{\emph{#1}}
\myfmt{Slide content}
\end{frame}
\begin{frame}[fragile]{Another frame that uses a ,,local'' macro}
\def\myfmt#1{\color{red} #1}
\myfmt{Slide content}
\end{frame}
\againframe{noproblem}
\end{document}
此外,如果您隐藏它#
,\frame
它就会起作用,例如,将您的定义放在框架外的另一个宏内,并在框架中使用该宏,但要做到这一点,就需要再次在框架外定义一个宏,这会违背目的。