# Selectively suppress generation of typeset output

Is it possible put TeX into a "mute" mode in which all typesetting is suppressed?

\documentclass{article}
\pagestyle{empty}
\begin{document}
\suppress
This text will not be seen in the generated document.
\enable
But this text will.
\suppress
And this text won't again.
\end{document}


The input should be processed "as usual" (maintaining counters, etc.), just without outputting anything.

EDIT: The current application is the creation of a document, in PDF format, that contains only the figures contained in a given source. However, in the end I'm interested if it's possible to mute output in a generic fashion, just the way I asked. If I wanted just to solve the problem, I would simply open the PDF in Acrobat and extract the figures.

• I once had the same question. I tried a comment environment, but unfortunately it didn't work inside document environment. – Thanos Feb 8 '13 at 13:08
• You can extract the figures directly if it's really what you want. This seems a bit like an XY problem to me... – yo' Feb 8 '13 at 13:09
• You can do it with the endfloat package, which writes out a file with extension .fff that contains the figure environments. If you don't number the figures by section, this should be enough. Please, try to better specify your aim. – egreg Feb 8 '13 at 13:12
• Deferred writes (the ones used for labels, for instance) require the page where they are to be shipped out. This is a big limitation for the "generic" problem. – egreg Feb 8 '13 at 13:37
• The answers to the following question might solve your problem: How to replace a large block of text by an empty block of the same size? (possible duplicate – Hendrik Vogt Feb 8 '13 at 13:42

Taking inspiration from syntonly.sty:

\documentclass{article}
\makeatletter
\font\dummyft@=dummy \relax
\def\suppress{%
\begingroup\par
\parskip\z@
\offinterlineskip
\baselineskip=\z@skip
\lineskip=\z@skip
\lineskiplimit=\maxdimen
\dummyft@
\count@\sixt@@n
\loop\ifnum\count@ >\z@
\textfont\count@\dummyft@
\scriptfont\count@\dummyft@
\scriptscriptfont\count@\dummyft@
\repeat
\let\selectfont\relax
\let\mathversion\@gobble
\let\getanddefine@fonts\@gobbletwo
\tracinglostchars\z@
\frenchspacing
\def\endsuppress{\par\endgroup}
\makeatother

\begin{document}
Some text.
\suppress
This text \emph{will} not be seen in the generated document.
\endsuppress
But this text will.
\suppress
And this text won't again.
\endsuppress
This will show.
\end{document}


However rules, radical bars, fraction bars and some other things (mostly math) can escape.

• Ah, yes, maths! I totally forgot about maths! – morbusg Feb 8 '13 at 14:16

One idea that occured to me was to use \nullfont:

\documentclass{article}
\long\def\suppress#1\endsuppress{%
\begingroup%
\tracinglostchars=0%
\let\selectfont=\nullfont
\nullfont #1\endgroup}
\pagestyle{empty}
\begin{document}
\suppress
This text will not be seen in the generated document.
\endsuppress
But this text will.
\suppress
And this text won't again.
\endsuppress
\end{document}


### Super-Caveats

1. Maths are not hidden
2. I don’t know LaTeX well enough to tell if I’m doing something really silly in the above.
• haha just a few seconds late :) – percusse Feb 8 '13 at 13:55
• @percuße: Ouch, I know the feeling; I’m sorry O:-). But feel free to improve this answer! – morbusg Feb 8 '13 at 13:57
• At least add \tracinglostchars=0 in order not to fill the log file with Missing character messages. – egreg Feb 8 '13 at 14:49
• Nope much better than what I intended. – percusse Feb 8 '13 at 14:51
• @tohecz: absolutely! I just love to delete lines of code! Thanks! :-D – morbusg Feb 8 '13 at 20:08

The comment package should do what you want:

...
\comment
This text will not be seen
\endcomment
But this text will!
...

• Will the commented text be processed (counters, macro definitions, ...)? – krlmlr Mar 22 '13 at 10:41

A different solution just for the figure problems.

Here's the main file, where some additions to endfloat are made; let's assume it's called main.tex:

\documentclass{book}
\usepackage{endfloat,etoolbox}
\makeatletter
\pretocmd{\@chapter}{\efloat@iwrite{fff}{\noexpand\fakestepcounter{chapter}}}{}{}
\AtBeginDocument{
\efloat@openpost{fff}
\efloat@iwrite{fff}{\noexpand\fakesetcounter{chapter}{0}}
}
\let\fakestepcounter\stepcounter
\let\fakesetcounter\setcounter
\makeatother

\begin{document}

\mainmatter
\chapter{A}
\section{SA1}

aaa

\begin{figure}
\caption{abc}\label{abc}
\end{figure}

aaa

\section{SA2}

aaa

\begin{figure}
\caption{def}\label{def}
\end{figure}

aaa

\chapter{B}
\section{SA1}

aaa

\begin{figure}
\caption{ghi}\label{ghi}
\end{figure}

aaa

\section{SA2}

aaa

\begin{figure}
\caption{jkl}\label{jkl}
\end{figure}

aaa

\end{document}


Now the auxiliary file, say doonlyfigures.tex

\documentclass{article}
\usepackage{xr,refcount,environ}

\externaldocument{main}

