16

To ease the typesetting of nontrivial beamer frames I often employ local helper macros. This is not too easy in beamer, as defining a macro with parameters (e.g., \def\myfmt#1{\emph{#1}}) between \begin{frame} and \end{frame} fails with:

! Illegal parameter number in definition of \beamer@doifinframe.
<to be read again> 
               1
l.11 \end{frame}

The commonly mentioned workaround for this is to define the macro outside of the frame together with the latter inside a group:

\bgroup
\def\myfmt#1{\emph{#1}}
\begin{frame}[label=problem]{A frame that uses a ,,local'' macro}
  \myfmt{Slide content}
\end{frame}
\egroup

This, however, does not work if one wants to use the frame with \againframe later (complete 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}

Apparently, \againframe does insert only the content that was defined between \begin{frame} and \end{frame} - which makes sense, of course.

So how can I define "frame-local" helper macros that work with \againframe?

4
  • 1
    Use the fragile option or try to double the #: \begin{frame}[label=problem]{A frame that uses a ,,local'' macro} \def\myfmt##1{\emph{##1}} \myfmt{Slide content} \end{frame} . The frame environment is a pseudo-environment, i.e. actually \frame{ .. } in disguise. The argument is stored in a parameter-less macro and therefore the #1 is taken as its argument. Jul 4, 2011 at 20:15
  • Supplement: You need to use four hashes, apparently the content is expanded twice. Using \def\myfmt####1{\emph{####1}} works for me in the frame, but not with \againframe. So using fragile seems to be the way to go. Jul 4, 2011 at 20:19
  • @Martin: That should be an answer.
    – Caramdir
    Jul 4, 2011 at 21:28
  • @Martin: I had tried it with two #, but not with four, nice :-) However, fragile seems not to help wrt to \againframe; have you tested this?
    – Daniel
    Jul 4, 2011 at 21:38

1 Answer 1

20

The frame environment is a pseudo-environment, i.e. actually \frame{ .. } in disguise. The argument is stored in at least one parameter-less macro and therefore the #1 is taken as its argument. You can try doubling the #s as usual in such cases. In my tests I needed to double all # twice: \def\myfmt####1{\emph{####1}}. This then works in the first frame, but not in the \againframe. Apparently the content is assigned there again and causes issues.

The easiest solution would be to use the fragile option for the frame which warns beamer about such issues and make it process the frame more carefully.

\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}

Also if you would hide the # from the \frame it would work, e.g. placing your definition inside another macro outside the frame and use that macro in the frame, but for doing this one would again need to define one macro outside the frame which defeats the purpose.

2
  • 1
    Thanks Martin, this works! As usual, I will wait a couple of days before accepting the answer. Comment: The only caveat with fragile is that it does not play together with allowframebreaks. However, a frame with local macros and frame-breaks that is used again with \againframe would be a pathological case anyway.
    – Daniel
    Jul 5, 2011 at 10:24
  • Very useful tip. I had the same problems with \docsvlist for sparklines inside a beamer document. Thanks.
    – drstevok
    Apr 16, 2013 at 17:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .