如何在投影仪框架内定义带有参数的宏

如何在投影仪框架内定义带有参数的宏

为了简化非平凡的 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它就会起作用,例如,将您的定义放在框架外的另一个宏内,并在框架中使用该宏,但要做到这一点,就需要再次在框架外定义一个宏,这会违背目的。

相关内容