105

Let's say I have .tex file which is a set of problems and solutions, of which I want to make two pdf files, one which includes the solutions and one which doesn't. so I need to build the .tex file under two different modes, and specify that parts of the document be ignored under one of the modes.

This is something common in programming context. e.g. in C++ i can code

#ifdef DEBUG
  // do this additional stuff ...
#endif

How can I do something equivalent in latex?

1

7 Answers 7

84

As I mentioned here, the simplest way might be conditionals:

\newif\ifanswers
\answerstrue % comment out to hide answers
\documentclass{article}
\begin{document}
Question
\ifanswers
Answer
\fi
\end{document}
5
  • 1
    Great solution! Is there a simple way, by keeping your current method, to have answers automatically in red color (if \answerstrue, if not answers are hidden)?
    – Basj
    Apr 18, 2018 at 20:48
  • Define for example\newcommand\answer{\ifanswers\color{red}} \let\endanswer\fi and then use \begin{answer}...\end{answer}
    – Marian
    Jan 23, 2019 at 14:43
  • 1
    Btw, I've been using mdframed for this. For example \newmdenv[linecolor=cyan, linewidth=1mm, backgroundcolor=black!4, topline=false, bottomline=false, skipabove=5mm, skipbelow=3mm, innertopmargin=3mm, innerbottommargin=3mm]{solution} and \ifanswers\else\let\solution\comment \let\endsolution\endcomment\fi
    – Marian
    Jan 23, 2019 at 14:48
  • I get an error when trying this: \documentclass{article} \usepackage{xcolor} \usepackage{mdframed} \usepackage{comment} \newif\ifanswers %\answerstrue % Commenting this out gives an error message: % File ended while scanning use of \next. \newmdenv[linecolor=cyan, linewidth=1mm, backgroundcolor=black!4, topline=false, bottomline=false, skipabove=5mm, skipbelow=3mm, innertopmargin=3mm, innerbottommargin=3mm]{solution} \ifanswers\else\let\solution\comment \let\endsolution\endcomment\fi \begin{document} \begin{solution} S \end{solution} \end{document} Mar 25, 2020 at 10:06
  • In short: without color the original tip works fine, but the coloring described in comments does not. Mar 25, 2020 at 10:09
97

There are numerous ways to do this.

One way is to use \ifdefined:

\documentclass{article}
%\newcommand*{\DEBUG}{}%
\begin{document}
\ifdefined\DEBUG
    DEBUG was on
\else
   DEBUG was off
\fi
\end{document}

Another is to use a \newtoggle defined by the etoolbox package:

\documentclass{article}
\usepackage{etoolbox}

\newtoggle{DEBUG}
\toggletrue{DEBUG}
%\togglefalse{DEBUG}

\begin{document}
\iftoggle{DEBUG}{
    DEBUG was on
}{
   DEBUG was off
}
\end{document}

The same pacakge also provides a newbool with similar functionality:

\documentclass{article}
\usepackage{etoolbox}

\newbool{DEBUG}
\booltrue{DEBUG}
%\boolfalse{DEBUG}

\begin{document}
\ifbool{DEBUG}{
    DEBUG was on
}{
   DEBUG was off
}
\end{document}

See Difference between \newbool and \newtoggle from etoolbox package for a discussion of these two.


Another is to use the xstring package:

\documentclass{article}
\usepackage{xstring}

\newcommand{\DEBUG}{ON}%

\begin{document}
\IfStrEq{\DEBUG}{ON}{
    DEBUG was on
}{
    DEBUG was off
}
\end{document}

Or use the ifthen package. But do make a note of Why is the ifthen package obsolete? if considering this solution.

\documentclass{article}
\usepackage{xifthen}

\newcommand{\DEBUG}{ON}%

\begin{document}
\ifthenelse{\equal{\DEBUG}{ON}}{
    DEBUG was on
}{
    DEBUG was off
}
\end{document}

Over time I have used all the options (and stayed away from xifthen due to comments at link regarding that this package is obsolete), but tend to gravitate to \ifdefined when doing quick tests, and use etoolbox approach for more longer term solutions for on/off conditions, and the xstring approach when there are more conditions to consider.

As @Seamus mentions there is a \newif built in, but I have tended to avoid that as I did not like the syntax and had to look it up every time, but that is just a personal preference

