# Make a \NewEnviron which holds an lstlisting within a frame of beamer

I am setting up a template for a presentation on some sort of code. Thus I would like to have an environment that holds a frame (done with \usepackage{environ}) within which I have a lstlisting environment.

The minimal working example, not defined as a new environment would be the following:

\documentclass{beamer}

\usepackage{listings}

\begin{document}

\begin{frame}[fragile]
\begin{center}
\begin{minipage}{0.9\linewidth}
\begin{lstlisting}
for i=1:2:10
do something
end
\end{lstlisting}
\end{minipage}
\end{center}
\end{frame}
\end{document}


Now what I would like to achieve is something like this:

\NewEnviron{TFListing}[1][]{
\begin{frame}[fragile]{#1}
\begin{center}
\begin{minipage}{0.9\linewidth}
\begin{lstlisting}
\BODY
\end{lstlisting}
\end{minipage}
\end{center}
\end{frame}
}


Which I could then use as:

\begin{TFListing}[Title]
for i=1:2:10
do something
end
\end{TFListing}


However, the main problem is that latex does not allow reading the \BODY argument signalizing the content of the newly defined environment, since it is escaped by the \begin{lstlisting}. The benefit of such an environment would be that about eight lines of code per frame could be spared.

• This is hard, but, isn't this already a build in feature of the tcolorbox package, amongst all the other things that package can do? – daleif Feb 4 '18 at 21:27
• With \NewEnviron you lose line breaks, for instance; but the most important aspect is that the contents is absorbed as the argument to a command, so listings can no longer do its job. – egreg Feb 4 '18 at 21:28

There are a few problems with your approach:

1. With \NewEnviron, line breaks are lost.
2. The contents of such an environment is absorbed as the argument to a command and lstlisting can never appear in the argument to a command.
3. Hiding frame is bad programming anyway.

Here's a different implementation.

\documentclass{beamer}
\usetheme{Warsaw}

\usepackage{listings}

\lstnewenvironment{tflisting}[1][]
{%
\lstset{
linewidth=0.9\textwidth,
xleftmargin=0.05\textwidth,
#1
}%
}{}

\begin{document}

\begin{frame}[fragile]

\begin{tflisting}
for i=1:2:10
do something
end
\end{tflisting}

\end{frame}

\end{document}


You can also use

\begin{tflisting}[<listings options>]

• How do you mean "Hiding the frame"? Do you mean hiding it in a \NewEnviron command? – GianAndrea Müller Feb 14 '18 at 19:34
• @GianAndreaMüller Masking frame inside another environment: I don't think you need it. – egreg Feb 14 '18 at 20:01
• I see your point. I guess it's a question of taste :) Thanks a lot for your help! I could use your fix really well! – GianAndrea Müller Feb 14 '18 at 20:34
• @GianAndreaMüller I don't see why obfuscating the code just for saving a few keystrokes. – egreg Feb 14 '18 at 20:48

As far as I understand it, this is not easily possible. But at least it can partly be achieved with:

\documentclass{beamer}

\usepackage{listings}

\lstnewenvironment{TFListing}[1][]{
\lstset{caption={#1}}%
\centering\minipage{.9\textwidth}%
}{
\endminipage%
}

\begin{document}

\begin{frame}[fragile]
\begin{TFListing}[Title]
for i=1:2:10
do something
end
\end{TFListing}
\end{frame}

\end{document}


The center environment adds some spacing, but the \centering macro does not. So, maybe you have to add some vertical spacing manually.