0

Let's say I want to make a new environment that is a copy of the beamer class' frame, but it allows one to optionally place (something) at the end to change the behaviour of the frame. I would still like to capture the complexities of the original 'frame' environment as described in the manual: \begin{frame}<⟨overlay specification⟩>[<⟨default overlay specification⟩>][⟨options⟩]{⟨title⟩}{⟨subtitle⟩}

Is there a canonical way of doing this without getting too messy?

\documentclass{beamer}

\NewDocumentEnvironment{myframe}{d<> o o m m d() +b}{%
\begin{frame}% some conditional and expansion magic here to only include #1, #2, etc. if they are provided
~~does something with (#6)
#7
\end{frame}
}{}

\begin{document}

\end{document}

1
  • 2
    frame is not a classical environment but more like verbatim and defining new environments based on it is hard. Jan 17, 2022 at 7:29

1 Answer 1

2

Probably xparse's deprecated g-type-argument does the trick.

But you also need to check optional arguments in square brackets for leading < for cranking out default overlay specifications.

\documentclass{beamer}
\usepackage{xparse}

\makeatletter
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral\expandafter\@secondoftwo\string{\expandafter
  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
  \@secondoftwo\string}\expandafter\UD@stopromannumeral\@secondoftwo}{%
  \expandafter\UD@stopromannumeral\@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether start has a leading <
%%.............................................................................
%% \UD@CheckWhetherLeadingExplicitSpace{<Argument which is to be checked>}%
%%                                     {<Tokens to be delivered in case <argument
%%                                       which is to be checked> does have a
%%                                       leading "<"-token>}%
%%                                     {<Tokens to be delivered in case <argument
%%                                       which is to be checked> does not have a
%%                                       a leading "<"-token>}%
\@ifdefinable\UD@stopromannumeral{\chardef\UD@stopromannumeral=`\^^00}%
\newcommand\UD@Exchange[2]{#2#1}%
\newcommand\UD@CheckWhetherLeadingLower[1]{%
  \romannumeral\UD@CheckWhetherNull{#1}%
  {\expandafter\UD@stopromannumeral\UD@secondoftwo}%
  {%
    % Let's nest things into \UD@firstoftwo{...}{} to make sure they are nested in braces
    % and thus do not disturb when the test is carried out within \halign/\valign:
    \expandafter\@firstoftwo\expandafter{%
      \expandafter\expandafter\expandafter\UD@stopromannumeral
      \romannumeral\expandafter\@secondoftwo
      \string{\UD@CheckWhetherLeadingLowerB.#1<}{}%
    }{}%
  }%
}%
\@ifdefinable\UD@CheckWhetherLeadingLowerB{%
  \long\def\UD@CheckWhetherLeadingLowerB#1<{%
    \expandafter\UD@CheckWhetherNull\expandafter{\@firstoftwo{}#1}%
    {\UD@Exchange{\@firstoftwo}}{\UD@Exchange{\@secondoftwo}}%
    {\expandafter\expandafter\expandafter\UD@stopromannumeral
     \expandafter\expandafter\expandafter}%
     \expandafter\@secondoftwo\expandafter{\string}%
  }%
}%
\NewDocumentEnvironment{myframe}{d<> o o g g d()}{%
  \IfNoValueTF{#5}{\@firstofone}{\UD@Exchange{{#5}}}{%
    \IfNoValueTF{#4}{\@firstofone}{\UD@Exchange{{#4}}}{%
      \IfNoValueTF{#3}{%
        \IfNoValueTF{#2}{\UD@Exchange{[{environment=myframe,fragile}]}}%
                       {%
                          \UD@CheckWhetherLeadingLower{#2}{%
                            \UD@Exchange{[#2]}%
                          }{%
                            \UD@Exchange{[environment=myframe,fragile,#2]}%
                          }%
                       }%
      }{%
        \IfNoValueTF{#2}{%
                          % This case should never happen.
                          \UD@CheckWhetherLeadingLower{#3}{%
                            \UD@Exchange{[#3]}%
                          }{%
                            \UD@Exchange{[environment=myframe,fragile,#3]}%
                          }%
                        }%
                        {%
                          \UD@CheckWhetherLeadingLower{#2}{%
                            \UD@CheckWhetherLeadingLower{#3}{%
                              % This should not happen:
                              \UD@Exchange{[#2][#3]}%
                            }{%
                              \UD@Exchange{[#2][environment=myframe,fragile,#3]}%
                            }%
                          }{%
                            \UD@CheckWhetherLeadingLower{#3}{%
                              % This should not happen:
                              \UD@Exchange{[environment=myframe,fragile,#2][#3]}%
                            }{%
                              % This should not happen:
                              \UD@Exchange{[environment=myframe,fragile,#2][environment=myframe,fragile,#3]}%
                            }%
                          }%
                        }%
      }{%
        \IfNoValueTF{#1}{\@firstofone}{\UD@Exchange{<#1>}}{\begin{frame}}%
      }%
    }%
  }%
  \IfNoValueF{#6}{does something with (#6)}%
}{\end{frame}}
\makeatother

\begin{document}

\begin{myframe}(bla)
blubb
\end{myframe}

\end{document}

enter image description here

You must log in to answer this question.

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