# Hide “tagged” frames - beamer+listings+custom xparse environments

There are various ways to hide certain parts of a Latex Beamer document, but I could not apply any of them to my rather complex setup.

The code below stems from a framework to create various forms of teaching materials - mainly in the form of beamer slides. This includes for example some custom blocks that show exercises and respective solutions respectively. The solutions can be hidden by a variable so that I can create a handout for students without solutions but can show them in my actual slides while presenting. Since the slide contents are not for a single course but are used in a modular way I want to be able to disable certain parts of the presentations to be hidden completely when some variables are set (think about bachelor vs. master level). Stuffing these optional parts into individual files is not really feasible (I'd rather write and run a preprocessor on the files than that actually).

I have tried/looked at

• beameraudience package
• comment package
• tagging package
• numerious others ways to simply "if" out.

The main problem in my implementations was (probably) that at least three components try rather unlatex things (reading source without immediately interpreting it): beamer, listings and whatever tries to hide things. So the usual outcome of my tries were something like Paragraph ended before \lst@next was complete. (not always the same but you get the idea).

As can probably be seen from my MWE I have mixed various packages that do somewhat similar things (because I usually get the code or at least ideas for some solutions from stackexchange and have for the most time no idea what really happens behind the scenes ;) I don't prefer any of the packages/approaches named above, however the existing solution block code uses \endcomment (of tagging to hide the content of the custom block environment (see MWE) thus that might be favorable to including just another package. However, if you have to change the existing code I am totally fine with that (as long as I can port it over to my actual code of course ;)

The question is: how to make the second and third frame hidden if a variable is (not) set as specified by the FIXMEs in the MWE while still allowing to toggle print_solutions?

\documentclass[english,10pt,t,xcolor={usenames,svgnames}]{beamer}

\newcommand{\slidestype}{exercise}
\newcommand{\osroot}{/home/stefanct/work/lehre/os}
\newcommand{\thesession}{1}
\usepackage{etoolbox}

% The value of this variable is usually supplied externally
\newtoggle{print_solutions}
% \toggletrue{print_solutions}
\togglefalse{print_solutions}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}

\usepackage{ifthen}

\usepackage[main=english,ngerman]{babel}

\usepackage{listings}

\usepackage{xcolor}
\usepackage{tagging} % provides \comment \endcomment
\usepackage{xparse} % For NewDocumentEnvironment, IfNoValueF etc.

\newcounter{prob}\setcounter{prob}{1}
\resetcounteronoverlays{prob}
\newcounter{solu}
\resetcounteronoverlays{solu}

% Save old block environment commands (with LetLtxMacro to support arguments)
\LetLtxMacro\origblock\block
\LetLtxMacro\endorigblock\endblock

