81

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?

56

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}
  • 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 '18 at 20:48
  • Define for example\newcommand\answer{\ifanswers\color{red}} \let\endanswer\fi and then use \begin{answer}...\end{answer} – Marian Jan 23 at 14:43
  • 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 at 14:48
78

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

  • In your first example, why are you not simply use \newif\ifdebug, \debugtrue or \debugfalse and then use \ifdebug? – Martin Scharrer Nov 3 '11 at 23:10
  • @MartinScharrer: That solution is covered in Seamus's answer, but I can never remember the syntax of \newif so just got used to \ifdefined. – Peter Grill Nov 3 '11 at 23:24
  • Keep in mind that using the \ifdefined method will not be able to work as an include guard. – dionyziz Jun 18 '17 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? – Peter Grill Jun 19 '17 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 '17 at 12:11
9

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

8

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.

6

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.

4

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.

3

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}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.