frame in NewDocumentEnvironment

by XZS   Last Updated March 08, 2019 15:23 PM

With beamer frames, this does not work.

\newenvironment{itemframe}[1]{
  \begin{frame}{#1}
    \begin{itemize}
}{
    \end{itemize}
  \end{frame}
}

Adding fragile, environment=itemframe as an optional argument to the frame will solve the issue. But there is also an alternative that avoids making the frame fragile: Exporting everything apart from the frame environments to own commands.

\documentclass{beamer}
\usepackage{xparse}

\newenvironment{itemframe}[1]{
%\NewDocumentEnvironment{itemframe}{m}{
  \begin{frame}{#1}
    \itemframebegin
}{
    \itemframeend
  \end{frame}
}
\newcommand\itemframebegin{
  \begin{itemize}
}
\newcommand\itemframeend{
  \end{itemize}
}

\begin{document}
\begin{itemframe}{Title}
  \item A
  \item B
  \item C
\end{itemframe}
\end{document}

Now when \newenvironment is replaced with \NewDocumentEnvironment from the xparse package, as shown as a comment above, both solutions again fail with

! File ended while scanning use of \[email protected]@@body.

Is there a possibility to make a \NewDocumentEnvironment including a frame? Avoiding the fragile option is preferred.



Answers 1


Unfortunately, xparse defined environments play bad with \[email protected]@@body.

A workaround is using environ:

\documentclass{beamer}
\usepackage{xparse,environ}

\NewEnviron{itemframe}{\expandafter\doitemframe\BODY\ENDBODY}
\NewDocumentCommand{\doitemframe}{mo u{\ENDBODY}}{%
  \begin{frame}{#1}
  \IfNoValueTF{#2}{NO OPT}{OPT}
  \begin{itemize}
  #3
  \end{itemize}
  \end{frame}
}

\begin{document}
\begin{itemframe}{Title}[opt]
  \item A
  \item B
  \item C
\end{itemframe}
\end{document}

The argument list is ended by u{\ENDBODY} so that \doitemframe collects the arguments in the proper way and then you can use #3 (or whatever is the resulting argument number).

If you don't need the full force of xparse but just standard arguments, you can do

\NewEnviron{itemframe}[1]{%
  \begin{frame}{#1}
  \begin{itemize}
  \BODY
  \end{itemize}
  \end{frame}
}

With xparse release 2019-05-03 one can do as follows: +b denotes that the body of the environment will be collected (in this case as #3) before processing further.

\documentclass{beamer}
\usepackage{xparse}

\NewDocumentEnvironment{itemframe}{mo+b}
 {%
  \begin{frame}{#1}
  \IfNoValueTF{#2}{NO OPT}{OPT: #2}
  \begin{itemize}
  #3
  \end{itemize}
  \end{frame}
 }{}

\begin{document}
\begin{itemframe}{Title}[opt]
  \item A
  \item B
  \item C
\end{itemframe}
\end{document}
egreg
egreg
February 08, 2015 12:20 PM

Related Questions






Nesting Tasks within an xparse Environment

Updated September 15, 2017 01:23 AM