% Introduce a new block whose title and body format can be customized
\newenvironment{formattedblock}[3]%
{%
% Force expansion of the second setbeamercolor argument by using edef
\edef\settitleformat{\noexpand\setbeamercolor{block title}{#2}}
\settitleformat
\edef\setbodyformat{\noexpand\setbeamercolor{block body}{#3}}
\setbodyformat
\begin{origblock}{#1}
}{%
\end{origblock}%
}
% Constants for the format of various block types
% No worries, the actual colors are different ;)
% Ordinary blocks (blue-ish)
\newcommand{\normalblocktitle}{bg=blue,fg=white}
\newcommand{\normalblockbody}{bg=white!92!blue,fg=black}
% Exercise blocks (green-ish)
\newcommand{\execblocktitle}{bg=green,fg=black}
\newcommand{\execblockbody}{bg=white!90!green,fg=black}
% Solution blocks (red-ish)
\newcommand{\solublocktitle}{bg=red,fg=white}
\newcommand{\solublockbody}{bg=white!90!red,fg=black}

% execblock takes one optional parameter - the title
\NewDocumentEnvironment{execblock}{ g }%
{%
\begin{formattedblock}{Exercise \theprob{}\IfNoValueF{#1}{: #1}}{\execblocktitle}{\execblockbody}%
}{%
% When done with the block manage counters
\end{formattedblock}\setcounter{solu}{\theprob}\stepcounter{prob}%
}%

\makeatletter
\iftoggle{print_solutions}{
\NewDocumentEnvironment{solublock}{ } {%
\ifbeamer@autobreak%
\else%
\pause
\fi%
\begin{formattedblock}{Solution \thesolu{}}{\solublocktitle}{\solublockbody}%
}{%
\end{formattedblock}%
}
}{%
% if print_solutions is not set we want to skip the environment including all its contents!
\NewDocumentEnvironment{solublock}{ } {\expandafter\comment}{\expandafter\endcomment}
}
\makeatother

% Reformat ordinary blocks by using this formattedblock config
\RenewDocumentEnvironment{block}{ g }%
{%
\begin{formattedblock}{#1}{\normalblocktitle}{\normalblockbody}
}{%
\end{formattedblock}%
}

\begin{document}

\begin{frame}[fragile]{untagged}
\begin{block}{just a block}
some text
\end{block}
\begin{execblock}{an exercise block}
some text
\end{execblock}
\begin{solublock}
other text
\end{solublock}
\end{frame}

% FIXME: some command or begin environment here that hides
% one frame (or if possible even multiple ones)
% based on the existence of a variable/tag
\begin{frame}[fragile]{tagged but excluded}
\begin{execblock}{Exec Title}
\begin{lstlisting}[gobble=6]
some listing
\end{lstlisting}
\end{execblock}
\begin{solublock}
\begin{lstlisting}[gobble=6]
some listing
\end{lstlisting}
\end{solublock}
\end{frame}

% FIXME: As above but this time the slide(s) should be
% enabled iff the variable/tag is set
\begin{frame}[fragile]{tagged and included}
\begin{execblock}{Exec Title}
\begin{lstlisting}[gobble=6]
some listing
\end{lstlisting}
\end{execblock}
\begin{solublock}
\begin{lstlisting}[gobble=6]
some listing
\end{lstlisting}
\end{solublock}
\end{frame}

\end{document}


Sorry if I don't use your (M)WE. I did use the following approach to print some stuff based of a value I set.

\documentclass[]{beamer}

\let\BEGIN\begin% just for matching case

\makeatletter%
\def\NirvanaOrDocument{1}%
\long\def\grab@toNirvana#1#2\END{%
\expandafter\ifnum\NirvanaOrDocument<#1\relax%
#2%
\fi%
\end}%
\newenvironment*{toNirvana}[1][1]{\grab@toNirvana{#1}}{}%
\makeatother%<<<

\begin{document}
\BEGIN{toNirvana}
\begin{frame}
Foo
\end{frame}
\END{toNirvana}

\BEGIN{toNirvana}[2]
\begin{frame}
Bar
\end{frame}
\END{toNirvana}

\BEGIN{toNirvana}[3]
\begin{frame}
Baz
\end{frame}
\END{toNirvana}

\BEGIN{toNirvana}[4]
\begin{frame}
Foobar
\end{frame}
\END{toNirvana}

\end{document}


You can use the optional argument to specify a threshold how likely it is to be displayed based on the definition of \NirvanaOrDocument. If the optional argument is greater than \NirvanaOrDocument the content of the environment is displayed.

I originally created the above environment to move parts of my presentation into an appendix. Therefore it is more complicated, than it has to be. You could as well just use the following:

\documentclass[]{beamer}

\def\NirvanaOrDocument{1}%
\newcommand*\ifToNirvana[1][1]{%
\expandafter\ifnum\NirvanaOrDocument<#1\relax%
}

\begin{document}
\ifToNirvana
\begin{frame}
Foo
\end{frame}
\fi

\ifToNirvana[2]
\begin{frame}
Bar
\end{frame}
\fi

\ifToNirvana[3]
\begin{frame}
Baz
\end{frame}
\fi

\ifToNirvana[4]
\begin{frame}
Foobar
\end{frame}
\fi

\begin{frame}
it's on
\end{frame}
\end{document}