6
  • 1
    In your first example, why are you not simply use \newif\ifdebug, \debugtrue or \debugfalse and then use \ifdebug? Nov 3, 2011 at 23:10
  • 2
    @MartinScharrer: That solution is covered in Seamus's answer, but I can never remember the syntax of \newif so just got used to \ifdefined. Nov 3, 2011 at 23:24
  • 1
    Keep in mind that using the \ifdefined method will not be able to work as an include guard.
    – dionyziz
    Jun 18, 2017 at 15:30
  • @dionyziz: Can you elaborate? Not sure I understand what you mean by "include guard" and if it is what I think then why it would not work? Jun 19, 2017 at 1:18
  • @PeterGrill When you do something like \ifdefined\DEBUG\import{xxx.tex}\fi, then this import is always done – meaning if you're importing packages with conflicting names (e.g. defining different proof envs) based on DEBUG, it won't work with a "redefined" error.
    – dionyziz
    Jun 19, 2017 at 12:11
12

The other answers address the general case. In relation to the specific problem that you describe in which you want to typeset Questions and Answers, you might like to consider the answers package which does all of the hard work for you.

MWE

I've set up a problem and shortsolution environment in what follows- the answers package writes the shortsolution to the file shortsolutions.tex, which is then included at the end of the document.

\documentclass{article}
\usepackage{answers} 
%\usepackage[nosolutionfiles]{answers}        % use this line if you want to see the answers 
                                                                                        % in the document

\newcounter{problem}
\newenvironment{problem}{\refstepcounter{problem} {\bfseries\theproblem}.\ }{}
% solution files
\Opensolutionfile{shortsolutions}
\Newassociation{shortsolution}{shortSoln}{shortsolutions}

\begin{document}

\begin{problem}
Here's a question
     \begin{shortsolution}
      Here's the answer- can put anything in here: e.g $\frac{1}{3}$
     \end{shortsolution}
\end{problem}

\begin{problem}
Here's another question
     \begin{shortsolution}
      Here's another answer- can put figures, tables- anything you like!
     \end{shortsolution}
\end{problem}
\newpage

% close the solutions files
\Closesolutionfile{shortsolutions}

% input the SHORT solutions file
\IfFileExists{shortsolutions.tex}{\input{shortsolutions.tex}}{}

\end{document}

If you toggle the lines

%\usepackage{answers} 
\usepackage[nosolutionfiles]{answers}        % use this line if you want to see the answers 

then the answers will be displayed with the questions.

screenshot

10

http://www.ctan.org/tex-archive/macros/latex/contrib/comment

From the documentation:

[Purpose:] selectively in/exclude pieces of text: the user can define new comment versions, and each is controlled separately. Special comments can be defined where the user specifies the action that is to be taken with each comment line.

7

In ConTeXt, you can use modes for conditional typesetting. Modes can either be set on the command line by passing

context --modes=<list of modes>

or using \enablemode and \disablemode. You can test if a mode is set or not using \doifmodeelse{...}{...}{...} or using \startmode or \startnotmode.

See the ConTeXt wiki for more details.

5

It depends.

For code

A normal conditional method in TeX is to use \newif\iffoo and use \iffoo .. \else ... \fi to do the test, use \footrue and \foofalse to change the state.

This is the basic conditional mechanism in both Plain TeX and LaTeX, and is used by most LaTeX packages.

It is not the LaTeX syntax, and doesn't support complex bool expressions. Then packages ifthen/xifthen, etoolbox, expl3 etc. can be used to support more complex conditions. I suggest etoolbox or expl3.

For text

Those conditions above are for general material, mostly macros and short text. However, they are not robust sometimes: you can't use unbalanced \else, \fi, \ifXXX in the branches, for very long text it may cause surprising errors. Then you can use comment, xcomment, tagging packages for longer text (but not for macros). They work in a verbatim way.

See Document configuration via tags or labels? for tagging package. It is quite user-friendly.

4

The simplest way should be like the following,

\documentclass{article}

\newenvironment{problem}[1]
{\def\temp{#1}}{%
\temp% comment this line to remove the answer.
}

\begin{document}
\begin{problem}{Garbage Collector}
What is your name?
\end{problem}
\end{document}

You must log in to answer this question.

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