\makeatletter
\let\latexfigure\figure
\let\latexendfigure\endfigure
\let\figure\relax
\let\endfigure\relax
\NewEnviron{figure}{%
\vbox{
\def\label##1{\xdef\thefigure{\getrefnumber{##1}}}
\def\caption{\@dblarg\fake@caption}
\BODY
}
\let\label\@gobble
\latexfigure
\BODY
\latexendfigure}
\def\fake@caption[#1]#2{}
\let\efloatseparator\relax
\let\fakesetcounter\@gobbletwo
\let\fakestepcounter\@gobble
\makeatother

\begin{document}
\input{main.fff}
\end{document}


Similar adjustments to main.tex should be made for supporting tables as well.

This answer does not answer the question perfectly because not all input is processed as usual, which is what most of the other answers focus on. However, it seems that none of the other answers is perfectly satisfying either, mentioning that in some cases (like math mode) they can not guarantee to suppress the output. This answer takes a different approach, compromising on processing everything as usual but guaranteeing that all undesired output is suppressed.

This approach ignores everything between two macros which is not explicitly excluded. I am not expanding not-excluded macros so if an excluded macro is hidden inside of a not-excluded macro it will not be executed.

I am looking ahead with \futurelet. If the next token is the end token (\enable, as you called it) I do nothing. Otherwise I gobble the next token and call \suppress again, which again checks and gobbles tokens until reaching \enable:

\documentclass{article}

\newcommand{\suppress}{\futurelet\nexttoken\doSuppress}

\newcommand{\doSuppress}{%
\ifx \nexttoken \enable
\let\do=\relax
\else
\let\do=\suppress
\fi
\GobbleOneTokenAndCall \do
}

% I am not using \expandafter\do\@gobble because that may cause trouble if
% the next token has catcode 1 (begin group), 2 (end group) or 10 (space).
\newcommand{\GobbleOneTokenAndCall}[1]{%
\afterassignment#1%
% The space after the equals is important if you want to gobble a space.
% Without it the next token after the space would be gobbled, too.
\let\gobbledToken= %
}

% The end token.
% This won't be expanded but the replacement text should be unique.
\newcommand*{\enable}{\PackageError{suppress}{\string\enable\space without \string\suppress}{}}

\begin{document}
\suppress
This text will not be seen in the generated document.
\enable

But this text will.
\end{document}


It is easy to extend this code to not suppress certain commands like \end{document} and \begin{figure}.

The following code does not suppress the content of the figure environment, independent of whether it is after a \suppress or not. Consequently the counter for figures is increased as usual. Other counters, like the section counter, are not implemented to be increased if a \section command is \suppressed.

\documentclass{article}

% Suppress code
% =============
\usepackage{etoolbox}

\newcommand{\suppress}{\futurelet\nexttoken\doSuppress}

\newcommand{\doSuppress}{%
\ifx \nexttoken \enable
\let\do=\relax
\else\ifx \nexttoken \begin
\let\do=\suppressCheckBegin
\else\ifx \nexttoken \end
\let\do=\suppressCheckEnd
\else
\let\do=\suppress
\fi \fi \fi
\GobbleOneTokenAndCall \do
}

\newcommand{\suppressCheckBegin}[1]{% #1: environment name
\def\envName{#1}%
\ifx \envName \envNameFigure
\def\do{\beginAndSuppressAfterEnd{#1}}%
\else
\let\do=\suppress
\fi
\do
}

\newcommand{\beginAndSuppressAfterEnd}[1]{%
\begin{#1}%
\csappto{end#1}{\endgroup\suppress}%
}

\newcommand{\suppressCheckEnd}[1]{% #1: environment name
\def\envName{#1}%
\ifx \envName \envNameDocument
\def\do{\end{document}}%
\else
\let\do=\suppress
\fi
\do
}

% Note the star, which means that this macro is not \long.
% Without this \ifx would always evaluate to false
% because it would compare a \long to a not \long macro.
\newcommand*{\envNameDocument}{document}
\newcommand*{\envNameFigure}{figure}

% I am not using \expandafter\do\@gobble because that may cause trouble if
% the next token has catcode 1 (begin group), 2 (end group) or 10 (space).
\newcommand{\GobbleOneTokenAndCall}[1]{%
\afterassignment#1%
% The space after the equals is important if you want to gobble a space.
% Without it the next token after the space would be gobbled, too.
\let\gobbledToken= %
}

% The end token.
% This won't be expanded but the replacement text should be unique.
\newcommand*{\enable}{\PackageError{suppress}{\string\enable\space without \string\suppress}{}}

% Test document
% =============
\usepackage{float}
\floatplacement{figure}{htbp}

% see https://www.ctan.org/pkg/latex2e-help-texinfo, section 5.6 "Floats"
\setcounter{topnumber}{10}
\setcounter{bottomnumber}{10}
\setcounter{totalnumber}{10}

\begin{document}
\suppress
suppressed~1.1

\begin{figure}
\centering
ABC
\caption{An example}
\label{fig:abc}
\end{figure}

suppressed~1.2

\enable

\emph{not} suppressed~1.1

\begin{figure}
\centering
DEF
\caption{Another example}
\label{fig:def}
\end{figure}

\emph{not} suppressed~1.2

\suppress
suppressed~2.1

\begin{minipage}{.5\linewidth}
Environments are not a problem.
\end{minipage}

suppressed~2.2

\begin{figure}
\centering
GHI
\caption{Yet another example}
\label{fig:ghi}
\end{figure}

suppressed~2.3

\end{document}

• The question says “The input should be processed "as usual" (maintaining counters, etc.)” — does this fit? – ShreevatsaR Jul 14 at 17:39
• @ShreevatsaR good point. I think I should have made that more explicit. Please see my updated answer. – jakun Jul 14 at 18:41